Android 12 中 App 与 SurfaceFlinger(SF)的 Vsync 通信机制

Vsync(垂直同步)是 Android 系统渲染流水线的核心机制,负责协调 App 绘制与屏幕刷新的节奏。在 Android 12 中,App 与 SurfaceFlinger(SF,系统合成服务)之间的 Vsync 通信依赖两套核心通道:Binder 通信 (App 向 SF 发起 Vsync 请求)和 BitTube 本地套接字(SF 向 App 下发 Vsync 事件)。本文将详细拆解二者的连接建立流程与核心逻辑。

一、核心通信通道概述

App 与 SF 之间的 Vsync 交互分为两个核心环节:

  1. Binder 通道(IDisplayEventConnection):App 主动向 SF 发起 Vsync 请求的 "控制通道",是双向的跨进程通信接口;
  2. BitTube 套接字:SF 向 App 推送 Vsync 事件的 "数据通道",基于本地 socketpair 实现,为 SF 发、App 收的单向通信,App 会将其文件描述符(fd)加入线程 Looper 监听事件。

二、App 侧 Vsync 连接初始化流程

App 侧的 Vsync 交互核心封装是 Choreographer(线程单例),通常绑定主线程(需 Looper 支持);ViewRootImpl 是触发 Vsync 连接建立的起点。

1. 上层初始化:ViewRootImpl → Choreographer

ViewRootImpl 是 App 界面渲染的根节点,其创建时会获取 Choreographer 实例,触发 Vsync 连接的初始化:

复制代码
// ViewRootImpl.java
public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
                    boolean useSfChoreographer) {
    // ...
    mChoreographer = Choreographer.getInstance(); // 获取线程单例的Choreographer
    // ...
}

// Choreographer.java
public static Choreographer getInstance() {
    return sThreadInstance.get(); // 线程级ThreadLocal单例
}

private static final ThreadLocal<Choreographer> sThreadInstance =
        new ThreadLocal<Choreographer>() {
    @Override
    protected Choreographer initialValue() {
        Looper looper = Looper.myLooper();
        if (looper == null) { // Choreographer依赖Looper(需监听套接字事件)
            throw new IllegalStateException("The current thread must have a looper!");
        }
        // 创建Choreographer,指定Vsync源为APP
        Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
        return choreographer;
    }
};

private Choreographer(Looper looper, int vsyncSource) {
    mLooper = looper;
    mHandler = new FrameHandler(looper);
    // 创建FrameDisplayEventReceiver,封装Vsync事件接收逻辑
    mDisplayEventReceiver = new FrameDisplayEventReceiver(looper, vsyncSource);
    // 初始化回调队列(处理Vsync触发的绘制回调)
    mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
    for (int i = 0; i <= CALLBACK_LAST; i++) {
        mCallbackQueues[i] = new CallbackQueue();
    }
}

final class FrameDisplayEventReceiver extends DisplayEventReceiver {
    public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
        super(looper, vsyncSource, 0);
    }
}

public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) {
    mMessageQueue = looper.getQueue();
    // 调用Native层初始化,建立与SF的连接
    mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), 
            mMessageQueue, vsyncSource, eventRegistration);
}

2. Native 层初始化:建立 Binder + BitTube 连接

DisplayEventReceivernativeInit 会进入 Native 层,完成与 SF 的连接建立,核心链路在 android_view_DisplayEventReceiver.cppDisplayEventDispatcher.cpp 中:

复制代码
// android_view_DisplayEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj,
                        jint vsyncSource, jint eventRegistration) {
    // 创建NativeDisplayEventReceiver实例
    sp<NativeDisplayEventReceiver> receiver =
            new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource,
                                           eventRegistration);
    // 初始化连接(Binder + BitTube)
    status_t status = receiver->initialize(); 
    return reinterpret_cast<jlong>(receiver.get());
}

// NativeDisplayEventReceiver继承自DisplayEventDispatcher,封装调度逻辑
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
                                                       const sp<MessageQueue>& messageQueue,
                                                       jint vsyncSource, jint eventRegistration)
      : DisplayEventDispatcher(messageQueue->getLooper(),
                               static_cast<ISurfaceComposer::VsyncSource>(vsyncSource),
                               static_cast<ISurfaceComposer::EventRegistration>(eventRegistration)),
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mMessageQueue(messageQueue) {}

// DisplayEventDispatcher.cpp
DisplayEventDispatcher::DisplayEventDispatcher(
        const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
        ISurfaceComposer::EventRegistrationFlags eventRegistration)
      : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
    ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}

// DisplayEventReceiver核心逻辑:与SF建立Binder连接+创建BitTube
DisplayEventReceiver::DisplayEventReceiver(
        ISurfaceComposer::VsyncSource vsyncSource,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr) {
        // 1. 通过Binder调用SF的createDisplayEventConnection,建立IDisplayEventConnection连接
        mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
        if (mEventConnection != nullptr) {
            // 2. 创建BitTube本地套接字(App侧接收端)
            mDataChannel = std::make_unique<gui::BitTube>();
            // 3. 从SF侧获取套接字fd,绑定到当前BitTube
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

// 将BitTube的fd加入Looper监听,等待SF下发Vsync事件
status_t DisplayEventDispatcher::initialize() {
    status_t result = mReceiver.initCheck();
    if (mLooper != nullptr) {
        // 监听套接字的INPUT事件(SF下发Vsync时触发)
        int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
    }
    return OK;
}

三、SF 侧 Vsync 连接的建立流程

SF 侧负责管理所有 App 的 Vsync 连接,核心封装是 EventThread(独立线程处理 Vsync 事件分发),通过 EventThreadConnection 维护与单个 App 的连接。

1. SF 侧 Binder 调用处理:创建连接实例

App 调用 sf->createDisplayEventConnection 后,SF 侧的处理链路如下:

复制代码
// SurfaceFlinger.cpp
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
        ISurfaceComposer::VsyncSource vsyncSource,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}    

// Scheduler.cpp
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
        ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
}

sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    // 由EventThread创建具体的连接实例
    return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}

// EventThread.cpp
sp<EventThreadConnection> EventThread::createEventConnection(
        ResyncCallback resyncCallback,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
    // 创建EventThreadConnection,封装与单个App的连接
    return new EventThreadConnection(const_cast<EventThread*>(this),
                                     IPCThreadState::self()->getCallingUid(),
                                     std::move(resyncCallback), eventRegistration);
}

2. 连接注册与 BitTube fd 绑定

EventThreadConnection 创建后会完成两件核心事:注册到 EventThread 的连接队列、向 App 暴露 BitTube 的 fd:

复制代码
// EventThreadConnection构造函数:创建BitTube套接字(SF侧发送端)
EventThreadConnection::EventThreadConnection(
        EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback,
        ISurfaceComposer::EventRegistrationFlags eventRegistration)
      : resyncCallback(std::move(resyncCallback)),
        mOwnerUid(callingUid),
        mEventRegistration(eventRegistration),
        mEventThread(eventThread),
        mChannel(gui::BitTube::DefaultSize) {} // 创建SF侧的BitTube

// 首次引用时,将连接注册到EventThread的队列
void EventThreadConnection::onFirstRef() {
    mEventThread->registerDisplayEventConnection(this);
}

// EventThread保存所有App的连接
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
    mDisplayEventConnections.push_back(connection); // 加入连接队列,用于后续分发Vsync
    mCondition.notify_all();
    return NO_ERROR;
}

// 向App侧传递BitTube的fd(App侧绑定后即可监听SF的Vsync事件)
status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
    outChannel->setReceiveFd(mChannel.moveReceiveFd());
    outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd())));
    return NO_ERROR;
}

四、核心总结

  1. 连接双核心
    • Binder 通道(IDisplayEventConnection):App 向 SF 发起 Vsync 请求的控制通道,SF 侧通过 EventThread 管理所有 App 连接;
    • BitTube 通道:SF 向 App 下发 Vsync 事件的单向数据通道,App 将其 fd 加入线程 Looper 监听事件,保证事件能触发绘制回调。
  2. Choreographer 特性:线程单例(默认主线程),依赖 Looper 才能工作(需监听 BitTube 事件),是 App 侧 Vsync 事件的核心封装。
  3. SF 侧核心逻辑EventThread 维护所有 App 的 EventThreadConnection 连接,Vsync 信号到达时,通过 BitTube 向所有注册的 App 下发事件。

整个流程实现了 App 与 SF 之间 Vsync 请求与事件的高效通信,是 Android 渲染流水线的核心基础。

相关推荐
Kapaseker3 小时前
你不看会后悔的2025年终总结
android·kotlin
alexhilton6 小时前
务实的模块化:连接模块(wiring modules)的妙用
android·kotlin·android jetpack
ji_shuke6 小时前
opencv-mobile 和 ncnn-android 环境配置
android·前端·javascript·人工智能·opencv
sunnyday04268 小时前
Spring Boot 项目中使用 Dynamic Datasource 实现多数据源管理
android·spring boot·后端
幽络源小助理9 小时前
下载安装AndroidStudio配置Gradle运行第一个kotlin程序
android·开发语言·kotlin
inBuilder低代码平台10 小时前
浅谈安卓Webview从初级到高级应用
android·java·webview
豌豆学姐10 小时前
Sora2 短剧视频创作中如何保持人物一致性?角色创建接口教程
android·java·aigc·php·音视频·uniapp
白熊小北极10 小时前
Android Jetpack Compose折叠屏感知与适配
android
HelloBan10 小时前
setHintTextColor不生效
android
洞窝技术12 小时前
从0到30+:智能家居配网协议融合的实战与思考
android