【Android FrameWork】第三十天:Surface创建流程解析

Android Surface创建

Surface的创建是Android图形渲染链路中最核心的跨进程协同环节,涉及应用进程(Java层)、SystemServer进程(WMS,Java层)、SurfaceFlinger进程(C++层)三方交互,且整个流程是"Java层封装调用 + C++层核心实现"的典型分层架构。

本文将以源码级视角,拆解Surface创建的完整步骤,并逐一解析Java层与C++层的具体实现逻辑。

前置核心认知

在拆解流程前,需明确Surface创建涉及的核心组件及其分层实现,这是理解Java/C++交互的关键:

层级 核心组件 语言 核心作用
应用进程-Java ViewRootImpl、Surface、Session Java 发起Surface申请,接收并封装SurfaceFlinger返回的Producer端
SystemServer-Java WMS(WindowManagerService)、SurfaceControl Java 校验窗口属性,转发Surface创建请求至SurfaceFlinger
SurfaceFlinger-C++ SurfaceFlinger、BufferQueue、Layer、IGraphicBufferProducer C++ 创建BufferQueue/显存缓冲区,生成Producer端,是Surface的核心实现层
跨进程通信 Binder(IWindowSession、ISurfaceComposer、IGraphicBufferProducer) 混合 Java层通过AIDL生成Binder代理,C++层通过Binder接口实现跨进程调用

核心结论:Java层仅负责"发起请求"和"封装结果",Surface的核心创建逻辑(BufferQueue、显存管理、Producer/Consumer构建)全部在C++层的SurfaceFlinger中实现

Surface创建全流程拆解

Surface创建的核心链路为:应用进程Java层 → SystemServer(WMS)Java层 → SurfaceFlinger C++层 → WMS Java层 → 应用进程Java层,共5个核心步骤,以下逐步骤解析。

步骤1:应用进程Java层发起Surface申请(ViewRootImpl → WMS)

触发时机

ViewRootImpl在performTraversals方法中(View绘制总入口),检测到当前Window无可用Surface时,触发relayoutWindow请求------这是应用侧发起Surface创建的起点。

Java层实现细节
  1. ViewRootImpl封装请求参数

    ViewRootImpl构建WindowManager.LayoutParams(窗口尺寸、类型、Z轴层级等),调用mWindowSession.relayout()方法,核心代码片段:

    java 复制代码
    // ViewRootImpl.java
    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, ...) {
        // 1. 封装请求参数:是否需要创建Surface、窗口尺寸、像素格式等
        int relayoutResult = mWindowSession.relayout(
            mWindow, mSeq, params,
            (int) (mView.getMeasuredWidth() * appScale + 0.5f),
            (int) (mView.getMeasuredHeight() * appScale + 0.5f),
            viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
            mWinFrame, mPendingOverscanInsets, mPendingContentInsets,
            mPendingVisibleInsets, mPendingStableInsets, mPendingOutsets,
            mPendingBackDropFrame, mPendingConfiguration, mSurfaceControl); // 关键:SurfaceControl用于接收结果
        // 2. 若返回SurfaceControl非空,初始化应用侧Surface
        if (mSurfaceControl != null && mSurfaceControl.isValid()) {
            mSurface = new Surface(mSurfaceControl); // 绑定Producer端
        }
        return relayoutResult;
    }
    • mWindowSession:是IWindowSession的Binder代理对象(应用进程→WMS的通信通道),由WMS创建并返回。
    • mSurfaceControl:空对象传入,用于接收WMS返回的、包含Producer端的SurfaceControl实例。
  2. Binder跨进程调用WMS
    IWindowSession是AIDL生成的接口,应用进程的Session.relayout()会通过Binder触发SystemServer进程中WMS的Session.relayout()方法,核心AIDL定义:

    aidl 复制代码
    // IWindowSession.aidl
    interface IWindowSession {
        int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility, int flags,
            out Rect outFrame, ..., out SurfaceControl outSurfaceControl);
    }

步骤2:SystemServer进程(WMS)Java层处理请求

WMS接收到应用的relayout请求后,先校验窗口合法性,再通过Native层接口向SurfaceFlinger发起Surface创建请求。

步骤2.1:WMS校验与参数预处理(Java层)
java 复制代码
// WindowManagerService.java
@Override
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, ..., SurfaceControl outSurfaceControl) {
    // 1. 校验窗口权限、令牌(WindowToken)、尺寸等合法性
    WindowState win = windowForClientLocked(session, window, false);
    if (win == null) throw new IllegalArgumentException("Invalid window");
    
    // 2. 若需要创建Surface,调用WindowState的relayout方法
    int res = win.relayout(attrs, requestedWidth, requestedHeight, viewVisibility, flags, ...);
    
    // 3. 将SurfaceFlinger返回的SurfaceControl写入out参数,透传给应用进程
    if (win.mSurfaceControl != null) {
        outSurfaceControl.copyFrom(win.mSurfaceControl);
    }
    return res;
}
  • WindowState:WMS中每个Window的封装对象,存储窗口属性和SurfaceControl引用。
  • 核心逻辑:WMS不直接创建Surface,仅做"权限校验 + 参数转发"。
步骤2.2:WMS通过SurfaceControl调用Native层(Java→C++)

WMS的WindowState.relayout()最终调用SurfaceControl.createSurface(),这是Java层触达SurfaceFlinger C++层的关键:

java 复制代码
// SurfaceControl.java (SystemServer进程)
public static SurfaceControl createSurface(Session session, String name, int width, int height,
        int format, int flags, SurfaceControl parent, int zOrder) {
    // 调用Native层方法,向SurfaceFlinger发起创建请求
    long ptr = nativeCreateSurface(session.mNativeClient, name, width, height, format, flags,
            parent != null ? parent.mNativeObject : 0, zOrder);
    return new SurfaceControl(session, ptr);
}
  • nativeCreateSurface:JNI方法,对应C++层的android_view_SurfaceControl_nativeCreateSurface
  • session.mNativeClient:是SurfaceComposerClient(C++)的指针,WMS通过它与SurfaceFlinger通信。
步骤2.3:WMS Native层转发请求(C++)

JNI方法最终调用SurfaceComposerClient::createSurface,向SurfaceFlinger发起跨进程请求:

cpp 复制代码
// SurfaceComposerClient.cpp (SystemServer进程Native层)
sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name, uint32_t width, uint32_t height, PixelFormat format, uint32_t flags) {
    // 1. 获取ISurfaceComposer接口(SurfaceFlinger的Binder代理)
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    // 2. 向SurfaceFlinger发起createSurface请求
    sp<IBinder> handle;
    sp<IGraphicBufferProducer> gbp; // 核心:Producer端
    status_t err = sf->createSurface(name, width, height, format, flags, &handle, &gbp);
    // 3. 封装为SurfaceControl(Native层),返回给Java层
    return new SurfaceControl(this, handle, gbp);
}
  • ISurfaceComposer:SurfaceFlinger的C++ Binder接口,是SystemServer→SurfaceFlinger的通信核心。
  • IGraphicBufferProducer:Surface的核心Producer端接口,由SurfaceFlinger创建并返回。

步骤3:SurfaceFlinger进程C++层创建Surface核心对象

这是Surface创建的"核心实现层",SurfaceFlinger接收请求后,创建BufferQueue、Layer、GraphicBuffer等核心对象,并生成Producer端。

步骤3.1:SurfaceFlinger接收createSurface请求
cpp 复制代码
// SurfaceFlinger.cpp
status_t SurfaceFlinger::createSurface(
        const String8& name, uint32_t width, uint32_t height, PixelFormat format,
        uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) {
    // 1. 校验权限(如是否允许创建窗口Surface)
    if (!checkPermission()) return PERMISSION_DENIED;
    
    // 2. 创建Layer(每个Surface对应一个Layer,管理Z轴、透明度、显存等)
    sp<Layer> layer = createLayer(name, width, height, format, flags);
    
    // 3. 获取Layer的Producer端(IGraphicBufferProducer)
    *gbp = layer->getProducer();
    *handle = layer->getHandle();
    
    return NO_ERROR;
}
  • Layer:SurfaceFlinger中对Surface的抽象,每个Window的Surface对应一个Layer,负责管理BufferQueue、Z轴层级、合成属性等。
  • 关键:Layer的创建是SurfaceFlinger的核心逻辑,包含BufferQueue的初始化。
步骤3.2:创建BufferQueue(显存缓冲区队列)

Layer的构造函数中会创建BufferQueue,这是Surface的"显存调度中枢":

cpp 复制代码
// Layer.cpp
Layer::Layer(SurfaceFlinger* flinger, const String8& name) : mFlinger(flinger) {
    // 1. 创建BufferQueue:分离Producer和Consumer端
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer); // 核心:创建双端队列
    
    // 2. 初始化Consumer端(SurfaceFlinger自身作为Consumer)
    mConsumer = new BufferLayerConsumer(consumer, mTextureName);
    mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
    mConsumer->setDefaultBufferSize(width, height);
    mConsumer->setDefaultBufferFormat(format);
    
    // 3. 保存Producer端,供返回给应用进程
    mProducer = producer;
    
    // 4. 初始化GraphicBufferAllocator(显存分配器)
    mGraphicBufferAllocator = new GraphicBufferAllocator();
}
  • BufferQueue::createBufferQueue:创建生产者(Producer)和消费者(Consumer),默认维护2~3个GraphicBuffer(双/三重缓冲)。
  • GraphicBufferAllocator:负责分配物理显存(Ashmem共享内存),避免CPU/GPU数据拷贝。
步骤3.3:封装Producer端为Binder对象

SurfaceFlinger将IGraphicBufferProducer(Producer端)封装为Binder代理对象,通过createSurface的返回值传递给WMS的Native层:

  • IGraphicBufferProducer是C++ Binder接口,继承自IBinder,支持跨进程传递。
  • 应用进程最终拿到的是该接口的Binder代理,而非实际对象(跨进程通信核心)。

步骤4:SurfaceFlinger返回结果,经WMS透传至应用进程

步骤4.1:WMS接收并封装结果(C++→Java)
  1. SurfaceFlinger将IGraphicBufferProducer(Producer)和Layer的Handle返回给WMS的SurfaceComposerClient
  2. Native层SurfaceControl封装Producer和Handle,通过JNI返回给WMS的Java层SurfaceControl
  3. WMS将Java层SurfaceControl通过relayoutoutSurfaceControl参数,透传给应用进程的ViewRootImpl。
步骤4.2:应用进程接收SurfaceControl(Java层)

ViewRootImpl接收到WMS返回的SurfaceControl后,初始化应用侧的Surface对象:

java 复制代码
// ViewRootImpl.java
mSurface = new Surface(mSurfaceControl);

步骤5:应用进程初始化Surface(Java+C++)

应用进程的Surface(Java层)是对Native层Surface(C++)的封装,核心是绑定Producer端。

步骤5.1:Java层Surface构造
java 复制代码
// Surface.java (应用进程)
public Surface(SurfaceControl surfaceControl) {
    // 调用Native方法,绑定SurfaceControl中的Producer端
    mNativeObject = nativeCreateFromSurfaceControl(surfaceControl);
    mCloseGuard.open("release");
}
步骤5.2:Native层Surface封装Producer端(C++)

JNI方法nativeCreateFromSurfaceControl最终创建应用进程Native层的Surface对象,绑定Producer端:

cpp 复制代码
// Surface.cpp (应用进程Native层)
sp<Surface> Surface::createFromSurfaceControl(const sp<SurfaceControl>& sc) {
    // 1. 从SurfaceControl中取出IGraphicBufferProducer(Producer端)
    sp<IGraphicBufferProducer> gbp = sc->getIGraphicBufferProducer();
    // 2. 创建应用侧Native层Surface,绑定Producer
    return new Surface(gbp);
}

// Surface构造函数:持有Producer端,为后续绘制做准备
Surface::Surface(const sp<IGraphicBufferProducer>& gbp) : mGraphicBufferProducer(gbp) {
    // 初始化BufferQueue相关参数(如缓冲区数量、像素格式)
    mGraphicBufferProducer->connect(new BufferProducerListener(this), NATIVE_WINDOW_API_CPU);
}
  • 至此,应用进程的Surface完成初始化:持有IGraphicBufferProducer(Producer端),具备申请GraphicBuffer、写入渲染数据的能力。

核心机制补充

1. Binder接口的跨层映射

Surface创建的跨进程通信依赖"Java AIDL + C++ Binder接口"的映射:

Java层接口 C++层接口 作用
IWindowSession - 应用→WMS的窗口请求通信
ISurfaceComposer ISurfaceComposer (C++) WMS→SurfaceFlinger的核心通信
- IGraphicBufferProducer SurfaceFlinger→应用的Producer通信

2. 显存缓冲区(GraphicBuffer)的预分配逻辑

  • SurfaceFlinger创建BufferQueue时,不会立即分配GraphicBuffer ,而是在应用进程首次调用lockCanvas()时,由Producer端向SurfaceFlinger申请空闲GraphicBuffer;
  • GraphicBuffer基于Ashmem(匿名共享内存)实现跨进程共享,应用进程写入数据后,SurfaceFlinger可直接访问,无需拷贝(零拷贝)。

3. 异常处理:Surface创建失败的兜底逻辑

  • WMS侧:若窗口属性非法(如尺寸为0、无权限),返回空SurfaceControl,应用进程mSurface为null,触发SurfaceHolder.Callback.surfaceDestroyed
  • SurfaceFlinger侧:若显存不足,创建Layer失败,返回错误码,WMS会通知应用进程重新发起请求。

常见问题

1. 为什么Surface创建是跨进程的?

  • Surface的核心是显存缓冲区(GraphicBuffer),由GPU/显示硬件管理,SurfaceFlinger是系统级显存管理者(运行在独立进程),必须由它统一分配和管理显存;
  • 多应用的Surface需要SurfaceFlinger统一合成(按Z轴层级),因此Surface的创建必须由SurfaceFlinger主导。

2. Java层的Surface和C++层的Surface有什么区别?

  • Java层android.view.Surface:仅为Native层Surface的封装,提供lockCanvas()/unlockCanvasAndPost()等上层API;
  • C++层android::Surface:核心实现层,持有IGraphicBufferProducer,负责与BufferQueue交互、申请GraphicBuffer。

3. SurfaceControl的作用是什么?

  • SurfaceControl是"Surface的控制器",Java/C++层均有实现,核心作用是:
    1. 封装IGraphicBufferProducer(Producer端);
    2. 管理Surface的属性(如尺寸、透明度、Z轴层级);
    3. 作为应用/WMS/SurfaceFlinger之间传递Surface的载体。

总结

Surface的创建流程是Android分层架构的典型体现:

  1. Java层(应用/WMS) 负责"发起请求、校验参数、封装结果",是面向开发者的上层抽象;
  2. C++层(SurfaceFlinger) 负责"创建BufferQueue、分配显存、生成Producer端",是Surface的核心实现层;
  3. 跨进程通信依赖Binder,IGraphicBufferProducer是连接应用进程与SurfaceFlinger的核心接口,也是Surface的本质。
相关推荐
元亓亓亓5 小时前
考研408--操作系统--day8--操作系统--虚拟内存&请求分页&页面置换/分配
android·java·开发语言·虚拟内存
有位神秘人6 小时前
Android的Compose系列之文本TextView
android
Engineer-Jsp6 小时前
Flutter 开发 Android 原生开发神器 flutter_api_stub
android·flutter
惟恋惜6 小时前
Jetpack Compose 多页面架构实战:从 Splash 到底部导航,每个 Tab 拥有独立 ViewModel
android·ui·架构·android jetpack
ab_dg_dp6 小时前
Android bugreportz 源码分析
android
木风小助理7 小时前
如何破解 MySQL 死锁?核心原则与实操方法
android
小吴学不废Java7 小时前
MySQL慢查询日志分析
android·adb
TechMix7 小时前
【用法总结】抓取main_log、events_log、kernel_log日志的方法
android