前言
在 native DisplayEventReceiver 通过 sp< IDisplayEventConnection > mEventConnection AIDL 获取 SurfaceFlinger 服务代理,调用 IDisplayEventConnection 的函数实现。而前文分析到 class EventThreadConnection : public gui::BnDisplayEventConnection 实现了IDisplayEventConnection 的接口函数。
因此,EventThreadConnection 就是此次学习的目标,鉴于EventThreadConnection 定义在 EventThread 又是 SurfaceFlinger 进程中运行的,这又和 通过 SurfaceFlinger 服务代理获取 mEventConnection 实例可以达成闭环。
EventThread 一个类对象,其中包含class EventThreadConnection、class EventThread类对象、class EventThread内部继承者。所以,本次将依据上面的几个部分进行分开整理。路径:frameworks/native/services/surfaceflinger/Scheduler。
1 EventThreadConnection
EventThreadConnection 表示一个客户端连接,通常是 Java 层的 DisplayEventReceiver 对应到 native 实现;每个连接都有独立的 BitTube 通信管道;提供事件接收与发送接口。
1.1 关系图谱
IDisplayEventConnection.aidl (Binder接口定义)
│ AIDL 自动生成
▼
BnDisplayEventConnection(Binder服务端Stub)
▲
│ 服务端实现代理对象
EventThreadConnection : public BnDisplayEventConnection
│ 调用
▼
EventThread : public android::EventThread
在 DisplayEventReceiver 中,通过 ISurfaceComposer 获取 SurfaceFlinger 服务代理,通过 createDisplayEventConnection 拿到 IDisplayEventConnection代理,实际指向 EventThreadConnection。EventThreadConnection又操作 EventThread。由此,完成从AP进程——>SurfaceFlinger 进程。
1.2 头文件解析
EventThreadConnection 的头文件部分是定义在EventThread.h中的,源码如下:
class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback,
EventRegistrationFlags eventRegistration = {});
virtual ~EventThreadConnection();
virtual status_t postEvent(const DisplayEventReceiver::Event& event);
// binder 指向代理端的函数
// -----------》 start
binder::Status stealReceiveChannel(gui::BitTube* outChannel) override;
binder::Status setVsyncRate(int rate) override;
binder::Status requestNextVsync() override; // asynchronous
binder::Status getLatestVsyncEventData(ParcelableVsyncEventData* outVsyncEventData) override;
// -----------》 end
// Called in response to requestNextVsync.
const ResyncCallback resyncCallback;
VSyncRequest vsyncRequest = VSyncRequest::None; // 枚举类型:VSyncRequest
const uid_t mOwnerUid;
const EventRegistrationFlags mEventRegistration;
/** The frame rate set to the attached choreographer. */
Fps frameRate;
private:
virtual void onFirstRef();
EventThread* const mEventThread; // EventThread 实例
std::mutex mLock;
gui::BitTube mChannel GUARDED_BY(mLock); // BitTube 管道
std::vector<DisplayEventReceiver::Event> mPendingEvents;
};
- EventThread* const mEventThread - 事件处理线程EventThread
- gui::BitTube mChannel - 进程间通信的管道,这里用于surfaceFlinger -> native侧ap进程的通信
- resyncCallback - 封装函数
1.3 核心函数
1.3.1 构造函数
EventThreadConnection 是每个应用与 SurfaceFlinger 中 EventThread 通信的表示单位,封装了 VSync 接收的上下文,包括接收通道、事件类型、所有者 UID 等。
EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
ResyncCallback resyncCallback,
EventRegistrationFlags eventRegistration)
: resyncCallback(std::move(resyncCallback)),
mOwnerUid(callingUid),
mEventRegistration(eventRegistration),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
(1)参数解释
| 参数名 | 类型 | 说明 |
|---|---|---|
eventThread | EventThread* | 当前连接所属的 EventThread 对象,用于注册、唤醒等操作 |
callingUid | uid_t | 创建该连接的调用者 UID,用于权限管理、节流等用途 |
resyncCallback | std::function<void()> | 应用调用 requestNextVsync() 后触发的回调,用于同步状态 |
eventRegistration | EventRegistrationFlags | 表示当前连接注册的事件类型(VSync、Hotplug、ModeChange等) |
(2)变量初始化
| 成员变量 | 含义 |
|---|---|
resyncCallback | 保存请求 vsync 后的回调函数(通常用于触发后续调度) |
mOwnerUid | 当前连接所属的 UID |
mEventRegistration | 当前连接希望订阅的事件类型 |
mEventThread | 回指所属的 EventThread,用于注册请求、回调、事件发送等 |
mChannel | 使用 BitTube 创建通信通道(socketpair),与应用侧 DisplayEventReceiver 通信 |
(3)BitTube 的作用
mChannel(gui::BitTube::DefaultSize)
- BitTube 是 Android native 层的一个轻量级 socket 封装类;
- 底层使用 socketpair(AF_UNIX, SOCK_SEQPACKET) 创建;
- 一端留在 SF 中用于 sendObject(),一端通过 stealReceiveChannel() 传递给应用;
- 应用层的 DisplayEventReceiver 使用 read() 接收 VSync 事件。
1.3.2 关键方法
EventThreadConnection 负责维护 App 与 SurfaceFlinger 之间的一条 VSync 事件连接。主要作用包括:
| 方法名 | 作用 | 触发方 |
|---|---|---|
onFirstRef() | 注册到 EventThread 中 | 构造后自动 |
stealReceiveChannel() | 把 BitTube fd 给 App | Java 初始化阶段 |
setVsyncRate() | 设置 VSync 频率 | Java 控制 |
requestNextVsync() | 请求下一帧的 VSync | App 调用 Choreographer::doFrame() 前 |
getLatestVsyncEventData() | 获取最新 VSync 时间数据 | App 调用时 |
postEvent() | 将事件通过 BitTube 发送给应用 | EventThread 调用 |
(1) onFirstRef
调用 EventThreadConnection 的构造方法创建实例对象的时候,在 DisplayEventReceiver 头文件中可以看到成员变量 mEventConnection 是 sp<> 修饰的(如:sp< IDisplayEventConnection > mEventConnection),这是在 Android 中 Google 实现的一种强引用的智能指针,并且 EventThreadConnection 类的最顶层父类是 RefBase 类,因此在 EventThreadConnection 初始化后将自动回调其实现的 onFirstRef() 方法。
【注】使用 fromExisting(this) 把裸指针转成 sp< T >,是 RefBase 系对象的常见技巧。
void EventThreadConnection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
// 将新构建的 EventThreadConnection 也就是把自己注册到 EventThread
mEventThread->registerDisplayEventConnection(sp<EventThreadConnection>::fromExisting(this));
}
(2) stealReceiveChannel
DisplayEventReceiver初始化的时候会将 SurfaceFlinger 进程中服务端创建的 gui::BitTube 对象赋值给应用进程端空的 gui::BitTube 对象,建立 app 应用进程和 SurfaceFlinger 进程之间的通道。就是通过sp< IDisplayEventConnection > mEventConnection # stealReceiveChannel函数执行设置的,其方法实现则是在此处。
binder::Status EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
std::scoped_lock lock(mLock);
if (mChannel.initCheck() != NO_ERROR) {
return binder::Status::fromStatusT(NAME_NOT_FOUND);
}
outChannel->setReceiveFd(mChannel.moveReceiveFd()); // 获取服务端gui::BitTube对象的文件描述mReceiveFd,设置到应用进程端
outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd()))); // 获取服务端gui::BitTube对象的文件描述mSendFd,设置到应用进程端
return binder::Status::ok();
}
(3) setVsyncRate
设置当前连接所需的 VSync 频率(0 表示关闭、1 表示每帧触发、n 表示每 n 帧触发一次)。本质上是控制 EventThread 是否定期向该连接分发 VSync 事件。
binder::Status EventThreadConnection::setVsyncRate(int rate) {
mEventThread->setVsyncRate(static_cast<uint32_t>(rate),
sp<EventThreadConnection>::fromExisting(this));
return binder::Status::ok();
}
(4) requestNextVsync
应用调用 Choreographer::postCallback 时最终会走到这里,发起一次「异步的单次 VSync 请求」。
binder::Status EventThreadConnection::requestNextVsync() {
ATRACE_CALL();
mEventThread->requestNextVsync(sp<EventThreadConnection>::fromExisting(this)); // 调用 EventThread 的 requestNextVsync() 请求 VSync 信号
return binder::Status::ok();
}
(5) postEvent
将事件通过 BitTube 发送给应用。由 EventThread 调用,用于将一个 VSync/Hotplug/ModeChange 等事件通过 BitTube 写入给对应应用。对于 FrameRateOverride 类型的事件,会临时缓存在 mPendingEvents 中直到 flush。
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
constexpr auto toStatus = [](ssize_t size) {
return size < 0 ? status_t(size) : status_t(NO_ERROR);
};
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
mPendingEvents.emplace_back(event);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
return status_t(NO_ERROR);
}
auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
mPendingEvents.size());
mPendingEvents.clear();
return toStatus(size);
}
auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
return toStatus(size);
}
1.4 VSyncRequest
描述客户端请求 VSync 的方式:
- None:当前无请求;
- Single:一次性唤醒,通常用于 scheduleVsync();
- Periodic:周期性 VSync;
后续值用于自定义周期控制。
enum class VSyncRequest {
None = -2, // 初始值;表示当前没有 VSync 请求
// Single wakes up for the next two frames to avoid scheduler overhead
Single = -1, // 接下来的两帧中单独唤醒,以避免调度程序开销太大;表示这是一次性 VSync 请求(请求一次,接收一次)
// SingleSuppressCallback only wakes up for the next frame
SingleSuppressCallback = 0,
Periodic = 1, // 后续请求的是周期性信号;表示是周期性 VSync 请求(请求一次可以一直接收)
// Subsequent values are periods.
};
2 EventThread定义
EventThread 负责接收来自 硬件 VSync 信号调度器(VsyncSchedule) 的回调,然后遍历它所管理的多个 EventThreadConnection(一个 App 对应一个),根据 App 的设置(如是否启用、频率等)决定是否通过 BitTube 投递事件。
2.1 EventThread 类继承关系
EventThread头文件中可以看到 class EventThread : public android::EventThread,在内部分别定义两个EventThread对象,其中一个为抽象类,内部定义虚函数,命名空间为android;另一个EventThread 对象继承前述抽象类,实现其虚函数,命名空间为impl。实际上是一个 Android 自己的类,定义在同一目录下,非 POSIX 的线程类。主逻辑通过 std::thread mThread 来调度。两个namespace关系如下:
namespace android {
class EventThread ...
namespace impl {
class EventThread : public android::EventThread ...
}
}
故而,在实现逻辑定义时显示指明android::EventThread。删减后源码如下:
class EventThread {
public:
virtual ~EventThread();
virtual sp<EventThreadConnection> createEventConnection(
ResyncCallback, EventRegistrationFlags eventRegistration = {}) const = 0;
// ... 省略
virtual void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) = 0;
};
2.2 EventThread 定义
EventThread 内部类定义的删减源码如下:
class EventThread : public android::EventThread {
public:
// 内部类型别名
using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; // 用于动态节流(如后台 App 降低 VSync 频率)
using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>; // 用于查询指定 UID 的期望 VSync 周期
// ... 省略override函数定义
private:
friend EventThreadTest;
// 当前事件线程负责的所有连接列表(一个连接对应一个 App)
using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;
// 构建传入给 VSyncDispatch 的回调函数,用于注册 EventThread 的处理逻辑(vsync 到来时触发该 callback)
scheduler::VSyncDispatch::Callback createDispatchCallback();
// Returns the old registration so it can be destructed outside the lock to
// avoid deadlock.
scheduler::VSyncCallbackRegistration onNewVsyncScheduleInternal(
std::shared_ptr<scheduler::VsyncSchedule>) EXCLUDES(mMutex);
const char* const mThreadName;
TracedOrdinal<int> mVsyncTracer;
TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex);
std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex);
// mVsyncSchedule 表示当前线程监听的 VSync 信号源
std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule GUARDED_BY(mMutex);
//
TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now();
// mVsyncRegistration 是注册后的回调绑定
scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex);
frametimeline::TokenManager* const mTokenManager;
const ThrottleVsyncCallback mThrottleVsyncCallback;
const GetVsyncPeriodFunction mGetVsyncPeriodFunction;
std::thread mThread; // 子线程: 真正处理 VSync 消息分发的主循环线程
// mMutex & mCondition : 线程的休眠与唤醒控制
mutable std::mutex mMutex;
mutable std::condition_variable mCondition;
// App 在初始化 DisplayEventReceiver 时,会创建一个 EventThreadConnection,通过 registerDisplayEventConnection 注册到这里
std::vector<wp<EventThreadConnection>> mDisplayEventConnections GUARDED_BY(mMutex);
// 当前待投递的事件队列,由 VSync 驱动后填入
std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
// VSYNC state of connected display.
struct VSyncState {
explicit VSyncState(PhysicalDisplayId displayId) : displayId(displayId) {}
const PhysicalDisplayId displayId; // 当前物理显示设备 ID
// Number of VSYNC events since display was connected.
uint32_t count = 0; // VSync 计数
// True if VSYNC should be faked, e.g. when display is off.
bool synthetic = false; // 是否使用 fake VSync(如屏幕关闭时模拟)等信息
};
// TODO(b/74619554): Create per-display threads waiting on respective VSYNC signals,
// and support headless mode by injecting a fake display with synthetic VSYNC.
// 记录当前物理显示设备 ID、VSync 计数、是否使用 fake VSync(如屏幕关闭时模拟)等信息。
std::optional<VSyncState> mVSyncState GUARDED_BY(mMutex);
// State machine for event loop.
enum class State {
Idle, // 等待唤醒
Quit, // 线程即将退出
SyntheticVSync, // 通过定时器模拟 VSync(屏幕关闭时)
VSync, // 正常 VSync 到来
};
State mState GUARDED_BY(mMutex) = State::Idle;
static const char* toCString(State);
};
3 EventThread 初始化
3.1 构造函数
源码如下
EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
android::frametimeline::TokenManager* tokenManager,
ThrottleVsyncCallback throttleVsyncCallback,
GetVsyncPeriodFunction getVsyncPeriodFunction,
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration)
: mThreadName(name), // 初始化线程名字
mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0), // tracing 标签,供调试时识别
mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration), // 初始化 work 时间
mReadyDuration(readyDuration), // 初始化 ready 时间
mVsyncSchedule(std::move(vsyncSchedule)), // 提供 VSync 信号的调度器
//step 1: mVsyncSchedule->getDispatch() 获取当前使用的 VSync 分发器(可以是硬件,也可以是模拟的)。
//step 2: createDispatchCallback() 创建一个绑定到该线程的 callback 函数。
//step 3: mVsyncRegistration 会自动将 callback 注册进 VSync 调度器中。
//step 4: 当 VSync 信号产生时,这个 callback 就会被触发,从而启动事件分发。
mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
mTokenManager(tokenManager),
mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
"getVsyncPeriodFunction must not be null");
// 创建线程,进入 threadMain() 方法,是事件分发主循环
mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
threadMain(lock);
});
// 设置线程名,如 "Vsync-app",便于 systrace、调试定位
pthread_setname_np(mThread.native_handle(), mThreadName);
pid_t tid = pthread_gettid_np(mThread.native_handle());
// Use SCHED_FIFO to minimize jitter
constexpr int EVENT_THREAD_PRIORITY = 2;
struct sched_param param = {0};
param.sched_priority = EVENT_THREAD_PRIORITY;
// 设置线程调度优先级: 使用 实时调度策略 SCHED_FIFO,减少 jitter。优先级设置为 2。
if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for EventThread");
}
// 设置线程调度策略
set_sched_policy(tid, SP_FOREGROUND);
}
参数说明:
| 参数 | 含义 |
|---|---|
name | 线程名(如 "app", "sf") |
vsyncSchedule | 提供 VSync 信号的调度器(底层来自 HWComposer 或模拟) |
tokenManager | 传入给 FrameTimeline 使用(用于帧同步调试) |
throttleVsyncCallback | 可用于控制某些 app 是否限制帧率 |
getVsyncPeriodFunction | 查询当前应用的 VSync 周期函数 |
workDuration | 预计一帧处理逻辑所需时间 |
readyDuration | 预计从准备好到真正投递事件的时间 |
3.2 DisplayEventReceiver::Event 对象创建
在DisplayEventReceiver的头文件定义了 struct Event 结构体。
union {
VSync vsync;
Hotplug hotplug;
ModeChange modeChange;
FrameRateOverride frameRateOverride;
};
在 EventThread 创建 Event 各种类型的对象,并针对上述不同的属性进行赋值。定义 makeXxx 函数封装了不同类型的 DisplayEventReceiver::Event 创建逻辑,用于构造:
| 函数名 | 创建的事件类型 | 用途 |
|---|---|---|
makeHotplug | DISPLAY_EVENT_HOTPLUG | 屏幕连接/断开通知 |
makeVSync | DISPLAY_EVENT_VSYNC | VSync 信号事件(核心) |
makeModeChanged | DISPLAY_EVENT_MODE_CHANGE | 分辨率/刷新率模式变更 |
makeFrameRateOverrideEvent | DISPLAY_EVENT_FRAME_RATE_OVERRIDE | FrameRate 覆盖策略事件 |
makeFrameRateOverrideFlushEvent | DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH | 上述事件清空标记 |
源码如下:
DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t timestamp,
bool connected) {
DisplayEventReceiver::Event event;
event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, displayId, timestamp};
event.hotplug.connected = connected;
return event;
}
DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
uint32_t count, nsecs_t expectedPresentationTime,
nsecs_t deadlineTimestamp) {
DisplayEventReceiver::Event event;
event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
event.vsync.count = count;
event.vsync.vsyncData.preferredFrameTimelineIndex = 0;
// Temporarily store the current vsync information in frameTimelines[0], marked as
// platform-preferred. When the event is dispatched later, the frame interval at that time is
// used with this information to generate multiple frame timeline choices.
event.vsync.vsyncData.frameTimelines[0] = {.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID,
.deadlineTimestamp = deadlineTimestamp,
.expectedPresentationTime =
expectedPresentationTime};
return event;
}
DisplayEventReceiver::Event makeModeChanged(const scheduler::FrameRateMode& mode) {
DisplayEventReceiver::Event event;
event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE,
mode.modePtr->getPhysicalDisplayId(), systemTime()};
event.modeChange.modeId = mode.modePtr->getId().value();
event.modeChange.vsyncPeriod = mode.fps.getPeriodNsecs();
return event;
}
DisplayEventReceiver::Event makeFrameRateOverrideEvent(PhysicalDisplayId displayId,
FrameRateOverride frameRateOverride) {
return DisplayEventReceiver::Event{
.header =
DisplayEventReceiver::Event::Header{
.type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
.displayId = displayId,
.timestamp = systemTime(),
},
.frameRateOverride = frameRateOverride,
};
}
DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId) {
return DisplayEventReceiver::Event{
.header = DisplayEventReceiver::Event::Header{
.type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH,
.displayId = displayId,
.timestamp = systemTime(),
}};
}
(1)DisplayEventReceiver::Event makeVSync(…)
构造一个 VSYNC 信号事件,是 EventThread 分发到 app 的最常见类型。
event.header = {
DisplayEventReceiver::DISPLAY_EVENT_VSYNC,
displayId,
timestamp
};
event.vsync.count = count;
event.vsync.vsyncData.frameTimelines[0] = {
.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID,
.deadlineTimestamp = deadline,
.expectedPresentationTime = expectedTime
};
- timestamp: 当前 VSync 到达时间
- count: 自上次连接以来 VSYNC 累加计数
- frameTimelines[0]: 当前帧的预计 deadline 和呈现时间
注意:它只是初始化 frameTimelines[0],真正填满多个 timeline 是在发送前动态完成的(由 FrameTimeline 模块处理)。
(2)DisplayEventReceiver::Event makeHotplug(…)
构建连接/断开显示器的事件:
event.header = {
DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
displayId,
timestamp
};
event.hotplug.connected = true / false;
会触发应用层 SurfaceView、GLSurfaceView 或 InputManager 做响应。
(3)DisplayEventReceiver::Event makeModeChanged(…)
用于分辨率或帧率模式变更:
event.header = {DISPLAY_EVENT_MODE_CHANGE, displayId, now};
event.modeChange.modeId = modeId;
event.modeChange.vsyncPeriod = newPeriod;
这种事件一般在:
- 动态切换刷新率(如 60Hz ↔ 120Hz)
- 连接 HDR 显示器自动调整模式时出现
4 关键函数
4.1 createEventConnection
创建并返回一个新的 EventThreadConnection 实例,用于客户端(如 SurfaceFlinger 的 binder 调用者,例如应用进程)注册和接收 VSYNC 等显示相关事件。
sp<EventThreadConnection> EventThread::createEventConnection(
ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) const {
return sp<EventThreadConnection>::make(const_cast<EventThread*>(this), // 指向当前 EventThread 的裸指针
IPCThreadState::self()->getCallingUid(), // 获取调用者的 UID
std::move(resyncCallback), // 移交回调函数
eventRegistration); // 注册标志
}
参数说明:
- ResyncCallback - 回调函数,用于需要重新同步(resync)时调用。
- EventRegistrationFlags - 枚举值,表示客户端希望接收的事件类型(如 VSYNC、HOTPLUG 等)。
- const - 表示该函数不会修改 EventThread 本身的状态。
sp< EventThreadConnection >::make
| 参数 | 含义 |
|---|---|
this | 当前 EventThread,用于 EventThreadConnection 和其建立联系 |
getCallingUid() | 获取当前 Binder 请求调用方的 UID(用于权限控制和节流) |
resyncCallback | 当事件队列卡顿等需要重同步时调用的回调 |
eventRegistration | 表示希望注册哪些事件类型(例如 VSYNC) |
调用链简图
SurfaceFlinger::createDisplayEventConnection() →
EventThread::createEventConnection() →
new EventThreadConnection(...) →
onFirstRef() →
EventThread::registerDisplayEventConnection(...) →
mDisplayEventConnections.push_back(...)
4.2 setVsyncRate
设置指定连接的 VSYNC 接收频率(即每 rate 次 VSYNC 接收一次),并在改变时唤醒 EventThread 的主循环以重新评估事件派发。
| 参数 | 含义 |
|---|---|
rate | 0 表示不接收 VSYNC,1 表示每帧接收,>1 表示跳帧模式 |
connection | 目标连接对象,代表某个监听显示事件的客户端 |
binder::Status EventThreadConnection::setVsyncRate(int rate) {
mEventThread->setVsyncRate(static_cast<uint32_t>(rate),
sp<EventThreadConnection>::fromExisting(this));
return binder::Status::ok();
}
void EventThread::setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) {
if (static_cast<std::underlying_type_t<VSyncRequest>>(rate) < 0) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
// 映射成内部定义的枚举类型 VSyncRequest(代表 "不接收" / "每 1 帧接收一次" / "每 n 帧接收一次")
const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
// 果请求频率有变,更新 vsyncRequest
if (connection->vsyncRequest != request) {
connection->vsyncRequest = request;
mCondition.notify_all(); // 唤醒 EventThread::threadMain(...) 中阻塞等待的线程
}
}
4.3 requestNextVsync
用于实现 客户端单次请求下一次 VSYNC 信号 的功能。让某个连接(通常是 APP 的 DisplayEventReceiver)请求下一次 VSYNC 信号:
- 如果当前未请求 VSYNC,则切换到“单次请求”状态;
- 如果是 suppress 模式,也恢复为正常请求;
- 同时调用 resyncCallback() 做一些状态同步(比如通知 Choreographer 重新对齐)。
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
if (connection->resyncCallback) {
connection->resyncCallback(); // 一个来自客户端的回调,通常传入自定义函数(如 Choreographer::resyncToVsync())。用于在重新请求 Vsync 时进行 帧同步、调度准备 的动作
}
std::lock_guard<std::mutex> lock(mMutex);
// 如果之前根本没有监听 VSYNC(即 None),那么改为监听下 一帧(Single)
if (connection->vsyncRequest == VSyncRequest::None) {
connection->vsyncRequest = VSyncRequest::Single;
mCondition.notify_all(); // 通过 notify_all() 唤醒主线程 threadMain(),使其处理一次 dispatch
} else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
// 如果之前是特殊状态 SingleSuppressCallback(即:下一帧监听但 suppress 了回调),现在改为 真正要处理的单帧监听
connection->vsyncRequest = VSyncRequest::Single;
}
}
4.4 onVsync
EventThread::onVsync(…) 是 SurfaceFlinger 中 EventThread 收到 VSYNC 信号时的响应函数,其主要职责是:
- 记录收到的 VSYNC 时间戳;
- 构造 VSYNC 事件(DisplayEventReceiver::Event);
- 推入等待分发的事件队列 mPendingEvents;
- 唤醒线程主循环 threadMain() 进行事件分发。
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
std::lock_guard<std::mutex> lock(mMutex);
mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime); // 记录收到 Vsync 的时间
// 安全检查:是否设置过 VSyncState
LOG_FATAL_IF(!mVSyncState);
mVsyncTracer = (mVsyncTracer + 1) % 2;
// 生成 VSYNC 事件
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
vsyncTime, readyTime));
mCondition.notify_all(); // 唤醒主线程处理分发任务
}
参数说明
| 参数 | 含义 |
|---|---|
vsyncTime | 硬件发出的 Vsync 时间(理想的呈现时间) |
wakeupTime | 本次 wakeup 时间,用于唤醒线程准备 |
readyTime | 应该准备好渲染输出的时间 deadline |
4.5 onModeChanged
EventThread::onModeChanged() 是 SurfaceFlinger 中处理显示刷新率模式(FrameRateMode)变化的关键回调函数之一。当 显示设备切换刷新率(如 60Hz → 90Hz) 时,这个函数会被调用,将变化事件封装并推入事件队列,等待 EventThread 主循环处理并分发到应用进程。
void EventThread::onModeChanged(const scheduler::FrameRateMode& mode) {
std::lock_guard<std::mutex> lock(mMutex);
// 构造刷新率变化事件
mPendingEvents.push_back(makeModeChanged(mode)); // 引用 DisplayEventReceiver::Event makeModeChanged
mCondition.notify_all(); // 通知 threadMain() 主线程唤醒
}
4.6 threadMain
EventThread::threadMain() 是 SurfaceFlinger 中 事件分发线程的主循环函数,负责:
- 分发各种事件(VSync、Hotplug、ModeChanged…)给应用;
- 管理连接的客户端;
- 控制 VSyncDispatch 的调度(包括 VSYNC 注册和取消);
- 处理显示断开和驱动卡顿时的容错机制(如合成 vsync)。
4.6.1 结构概览
while (mState != State::Quit) {
① 从 mPendingEvents 中取出事件
② 处理 HOTPLUG 事件 → 更新 mVSyncState
③ 查找有效连接 → 确定哪些 connection 需要消费该事件
④ 分发事件
⑤ 决定下一状态:VSync / SyntheticVSync / Idle
⑥ schedule or cancel vsync callback
⑦ 等待下一轮事件 or VSync 信号(带超时)
}
4.6.2 源码分析
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
DisplayEventConsumers consumers;
while (mState != State::Quit) {
std::optional<DisplayEventReceiver::Event> event;
// Determine next event to dispatch.
// 处理事件队列:mPendingEvents
if (!mPendingEvents.empty()) {
event = mPendingEvents.front(); // 从 mPendingEvents 事件队列中提取首个事件
mPendingEvents.pop_front();
// 特殊处理 HOTPLUG 事件
if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
if (event->hotplug.connected && !mVSyncState) {
mVSyncState.emplace(event->header.displayId); // 新建 VSYNC 状态
} else if (!event->hotplug.connected && mVSyncState &&
mVSyncState->displayId == event->header.displayId) {
mVSyncState.reset(); // 显示断开,取消状态
}
}
}
bool vsyncRequested = false;
// Find connections that should consume this event.
auto it = mDisplayEventConnections.begin();
while (it != mDisplayEventConnections.end()) {
if (const auto connection = it->promote()) {
// 找到需要接收事件的连接(connection)
if (event && shouldConsumeEvent(*event, connection)) {
consumers.push_back(connection);
}
// 失效的连接(weak_ptr promote 失败)会从 mDisplayEventConnections 中移除
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
++it;
} else {
it = mDisplayEventConnections.erase(it);
}
}
if (!consumers.empty()) {
dispatchEvent(*event, consumers); // 分发事件, 应用通过 DisplayEventReceiver.getEvents() 获取。
consumers.clear();
}
// 计算是否需要调度 VSYNC
if (mVSyncState && vsyncRequested) {
// 若该显示是 "synthetic"(模拟)模式,则进入合成 VSync 模式
mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
} else {
ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
// 否则进入 Idle
mState = State::Idle;
}
// 调度/取消 VSync 回调
if (mState == State::VSync) {
const auto scheduleResult =
mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
.readyDuration = mReadyDuration.count(),
.earliestVsync = mLastVsyncCallbackTime.ns()});
LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");
} else {
mVsyncRegistration.cancel();
}
// 等待下一事件 or 超时生成 fake VSYNC
if (!mPendingEvents.empty()) {
continue;
}
// Wait for event or client registration/request.
// 无事件立即处理,则根据状态进入等待
if (mState == State::Idle) {
mCondition.wait(lock);
} else {
// Generate a fake VSYNC after a long timeout in case the driver stalls. When the
// display is off, keep feeding clients at 60 Hz.
// 若超时,说明驱动卡顿了(可能没有送出 VSYNC)
const std::chrono::nanoseconds timeout =
mState == State::SyntheticVSync ? 16ms : 1000ms;
if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
if (mState == State::VSync) {
ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
}
LOG_FATAL_IF(!mVSyncState);
const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
const auto deadlineTimestamp = now + timeout.count();
const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
// 生成 fake VSYNC
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
++mVSyncState->count, expectedVSyncTime,
deadlineTimestamp));
}
}
}
// cancel any pending vsync event before exiting
mVsyncRegistration.cancel();
}
函数执行过程:
-> 声明即将消费事件的 connection 集合:DisplayEventConsumers consumers
-> 构建死循环,状态值不等于 State::Quit 则一直循环遍历
-> 通过mPendingEvents.empty()函数判断下一个要调度的 Event
-> 获取头部 Event:event = mPendingEvents.front(),将其存储在event对象中
-> 将头部 Event 弹出:mPendingEvents.pop_front()
-> 根据 Event 类型分别对应处理:主要分类为DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG和DisplayEventReceiver::DISPLAY_EVENT_VSYNC,Event 类型为 DISPLAY_EVENT_VSYNC 即 VSync 信号
-> 在DISPLAY_EVENT_VSYNC事件中,mInterceptVSyncsCallback 不为空则执行 VSync 回调,传入事件的时间戳
-> 声明标志位:是否有 VSync 请求,默认 false
-> 循环遍历存储 EventThreadConnection 的 vector 容器 mDisplayEventConnections,查找要消费事件的连接,
-> 通过begin()函数用于返回指向向量容器的第一个元素的迭代器:auto it = mDisplayEventConnections.begin()
-> 构建while循环,it != mDisplayEventConnections.end()作为执行条件,在mDisplayEventConnections遍历完成时退出
-> 判断 const auto connection = it->promote(),获取一个mDisplayEventConnections对象,通过it->promote()获取到EventThreadConnection强引用对象。后续备注promote用法
-> 如果有一个 connection 的 vsyncRequest 不为 None 则 vsyncRequested 为 true:vsyncRequested |= connection->vsyncRequest != VSyncRequest::None
-> 通过判断 event 是否为空以及 shouldConsumeEvent() 是否返回 true 则将 connection 加入到 consumers 等待消费 event:consumers.push_back(connection)
-> 对于 shouldConsumeEvent() 方法作用:对于 VSync 类型的事件,只要 VSyncRequest 的类型不是 None 就返回 true
-> 如果获取不到 connection,则将迭代器中获取的it对象从 mDisplayEventConnections 移除:it = mDisplayEventConnections.erase(it)
-> 在上述mDisplayEventConnections遍历完成后,如果 consumers 不为空,即当前 Event 有 EventThreadConnection 来消费,去执行消费事件处理
-> 调用 dispatchEvent() 方法遍历 consumers 为其每个 EventThreadConnection 分发事件:dispatchEvent(*event, consumers)
-> 分发完清空:consumers.clear()
-> 声明State nextState,保存下一个状态值
-> 判断if (mVSyncState && vsyncRequested),来确认当前是否有 VSync 请求
-> 屏幕亮屏时 synthetic 为 false,打开硬件 VSync,分发 VSync;熄屏时为 true,关闭硬件 VSync,停止分发 VSync
-> 根据mVSyncState->synthetic的值,更新 nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync
-> 如果显示器熄屏或没有连接、忽略 VSync 请求,即上述判断结果为假:nextState = State::Idle,直接将nextState设置为Idle状态
-> 判断mState与 nextState 不一致,mState 值默认为 State::Idle:if (mState != nextState),要区分判定执行逻辑
-> if (mState == State::VSync) 当前状态为 State::VSync,则调用 mVSyncSource 的 setVSyncEnabled 并传入 false:mVSyncSource->setVSyncEnabled(false)
-> if (nextState == State::VSync) nextState 状态为 State::VSync,则调用 mVSyncSource 的 setVSyncEnabled 并传入 true:mVSyncSource->setVSyncEnabled(true)
-> 经过上述两个处理步骤,mState与 nextState 不一致的情况消除,同步状态mState = nextState
-> 后续如果继续存在event事件则继续循环遍历:if (event) { continue; }
-> 如果没有事件且当前状态为:State::Idle,则线程继续等待事件或客户端注册/请求
-> 如果 mState == State::Idle,则执行 mCondition.wait(lock) 进入等待
-> 如果为非Idle状态,为防止驱动程序停止,这种情况是硬件不知什么原因没有发送 VSync 上来,需要伪造 VSync 信号,频率为熄屏时 16ms,亮屏时 1000ms
-> 根据mState == State::SyntheticVSync这个条件选择频率:std::chrono::nanoseconds timeout = mState = = State::SyntheticVSync ? 16ms : 1000ms
-> 增加一个判断环节mState == State::VSync,如果为VSync状态,打印一下VSync信息
-> 将伪造的 VSync 放入 mPendingEvents 准备分发,mPendingEvents.push_back + makeVSync组合,将消息派发出去,给到DisplayEventReceiver处理
注 :
① mVSyncState 声明在 EventThread.h 头文件中,通过其 synthetic 判断 nextState 是 SyntheticVSync 还是 VSync
② promote() 是 wp 的一个函数,调用 attemptIncStrong ,返回一个对象的强引用。即通过 promote() 函数将弱引用变为强引用,强引用数+1,弱引用数+1。因为通过弱指针 wp,不能获取实际的对象,wp 并没有提供 sp 那样的存取操作 * 和 -> 的重载,由弱生强后,可以 sp 获取实际的对象。
4.6.3 逻辑总结
总结:
① 声明消费 Event 的 EventThreadConnection 向量集合 consumers,开启死循环,如状态值不等于 State::Quit 则一直循环来处理 Event。
② 遍历双端队列 mPendingEvents,取出并确定下一个要调度的 Event。
③ 遍历存储 EventThreadConnection 的 vector 容器 mDisplayEventConnections,查找消费事件的连接,并将符合条件的 EventThreadConnection 添加到 consumers 中。
④ 调用 dispatchEvent(*event, consumers) 方法遍历 consumers 为其每个 EventThreadConnection 分发事件。
⑤ 没有事件且当前线程状态为:State::Idle,则线程继续等待事件或客户端注册、请求,如果没有事件且线程状态不为:State::Idle 时则需要伪造 VSync 发送给请求者,防止驱动程序停止。
问: mPendingEvents 这个队列中的 Event 是哪里来的?
回答这个问题,首先得弄清楚 VSync 信号是哪里来的?VSync 信号是由 HWC 硬件模块根据屏幕刷新率(60Hz)产生。HWC 产生硬件 VSync 信号后经由 VSyncReactor、VSyncDispatchTimerQueue 等类的包装处理,最后 VSync 事件会回调到 EventThread::onVSyncEvent() 方法中,该方法通过 makeVSync() 方法把事件封装成 Event 后存到 mPendingEvents 双端队列中,并唤醒 EventThread::threadMain() 进行下一步处理。
4.7 shouldConsumeEvent
EventThread::shouldConsumeEvent() 是 判断某个连接 (EventThreadConnection) 是否应当接收一个 DisplayEvent 事件 的核心函数。其功能对于控制 SurfaceFlinger 向应用分发事件的节奏、精度和性能优化至关重要。
函数定义
bool EventThread::shouldConsumeEvent(
const DisplayEventReceiver::Event& event,
const sp<EventThreadConnection>& connection) const
- 判断 event 是否应当被 connection 消费(即是否应推送给该客户端)。
- 如果返回 true,该连接会收到该事件(见 dispatchEvent())。
- 在 EventThread::threadMain() 中被调用。
源码分析
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
const sp<EventThreadConnection>& connection) const {
// 节流逻辑 throttleVsync(内部 Lambda)
const auto throttleVsync = [&]() REQUIRES(mMutex) {
const auto& vsyncData = event.vsync.vsyncData;
// 指定了 connection->frameRate
if (connection->frameRate.isValid()) {
// 使用 VsyncTracker::isVSyncInPhase(...) 判断当前 VSYNC 是否对齐该帧率;若未对齐,则跳过当前帧
return !mVsyncSchedule->getTracker()
.isVSyncInPhase(vsyncData.preferredExpectedPresentationTime(),
connection->frameRate);
}
// 未指定帧率,使用全局 throttle 回调(mThrottleVsyncCallback)
return mThrottleVsyncCallback &&
mThrottleVsyncCallback(event.vsync.vsyncData.preferredExpectedPresentationTime(),
connection->mOwnerUid);
};
switch (event.header.type) {
// HOTPLUG 事件:总是发送
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
return true; // 显示连接/断开事件,无需判断是否注册,直接发给所有连接
// MODE_CHANGE 事件:根据注册标志判断
case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
// 只有当连接明确注册了 modeChanged 事件,才发
return connection->mEventRegistration.test(
gui::ISurfaceComposer::EventRegistration::modeChanged);
}
// VSYNC 事件:逻辑最复杂
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
switch (connection->vsyncRequest) {
// VSyncRequest::None: 明确不接收 VSYNC
case VSyncRequest::None:
return false;
// VSyncRequest::SingleSuppressCallback:伪状态,用于忽略下一帧
case VSyncRequest::SingleSuppressCallback:
// 这是处理 Single 模式的一种中间态:抑制回调,只接收一次后清除请求
connection->vsyncRequest = VSyncRequest::None;
return false;
// VSyncRequest::Single: 仅请求接收一次
case VSyncRequest::Single: {
// 若需要节流,则跳过这帧;
if (throttleVsync()) {
return false;
}
// 否则允许接收,但设置状态为 SingleSuppressCallback,表示“下一帧别发了”
connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
return true;
}
// VSyncRequest::Periodic: 周期性接收
case VSyncRequest::Periodic:
// 若当前帧被判定为“应节流”,则跳过; 否则定期分发
if (throttleVsync()) {
return false;
}
return true;
// 默认分支:针对设置为自定义周期整数的情况
default:
// We don't throttle vsync if the app set a vsync request rate
// since there is no easy way to do that and this is a very
// rare case
// 例如某些应用可能请求每 N 帧才接收一次 vsync;利用 vsync.count % N == 0 来实现节奏控制。
return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
}
case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
[[fallthrough]];
case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
return connection->mEventRegistration.test(
gui::ISurfaceComposer::EventRegistration::frameRateOverride);
default:
return false;
}
}
4.8 generateFrameTimeline
EventThread::generateFrameTimeline(…) 函数的核心作用是:根据当前 VSync 信号,生成一组候选帧时间线(FrameTimelines)用于提交到 GPU 的时间调度与预测,供 Choreographer / RenderThread 等系统组件参考。
函数作用总结
输入:
- timestamp: 当前 VSync 的时间戳
- frameInterval: 一帧的时长(如 16.66ms)
- preferredExpectedPresentationTime: 首选的帧显示时间(App 理想显示点)
- preferredDeadlineTimestamp: 首选的帧提交 deadline(App 必须完成的时间)
输出:
- VsyncEventData& outVsyncEventData: 写入多个候选帧的 vsync 时间线信息,每个包括 expectedPresentationTime 与 deadlineTimestamp。
void EventThread::generateFrameTimeline(VsyncEventData& outVsyncEventData, nsecs_t frameInterval,
nsecs_t timestamp,
nsecs_t preferredExpectedPresentationTime,
nsecs_t preferredDeadlineTimestamp) const {
uint32_t currentIndex = 0;
// Add 1 to ensure the preferredFrameTimelineIndex entry (when multiplier == 0) is included.
// 循环构建多个 Frame Timeline 候选项,从较早的帧(负 multiplier)开始扫描,直到找到 kFrameTimelinesCapacity 个合法时间线。
for (int64_t multiplier = -VsyncEventData::kFrameTimelinesCapacity + 1;
currentIndex < VsyncEventData::kFrameTimelinesCapacity; multiplier++) {
// 计算候选帧的 deadline 与 expectedPresentationTime
nsecs_t deadlineTimestamp = preferredDeadlineTimestamp + multiplier * frameInterval;
// Valid possible frame timelines must have future values, so find a later frame timeline.
// 过滤掉无效帧(如已经过去的帧)
if (deadlineTimestamp <= timestamp) {
continue;
}
nsecs_t expectedPresentationTime =
preferredExpectedPresentationTime + multiplier * frameInterval;
// 过滤掉时间太远的帧(提前提交帧不能太早)
if (expectedPresentationTime >= preferredExpectedPresentationTime +
scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()) {
// 记录 preferred timeline 的 index,这是 App 本次 VSync 预期使用的时间线(即当前时间点所对应的 ideal 提交时机)
if (currentIndex == 0) {
ALOGW("%s: Expected present time is too far in the future but no timelines are "
"valid. preferred EPT=%" PRId64 ", Calculated EPT=%" PRId64
", multiplier=%" PRId64 ", frameInterval=%" PRId64 ", threshold=%" PRId64,
__func__, preferredExpectedPresentationTime, expectedPresentationTime,
multiplier, frameInterval,
static_cast<int64_t>(
scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()));
}
break;
}
if (multiplier == 0) {
outVsyncEventData.preferredFrameTimelineIndex = currentIndex;
}
// 填写 frameTimelines[] 数组
// 每个 timeline 对应一个 vsyncId(用于同步标识)+ deadline + 显示时间
outVsyncEventData.frameTimelines[currentIndex] =
{.vsyncId = generateToken(timestamp, deadlineTimestamp, expectedPresentationTime),
.deadlineTimestamp = deadlineTimestamp,
.expectedPresentationTime = expectedPresentationTime};
currentIndex++;
}
// 如果一个 timeline 都无法构建,强制写入 fallback timeline
if (currentIndex == 0) {
ALOGW("%s: No timelines are valid. preferred EPT=%" PRId64 ", frameInterval=%" PRId64
", threshold=%" PRId64,
__func__, preferredExpectedPresentationTime, frameInterval,
static_cast<int64_t>(scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()));
// 基于当前帧时间戳生成唯一帧 token;
// token 用于客户端(如 Choreographer)标识某一具体 VSync
outVsyncEventData.frameTimelines[currentIndex] =
{.vsyncId = generateToken(timestamp, preferredDeadlineTimestamp,
preferredExpectedPresentationTime),
.deadlineTimestamp = preferredDeadlineTimestamp,
.expectedPresentationTime = preferredExpectedPresentationTime};
currentIndex++;
}
// 最终写入 timeline 数量
outVsyncEventData.frameTimelinesLength = currentIndex;
}
4.9 dispatchEvent
函数 EventThread::dispatchEvent(…) 是 SurfaceFlinger 中 EventThread 向客户端(应用层)分发 DisplayEvent 的核心函数,特别关键在 VSYNC 事件传递上(会影响到应用中的 Choreographer、RenderThread 等接收帧信号的组件)。向多个 DisplayEventConnection 发送当前准备好的 DisplayEvent(如 Vsync、Hotplug、ModeChange 等)。
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, // 要派发的事件
const DisplayEventConsumers& consumers) { // 要通知的客户端连接列表
// 针对每个 consumer(连接)做处理
for (const auto& consumer : consumers) { // consumers 是经过 shouldConsumeEvent() 过滤的连接(即对该事件感兴趣的客户端)
// 复制事件结构体(每个 connection 都是独立副本)
DisplayEventReceiver::Event copy = event;
// 如果是 VSync 事件,填入连接专属的时间线信息
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
// 获取此连接所需的 frameInterval
const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
copy.vsync.vsyncData.frameInterval = frameInterval;
// 调用 generateFrameTimeline() 为该连接生成完整的帧时间线(带多个帧预测信息)
generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp,
event.vsync.vsyncData.preferredExpectedPresentationTime(),
event.vsync.vsyncData.preferredDeadlineTimestamp());
}
// postEvent(...) 实际是往 DisplayEventReceiver 注册的 Binder fd 写入事件
// EventThreadConnection::postEvent
// 消费端(如 App 内部的 Choreographer)读取该 fd 触发对应的事件处理
switch (consumer->postEvent(copy)) {
case NO_ERROR: // 成功发送
break;
case -EAGAIN: // 写入管道失败(可能 pipe 满了),可以稍后重试
// TODO: Try again if pipe is full.
ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
toString(*consumer).c_str());
break;
default: // 如 EPIPE 表示接收端挂掉了,主动清理连接
// Treat EPIPE and other errors as fatal.
removeDisplayEventConnectionLocked(consumer);
}
}
}
总结要点
| 核心点 | 说明 |
|---|---|
| 每个连接独立派发事件 | 每个 consumer 会收到一份拷贝,确保独立性 |
| 针对 vsync,生成个性化 frameTimeline | 不同 app 拥有不同 frameInterval 和调度策略 |
VSYNC 事件包含 frameInterval、多个候选帧时间线 | 用于 Choreographer 与 GPU pipeline 调度 |
| 若连接无响应或挂掉,自动清理 | 防止资源泄露 |
4.10 onNewVsyncSchedule
EventThread::onNewVsyncSchedule(…) 与 onNewVsyncScheduleInternal(…) 的代码,是 SurfaceFlinger 中 EventThread 切换新的 VsyncSchedule 调度器的实现逻辑。这是动态刷新率、Vsync 策略管理中的关键一环。
当 Vsync 调度策略发生变化(如刷新率变更、display 配置更新等),SurfaceFlinger 会调用:EventThread::onNewVsyncSchedule(…)。将新的 VsyncSchedule 安装进来,并在需要时重新注册 Vsync 回调,确保之后的 Vsync 事件能正确调度并触发 onVsync(…) 回调。
void EventThread::onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule> schedule) {
// 外部入口(保持线程安全、避免死锁)
// Hold onto the old registration until after releasing the mutex to avoid deadlock.
// 仅调用了内部实际逻辑函数,并保留返回值用于延迟释放资源(避免死锁)
scheduler::VSyncCallbackRegistration oldRegistration =
onNewVsyncScheduleInternal(std::move(schedule));
}
scheduler::VSyncCallbackRegistration EventThread::onNewVsyncScheduleInternal(
std::shared_ptr<scheduler::VsyncSchedule> schedule) {
std::lock_guard<std::mutex> lock(mMutex);
// 取消旧的回调注册, 解除当前 mVsyncRegistration 在调度器中的绑定。
const bool reschedule = mVsyncRegistration.cancel() == scheduler::CancelResult::Cancelled;
// 替换调度器和回调
mVsyncSchedule = std::move(schedule); // 更新 mVsyncSchedule
// 用新的 VsyncDispatch 创建并替换掉旧的 mVsyncRegistration
// 绑定 createDispatchCallback() 作为新的回调函数
// 注解:VSyncCallbackRegistration 是个包装器:用于自动管理 dispatch → callback 的注册与注销逻辑
auto oldRegistration =
std::exchange(mVsyncRegistration,
scheduler::VSyncCallbackRegistration(mVsyncSchedule->getDispatch(),
createDispatchCallback(),
mThreadName));
// 如果之前是激活状态(成功取消),则重新 schedule vsync
if (reschedule) {
mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(), // 客户端工作所需时间(提前多久 wakeup)
.readyDuration = mReadyDuration.count(), // GPU 准备所需时间(提前多久提交)
.earliestVsync = mLastVsyncCallbackTime.ns()}); // 当前最早允许的 vsync 时间戳(避免早唤醒)
}
return oldRegistration;
}
// 创建 Vsync 回调函数(最终回到 onVsync)
scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
onVsync(vsyncTime, wakeupTime, readyTime);
};
}
4.11 createDispatchCallback
EventThread::createDispatchCallback() 方法,返回一个类型为 scheduler::VSyncDispatch::Callback 的 闭包(lambda)函数,它将 onVsync(…) 方法绑定为 VSYNC 回调处理逻辑的执行入口。
scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
onVsync(vsyncTime, wakeupTime, readyTime);
};
}
- EventThread 调用 createDispatchCallback() 创建一个 VSYNC 到来时执行的函数。
- 这个函数被注册进了 scheduler::VSyncDispatch(调度器)中。
- 当 VSYNC 被触发时,VSyncDispatch 会调用这个 lambda。
- Lambda 内部调用 onVsync(vsyncTime, wakeupTime, readyTime),这是 EventThread实际处理逻辑的入口。
createDispatchCallback() 的作用是为当前 EventThread 生成一个 专属 VSYNC 响应函数,并注册到 VSyncDispatch 调度系统中。一旦系统检测到下一次 VSYNC 到来,调度器就会调用这个函数。
1522

被折叠的 条评论
为什么被折叠?



