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 渲染流水线的核心基础。

相关推荐
高远-临客2 小时前
unity IL2CPP模式下中使用UMP插件打包后无法播放视频监控报错问题解决方案
android·unity·音视频
装不满的克莱因瓶2 小时前
Windows下安装Dart
android·flutter·dart·移动端
Yao_YongChao2 小时前
adb wifi连接Android手机
android·adb·智能手机·无线连接手机·wifi连接手机
安果移不动2 小时前
git Cherry-Pick合并分支上的某些commits-》Android studio
android·git·android studio
灵感菇_3 小时前
Android Broadcast全面解析
android·广播·四大组件
byc3 小时前
Android 存储目录<内部存储,外部存储app专属,外部存储公共>
android·面试
RollingPin3 小时前
React Native与Flutter的对比
android·flutter·react native·ios·js·移动端·跨平台开发
刘大浪3 小时前
Android studio 开发将gradle 从c盘迁移至自定义盘
android·ide·android studio
装不满的克莱因瓶4 小时前
【2026最新最全】Android Studio安装教程
android·ide·flutter·app·android studio·移动端