IT技术博客大学习 共学习 共进步

Android Perfetto 系列 8:深入理解 Vsync 机制与性能分析

Android Performance 2026-06-03 09:03:23 累计浏览 3 次
本机暂存

本篇是 Perfetto 系列文章的第八篇,主要深入介绍 Android 中的 Vsync 机制及其在 Perfetto 中的表现形式。文章将从 Perfetto 的角度来分析 Android 系统如何基于 Vsync 信号进行帧渲染和合成,涵盖 Vsync、Vsync-app、Vsync-sf、VsyncWorkDuration 等核心概念。

随着高刷新率屏幕的普及,理解 Vsync 机制变得更加重要。本文将以 120Hz 刷新率为主要叙事线,帮助开发者理解现代 Android 设备中 Vsync 的工作原理,以及如何在 Perfetto 中观察和分析 Vsync 相关的性能问题。

注:本文内容基于 Android 16 的最新架构和实现

本文目录

系列文章目录

  1. Android Perfetto 系列目录
  2. Android Perfetto 系列 1:Perfetto 工具简介
  3. Android Perfetto 系列 2:Perfetto Trace 抓取
  4. Android Perfetto 系列 3:熟悉 Perfetto View
  5. Android Perfetto 系列 4:使用命令行在本地打开超大 Trace
  6. Android Perfetto 系列 5:Android App 基于 Choreographer 的渲染流程
  7. Android Perfetto 系列 6:为什么是 120Hz?高刷新率的优势与挑战
  8. Android Perfetto 系列 7 - MainThread 和 RenderThread 解读
  9. Android Perfetto 系列 8:深入理解 Vsync 机制与性能分析
  10. Android Perfetto 系列 (九) - CPU 信息解读
  11. 视频(B站) - Android Perfetto 基础和案例分享

如果大家还没看过 Systrace 系列,下面是传送门:

  1. Systrace 系列目录 : 系统介绍了 Perfetto 的前身 Systrace 的使用,并通过 Systrace 来学习和了解 Android 性能优化和 Android 系统运行的基本规则。
  2. 个人博客 :个人博客,主要是 Android 相关的内容,也放了一些生活和工作相关的内容。

欢迎大家在 关于我 页面加入微信群或者星球,讨论你的问题、你最想看到的关于 Perfetto 的部分,以及跟各位群友讨论所有 Android 开发相关的内容

什么是 Vsync

Vsync(Vertical Synchronization,垂直同步)是 Android 图形系统的核心机制,它的存在是为了解决一个根本性的问题:如何让软件的渲染节奏与硬件的显示节奏保持同步。

在没有 Vsync 机制之前,常见问题是屏幕撕裂(Screen Tearing)。当显示器读取 framebuffer 的同时,GPU 写入了下一帧,就会在同一次刷新中出现上下两部分不一致的画面。

Vsync 解决什么问题?

Vsync 机制的核心思想非常简单:让所有的渲染工作都按照显示器的刷新节拍来进行。具体来说:

  1. 同步信号:显示器每次开始新的刷新周期时,都会发出一个 Vsync 信号。
  2. 帧节拍与生产:应用侧在 Vsync 到来时由 Choreographer 驱动开始一帧的生产(Input/Animation/Traversal);CPU 提交渲染命令后,GPU 异步流水执行。SurfaceFlinger 侧在 Vsync 到来时进行 Buffer 的合成操作。
  3. 缓冲机制:使用双缓冲或三缓冲技术,确保显示器总是读取完整的帧数据。

这样,帧的生产与显示以 Vsync 为节拍对齐。以 120Hz 为例,每 8.333ms 会有一个显示机会;应用需要在该窗口前把可合成的 Buffer 提交给 SurfaceFlinger。关键约束是 queueBuffer/acquire_fence/present_fence 的时序;若未赶上本周期,会顺延到下一个周期显示。

Android 中 Vsync 的基本工作原理

Android 系统的 Vsync 实现比基本概念复杂得多,需要考虑多个不同的渲染组件,以及它们之间的协调工作。

Vsync 信号的分层架构

在 Android 系统中,并不是只有一个简单的 Vsync 信号。实际上,系统维护着多个不同用途的 Vsync 信号:

硬件 Vsync(HW Vsync)
这是最底层的 Vsync 信号,由显示硬件(HWC,Hardware Composer)产生。它的频率严格对应显示器的刷新率,比如 60Hz 的显示器会每 16.67ms 产生一次 HW Vsync,120Hz 的显示器会每 8.333ms 产生一次。(硬件 Vsync 回调由 HWC/SurfaceFlinger 管理,详见 frameworks/native/services/surfaceflinger 相关实现)

但是,HW Vsync 并不是一直开启的。由于频繁的硬件中断会消耗较多的电量,Android 系统采用了一种智能的策略:只有在需要精确同步的时候才开启 HW Vsync,大部分时间使用软件预测的方式生成 Vsync 信号。

Vsync-app(应用 Vsync)
这是专门用于驱动应用层渲染的 Vsync 信号。当应用需要进行 UI 更新时(比如用户触摸、动画运行、界面滚动等),应用会向系统申请接收 Vsync-app 信号。

1
2
3
4
5
6
7
8
9
10
// frameworks/base/core/java/android/view/Choreographer.java
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
// 向系统申请下一个 Vsync 信号
mDisplayEventReceiver.scheduleVsync();
}
}
}

Vsync-app 是按需申请的。如果应用界面是静态的,没有任何动画或用户交互,那么应用不会申请 Vsync-app 信号,系统也就不会为这个应用生成 Vsync 事件。

Vsync-sf(SurfaceFlinger Vsync)
这是专门用于驱动 SurfaceFlinger 进行图层合成的 Vsync 信号。SurfaceFlinger 是 Android 系统中负责将所有应用的图层合成为最终画面的服务。

Vsync-appSf(应用-SurfaceFlinger Vsync)
Android 13 引入的新信号类型。为消除旧设计中 sf EventThread 既唤醒 SurfaceFlinger 又服务部分 Choreographer 客户端带来的时序歧义,系统将两类职责分离:vsync-sf 专注唤醒 SurfaceFlinger,vsync-appSf 面向需要与 SurfaceFlinger 同步的客户端。

在 Perfetto 中观察 Vsync

Perfetto trace 中包含多个与 Vsync 相关的 Track,理解这些 Track 的含义有助于分析性能问题。

在 SurfaceFlinger 进程中

  1. vsync-app
    显示应用 Vsync 信号状态,数值在 0 和 1 之间变化。每次数值变化代表一个 Vsync 信号。
    image-20250811221826847

  2. **vsync-sf **
    显示 SurfaceFlinger Vsync 信号状态。无 Vsync Offset 时与 vsync-app 同步变化。
    image-20250811221902646

  3. vsync-appSf
    Android 13+ 新增,服务于需要与 SurfaceFlinger 同步的特殊 Choreographer 客户端。
    image-20250811222036489

  4. HW_VSYNC
    显示硬件 Vsync 开启状态。值为 1 表示开启,值为 0 表示关闭。为节省电量,硬件 Vsync 仅在需要精确同步时开启。
    image-20250811222159253

在应用进程中

FrameDisplayEventReceiver.onVsync Slice Track:
显示应用接收 Vsync 信号的时间点。由于信号通过 Binder 传递,时间可能略晚于 SurfaceFlinger 中的 vsync-app

image-20250918220632473

UI Thread Slice Track:
包含 Choreographer#doFrame 及相关的 Input、Animation、Traversal 等 Slice。每个 doFrame 对应一帧的处理工作。

image-20250918220709655

RenderThread Slice Track:
包含 DrawFramesyncAndDrawFramequeueBuffer 等 Slice,对应渲染线程工作。

image-20250918220730872

Android App 每一帧是如何基于 Vsync 工作的

Android 应用的每一帧基于 Vsync 机制完成从渲染到显示的完整过程涉及多个关键步骤。

image-20250918221821265

流程总览(按顺序)

  1. 触发重绘/输入:View.invalidate()、动画、数据变化或输入事件触发 → ViewRootImpl.scheduleTraversals()Choreographer.postCallback(TRAVERSAL)
  2. 申请 Vsync:Choreographer 通过 DisplayEventReceiver.scheduleVsync() 申请下一次 Vsync(app 相位)
  3. 接收 Vsync:DisplayEventReceiver.onVsync() 收到 Vsync 后,向主线程消息队列投递异步消息
  4. 主线程帧处理:Choreographer.doFrame() 按顺序执行五类回调:INPUT → ANIMATION → INSETS_ANIMATION → TRAVERSAL → COMMIT
  5. 渲染提交:RenderThread 执行 syncAndDrawFrame/DrawFrame,CPU 记录 GPU 命令,queueBuffer 提交到 BufferQueue
  6. 合成显示:SurfaceFlingervsync-sf 到来时合成(GPU/或HWC),生成 present_fence,输出到显示
  7. 帧完成度量:通过 FrameTimeline(PresentType/JankType)与 acquire/present_fence 判定是否按期显示

下面分别展开每一步的关键实现与 Perfetto 观测点。

App 什么时候会申请 Vsync 信号

应用并不是时刻都在申请 Vsync 信号的。Vsync 信号是按需申请的,只有在以下情况下,应用才会向系统申请下一个 Vsync:

触发申请 Vsync 的场景

  1. UI 更新需求:当 View 调用 invalidate()
  2. 动画执行:ValueAnimator、ObjectAnimator 等动画开始时
  3. 用户交互:触摸事件、按键事件等需要 UI 响应时
  4. 数据变化:RecyclerView 数据更新、TextView 文本改变等

App 申请 Vsync 的完整流程

当应用需要更新 UI 时,会通过以下流程申请 Vsync 信号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 1. UI 组件请求重绘
// frameworks/base/core/java/android/view/View.java
public void invalidate() {
// 标记为需要重绘,但不立即执行
mPrivateFlags |= PFLAG_DIRTY;

if (mParent != null && mAttachInfo != null) {
// 向父容器请求重绘
mParent.invalidateChild(this, null);
}
}

// 2. ViewRootImpl 调度遍历
// frameworks/base/core/java/android/view/ViewRootImpl.java
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 关键:向 Choreographer 注册回调,等待下一个 Vsync
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
}

// 3. Choreographer 申请 Vsync
// frameworks/base/core/java/android/view/Choreographer.java
public void postCallback(int callbackType, Runnable action, Object token) {
// 添加回调到队列
mCallbackQueues[callbackType].addCallbackLocked(action, token);

if (callbackType == CALLBACK_TRAVERSAL) {
// 如果是 UI 遍历回调,立即申请 Vsync
scheduleFrameLocked(now);
}
}

private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
// 关键:向系统申请 Vsync 信号
mDisplayEventReceiver.scheduleVsync();
}
}

主线程如何监听 Vsync 信号

应用主线程通过 DisplayEventReceiver 来监听 Vsync 信号。这个过程涉及几个关键步骤:

1. 建立连接

1
2
3
4
5
6
7
8
9
// frameworks/base/core/java/android/view/Choreographer.java
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {

public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
super(looper, vsyncSource);
// 在构造时建立与 SurfaceFlinger 的连接
}
}

2. 接收 Vsync 信号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
// 接收到 Vsync 信号,但注意:这里并不直接执行 doFrame
mTimestampNanos = timestampNanos;
mFrame = frame;

// 关键:将工作 post 到主线程的 MessageQueue 中
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true); // 设为异步消息,优先处理
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}

@Override
public void run() {
// 这里才真正开始执行一帧的工作
doFrame(mTimestampNanos, mFrame);
}

几个遗留问题

Q1:为什么不在 onVsync() 中直接执行 doFrame()
image-20250918221936675

  • 线程边界:onVsync() 可能不在主线程,UI 必须在主线程执行
  • 调度控制:通过 sendMessageAtTime() 精确对齐执行时刻
  • 队列语义:进入主线程 MessageQueue,确保与其他高优先级任务协同

Q2:Vsync 消息来了但主线程在忙,会丢吗?
image-20250918222045731

  • 不会。Vsync 消息入队后等待执行

Q3:CPU/GPU 是否必须在单个 Vsync 周期内完成?如果任何一个环节超过 1 个 vsync ,都会导致掉帧?

  • 现代 Android 系统采用多缓冲(通常是三缓冲)机制:

    • 应用端:Front Buffer(显示中)+ Back Buffer(渲染中)+ 可能的第三个 Buffer

    • SurfaceFlinger 端:也有类似的缓冲机制

    • 这意味着即使应用的某一帧超过了 Vsync 周期,也不一定会立即掉帧。

  • GPU 异步流水;关键是 queueBuffer 是否赶上 SF 合成窗口,多缓冲可掩盖单帧延迟但可能引入额外时延,可以看到下图里面,App 端的 BufferQueue 和 SurfaceFlinger 端的 Buffer 都是充足的,且有冗余,所以没有掉帧。

  • 但是如果 App 在之前没有堆积 Buffer ,则还是会出现掉帧。

image-20250918222258536

Q5:GPU 和 CPU 是怎么协同的?

  • GPU 渲染是异步的,这带来了额外的复杂性:

    • CPU 工作正常,GPU 成为瓶颈:即使应用主线程在 Vsync 周期内完成工作,GPU 渲染耗时过长仍会导致掉帧
    • GPU Fence 机制presentFence 是连接 GPU 渲染和 SurfaceFlinger 合成的关键同步机制。根据系统 Latch Unsignaled Buffers 策略,SurfaceFlinger 并非总是等待 GPU 完成,而是可以“抢跑”提前开始合成,仅在最终需要使用 Buffer 内容时才等待 fence 信号,以此来隐藏延迟。

    image-20250918222626100

Q6:Vsync Phase(相位差)的真正作用是什么?

  • 提升跟手性:通过调整 sf vsync 的相位差,可以让应用从开始绘制到显示在屏幕上的时间从 3 个 Vsync 周期缩短到 2 个 Vsync 周期。这对于触摸响应等交互场景非常重要。
  • 解决应用绘制超时问题:当应用绘制超时时,合理的 sf 相位差可以为应用争取更多的处理时间,避免因为时序不当导致的掉帧。
  • 通过观察 Perfetto 中的 VsyncWorkDuration 指标可以了解系统的 Vsync Offset 配置。
  • 下图中显示的时间段就是我手上的手机配置的 app offset (13.3ms)

image-20250918222707300

Vsync Offset 的技术实现

在 Android 系统中,Vsync Offset 是通过 VsyncConfiguration 来实现的:

1
2
3
4
5
6
7
8
9
10
11
// frameworks/native/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
struct VsyncConfiguration {
// 应用 Vsync 相对于硬件 Vsync 的偏移
nsecs_t appOffset;
// SurfaceFlinger Vsync 相对于硬件 Vsync 的偏移
nsecs_t sfOffset;
// 早期应用 Vsync 偏移(用于特殊情况)
nsecs_t appOffsetEarly;
// 早期 SurfaceFlinger Vsync 偏移
nsecs_t sfOffsetEarly;
};

关键概念

  • appOffset:应用 Vsync 相对于硬件 Vsync 的时间偏移
  • sfOffset:SurfaceFlinger Vsync 相对于硬件 Vsync 的时间偏移
  • Vsync Offset = sfOffset - appOffset:应用和 SurfaceFlinger 接收信号的时间差

实际的优化效果

以 120Hz 设备为例,配置 3ms Offset 的效果:

无 Offset(传统方式)

  • T0:应用和 SurfaceFlinger 同时接收 Vsync
  • T0+3ms:应用完成渲染
  • T0+8.333ms:下一个 Vsync,SurfaceFlinger 开始合成
  • T0+16.666ms:用户看到画面(总延迟 16.666ms)

有 Offset(优化方式)

  • T0+1ms:应用接收 Vsync-app,开始渲染
  • T0+3ms:应用完成渲染,提交 Buffer
  • T0+4ms:SurfaceFlinger 接收 Vsync-sf,立即开始合成
  • T0+6ms:SurfaceFlinger 完成合成
  • T0+8.333ms:用户看到画面(总延迟 8.333ms)

通过合理配置 Offset,可以将延迟从 16.666ms 减少到 8.333ms,提升一倍的响应性能。

实际的时间预算分配

以 120Hz 设备为例(8.333ms 周期):

  • 理想情况:应用 4ms + SurfaceFlinger 2ms + 缓冲 2.333ms
  • 但实际可以接受:应用 6ms + SurfaceFlinger 3ms(如果有足够的 Buffer 缓冲)
  • GPU 限制:在低端设备上,GPU 渲染可能需要 10-15ms,成为真正的瓶颈

掉帧的真正原因

  1. 应用端超时 + Buffer 耗尽:连续多帧超时导致 BufferQueue 没有可用 Buffer
  2. GPU 渲染超时:即使 CPU 工作正常,GPU 渲染超时也会掉帧
  3. SurfaceFlinger 超时:系统级合成超时,影响所有应用
  4. 系统资源竞争:CPU/GPU/内存等资源被其他进程占用

Vsync 信号的完整代码流程

Vsync 信号从硬件传递到应用层的完整链路如下。

Native 层:Vsync 信号的产生与管理

硬件 Vsync 的产生

Vsync 信号最初由显示硬件产生。在 HWC(Hardware Composer)层面,硬件会定期产生 Vsync 中断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// hardware/interfaces/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
// 注意:这是 HWC 1.x 到 2.x 的兼容性适配器,现代设备通常使用原生 HWC 2.x+
// 基于 Android 16 AOSP 最新代码
void HWC2On1Adapter::vsyncThread() {
while (!mVsyncEnded) {
if (mVsyncEnabled) {
const auto now = std::chrono::steady_clock::now();
const auto vsyncPeriod = std::chrono::nanoseconds(mVsyncPeriod);
const auto nextVsync = mLastVsync + vsyncPeriod;

if (now >= nextVsync) {
// 产生硬件 Vsync 时间戳
auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
nextVsync.time_since_epoch()).count();

// 回调到 SurfaceFlinger
if (mVsyncCallback) {
mVsyncCallback->onVsync(timestamp, mDisplayId);
}
mLastVsync = nextVsync;
}
}
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
}

VsyncController:核心控制器

VsyncController 是整个 Vsync 系统的大脑,它接收硬件 Vsync 并管理软件预测:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// frameworks/native/services/surfaceflinger/Scheduler/VsyncController.h
// 实际实现通常在 VSyncReactor.cpp 中
// 基于 Android 16 AOSP 最新代码
void VsyncController::onVsync(nsecs_t timestamp, int32_t hwcDisplayId) {
std::lock_guard<std::mutex> lock(mMutex);

// 记录硬件 Vsync 时间戳到追踪器
mVsyncTracker->addVsyncTimestamp(timestamp);

// 检查是否需要更多硬件 Vsync 样本来校准预测模型
if (mVsyncTracker->needsMoreSamples()) {
// 模型还需要更多样本,继续启用硬件 Vsync
ALOGV("VsyncController: Need more samples, keeping HW Vsync enabled");
} else {
// 模型已经稳定,可以关闭硬件 Vsync 节省电量
ALOGV("VsyncController: Model stable, disabling HW Vsync");
enableHardwareVsync(false);
}

// 通知所有等待的客户端
for (auto& callback : mCallbacks) {
callback->onVsync(timestamp);
}
}

void VsyncController::enableHardwareVsync(bool enable) {
if (mHwVsyncEnabled != enable) {
mHwVsyncEnabled = enable;
// 通过 HWC 接口控制硬件 Vsync
mHwc.setVsyncEnabled(mDisplayId, enable);

// 在 Perfetto trace 中可以看到这个状态变化
ATRACE_INT("HW_VSYNC", enable ? 1 : 0);
}
}

VsyncDispatch:信号分发机制

VsyncDispatch 负责将 Vsync 信号精确地分发给不同的消费者,每个消费者可以有不同的触发时间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatch.h
// 实际实现在 VSyncDispatchTimerQueue.cpp 中
// 基于 Android 16 AOSP 最新代码
VsyncDispatch::CallbackToken VsyncDispatch::registerCallback(
Callback callback, std::string callbackName) {
std::lock_guard<decltype(mMutex)> lock(mMutex);

// 为每个回调生成唯一的 token
auto token = CallbackToken(mCallbackMap.size());
mCallbackMap[token] = std::make_unique<CallbackEntry>(
std::move(callback), std::move(callbackName));

return token;
}

nsecs_t VsyncDispatch::schedule(CallbackToken token,
nsecs_t workDuration,
nsecs_t earliestVsync) {
std::lock_guard<decltype(mMutex)> lock(mMutex);

auto it = mCallbackMap.find(token);
if (it == mCallbackMap.end()) {
return kInvalidTime;
}

// 计算目标 Vsync 时间
auto targetVsync = mVsyncTracker->nextVsyncTime(earliestVsync);

// 计算唤醒时间 = 目标 Vsync - 工作时长
auto wakeupTime = targetVsync - workDuration;

// 如果唤醒时间已经过了,推到下一个 Vsync
auto now = systemTime(SYSTEM_TIME_MONOTONIC);
if (wakeupTime < now) {
targetVsync = mVsyncTracker->nextVsyncTime(targetVsync + 1);
wakeupTime = targetVsync - workDuration;
}

// 设置回调的触发时间
it->second->wakeupTime = wakeupTime;
it->second->targetVsync = targetVsync;
it->second->workDuration = workDuration;

// 重新调度定时器
reschedule();

return targetVsync;
}

void VsyncDispatch::reschedule() {
// 找到最早需要触发的回调
nsecs_t nextWakeup = std::numeric_limits<nsecs_t>::max();
for (const auto& [token, entry] : mCallbackMap) {
if (entry->wakeupTime > 0 && entry->wakeupTime < nextWakeup) {
nextWakeup = entry->wakeupTime;
}
}

if (nextWakeup != std::numeric_limits<nsecs_t>::max()) {
// 设置定时器在 nextWakeup 时间触发
mTimeKeeper->alarmAt(std::bind(&VsyncDispatch::timerCallback, this), nextWakeup);
}
}

void VsyncDispatch::timerCallback() {
std::vector<std::pair<CallbackToken, CallbackEntry*>> firedCallbacks;

{
std::lock_guard<decltype(mMutex)> lock(mMutex);
auto now = systemTime(SYSTEM_TIME_MONOTONIC);

// 找到所有应该触发的回调
for (auto& [token, entry] : mCallbackMap) {
if (entry->wakeupTime > 0 && now >= entry->wakeupTime) {
firedCallbacks.push_back({token, entry.get()});
entry->wakeupTime = 0; // 重置
}
}
}

// 在锁外执行回调,避免死锁
for (auto& [token, entry] : firedCallbacks) {
entry->callback(entry->targetVsync, entry->wakeupTime);
}
}

EventThread:连接 Native 和 Framework

EventThread 是连接 Native 层 Vsync 系统和 Framework 层的桥梁:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
std::unique_ptr<InterceptVSyncCallback> interceptVSyncCallback,
const char* threadName)
: mVSyncSource(std::move(vsyncSource))
, mInterceptVSyncCallback(std::move(interceptVSyncCallback))
, mThreadName(threadName) {

// 向 VsyncDispatch 注册回调
mVSyncSource->setCallback(this);

// 启动 EventThread 线程
mThread = std::thread([this] { threadMain(); });
}

void EventThread::threadMain() {
std::unique_lock<std::mutex> lock(mMutex);

while (mKeepRunning) {
// 等待 Vsync 事件或连接变化
mCondition.wait(lock, [this] {
return !mPendingEvents.empty() || !mKeepRunning;
});

// 处理所有待处理的事件
auto pendingEvents = std::move(mPendingEvents);
lock.unlock();

for (const auto& event : pendingEvents) {
// 分发给所有连接的客户端
for (const auto& connection : mConnections) {
if (connection->vsyncRequest != VSyncRequest::None) {
connection->postEvent(event);
}
}
}

lock.lock();
}
}

void EventThread::onVSyncEvent(nsecs_t timestamp, int32_t displayId) {
std::lock_guard<std::mutex> lock(mMutex);

// 创建 Vsync 事件
DisplayEventReceiver::Event event;
event.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
event.header.id = displayId;
event.header.timestamp = timestamp;
event.vsync.count = ++mVSyncCount;

// 添加到待处理事件队列
mPendingEvents.push_back(event);
mCondition.notify_all();
}

Framework 层:Vsync 信号的接收与处理

DisplayEventReceiver:Java 和 Native 的桥梁

DisplayEventReceiver 是 Framework 层接收 Vsync 信号的关键组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj, jint vsyncSource, jint configChanged) {

// 获取 Java 层的 MessageQueue
sp<MessageQueue&

建议继续学习

  1. 情绪版(Mood board)操作流程的新思考 (累计阅读 41,683)
  2. android 开发入门 (累计阅读 19,422)
  3. Android 连接SSID隐藏网络以及 LEAP 认证的方法 (累计阅读 9,461)
  4. 让安卓手机通过代理翻墙的方法 (累计阅读 8,977)
  5. 手机产品设计方向 (累计阅读 7,880)
  6. 实时监控Android设备网络封包 (累计阅读 6,482)
  7. Eclipse开发Android应用程序入门:重装上阵 (累计阅读 6,381)
  8. 基于 PhoneGap 与 Java 开发的 Android 应用的性能对比 (累计阅读 6,341)
  9. Android用户界面设计:表格布局 (累计阅读 6,122)
  10. Windows下使用VMware安装Android (累计阅读 5,561)