Vsync(垂直同步)是 Android 系统渲染流水线的核心机制,负责协调 App 绘制与屏幕刷新的节奏。在 Android 12 中,App 与 SurfaceFlinger(SF,系统合成服务)之间的 Vsync 通信依赖两套核心通道:Binder 通信 (App 向 SF 发起 Vsync 请求)和 BitTube 本地套接字(SF 向 App 下发 Vsync 事件)。本文将详细拆解二者的连接建立流程与核心逻辑。
一、核心通信通道概述
App 与 SF 之间的 Vsync 交互分为两个核心环节:
- Binder 通道(IDisplayEventConnection):App 主动向 SF 发起 Vsync 请求的 "控制通道",是双向的跨进程通信接口;
- 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 连接
DisplayEventReceiver 的 nativeInit 会进入 Native 层,完成与 SF 的连接建立,核心链路在 android_view_DisplayEventReceiver.cpp、DisplayEventDispatcher.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;
}
四、核心总结
- 连接双核心 :
- Binder 通道(IDisplayEventConnection):App 向 SF 发起 Vsync 请求的控制通道,SF 侧通过
EventThread管理所有 App 连接; - BitTube 通道:SF 向 App 下发 Vsync 事件的单向数据通道,App 将其 fd 加入线程 Looper 监听事件,保证事件能触发绘制回调。
- Binder 通道(IDisplayEventConnection):App 向 SF 发起 Vsync 请求的控制通道,SF 侧通过
- Choreographer 特性:线程单例(默认主线程),依赖 Looper 才能工作(需监听 BitTube 事件),是 App 侧 Vsync 事件的核心封装。
- SF 侧核心逻辑 :
EventThread维护所有 App 的EventThreadConnection连接,Vsync 信号到达时,通过 BitTube 向所有注册的 App 下发事件。
整个流程实现了 App 与 SF 之间 Vsync 请求与事件的高效通信,是 Android 渲染流水线的核心基础。