2026-10-13 技术更新:保留原有历史截图和代码。文中代码片段已对照 AOSP
android-10.0.0_r1,现代差异以android-16.0.0_r1为例;这不表示原截图运行的就是这些版本,原始 Trace、ROM 和构建信息并未附上。窗口动画归属、StartingWindow 与线程相互影响的旧说法已在下文修正。
本文是 Systrace 系列文章的第四篇,主要是对 SystemServer 进行简单介绍,介绍了 SystemServer 中几个比较重要的线程,由于 Input 和 Binder 比较重要,所以单独拿出来讲,在这里就没有再涉及到。
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
本文目录
- 系列文章目录
- 正文
- 窗口动画
- ActivityManagerService
- WindowManagerService
- Input
- Binder
- HandlerThread
- ServiceThread
- 现代 Android 的对应关系
- 关于我 && 博客
系列文章目录
- Systrace 简介
- Systrace 基础知识 - Systrace 预备知识
- Systrace 基础知识 - Why 60 fps ?
- Systrace 基础知识 - SystemServer 解读
- Systrace 基础知识 - SurfaceFlinger 解读
- Systrace 基础知识 - Input 解读
- Systrace 基础知识 - Vsync 解读
- Systrace 基础知识 - Vsync-App :基于 Choreographer 的渲染机制详解
- Systrace 基础知识 - MainThread 和 RenderThread 解读
- Systrace 基础知识 - Binder 和锁竞争解读
- Systrace 基础知识 - Triple Buffer 解读
- Systrace 基础知识 - CPU Info 解读
- Systrace 流畅性实战 1 :了解卡顿原理
- Systrace 流畅性实战 2 :案例分析: MIUI 桌面滑动卡顿分析
- Systrace 流畅性实战 3 :卡顿分析过程中的一些疑问
- Systrace 响应速度实战 1 :了解响应速度原理
- Systrace 响应速度实战 2 :响应速度实战分析-以启动速度为例
- Systrace 响应速度实战 3 :响应速度延伸知识
- Systrace 线程 CPU 运行状态分析技巧 - Runnable 篇
- Systrace 线程 CPU 运行状态分析技巧 - Running 篇
- Systrace 线程 CPU 运行状态分析技巧 - Sleep 和 Uninterruptible Sleep 篇
正文
先区分进程、服务和线程:system_server 承载 AMS、ATMS、WMS 等服务,一个服务的工作可以分布在 Binder 线程和多个 Handler 线程上,并不是“一项服务对应一个线程”。这里的 android.ui 是系统服务使用的线程,不是应用自己的主线程;SurfaceFlinger 则是另一个进程。
这篇 SystemServer 文章现在应该和 Perfetto 10:Binder 调度与锁竞争 一起读。旧 Systrace 里看 SystemServer,重点是窗口动画、Input、AMS/WMS、Binder 调用、锁竞争等长 Slice;Perfetto 里仍然看这些问题,但要同时看 SystemServer 线程、Binder 线程池、调用端 App 线程状态、CPU 调度和锁等待证据。
如果问题表现为 App 等待系统调用,先定位对应的 SystemServer 请求,再看服务端线程是在 Running(执行)、Runnable(等待 CPU),还是睡眠/阻塞。等锁需要额外证据;对于 Binder 调用,还要检查线程池排队、同步回复等待以及调度和唤醒延迟。这样可以把“SystemServer 慢”拆成窗口动画执行慢、AMS/WMS 持锁、Binder 远端慢、CPU 调度慢等具体原因。
窗口动画
窗口动画是观察 system_server 的一个入口,但窗口管理、动画计算、应用绘制和最终合成不是同一件事。历史实现中常见 android.anim 与 android.anim.lf 两条线程;后者是小写字母 l、f,不是 Android.Anim.if。部分转场可以由 Launcher 等远端实现参与,不能据此认为所有动画都在这两条线程上执行。
以点击桌面图标为例,Launcher 发起启动并可能参与动画;系统窗口管理决定是否显示 StartingWindow。AOSP Android 10 的 AppWindowToken 负责相关判断并调度 starting surface 创建,并非 Launcher 自行创建应用的 StartingWindow。应用首帧、starting surface 移除和转场播放之间有同步条件,不能简化为所有设备都固定经历“Launcher 动画结束后,切换到 App 窗口动画”。
下面保留历史案例。前两图分别是 Launcher3(PID 2089)和 Contacts(PID 26196),选区都是 253.986 ms,用来对照 Launcher 动画与应用启动工作;这个选区本身不等于完整启动耗时或输入到首帧延迟。
Launcher 动画
此时对应的,App 正在启动
Contacts 图能看到 activityStart、activityResume 和 Choreographer#doFrame 等阶段。下图继续展示 android.anim 与 android.anim.lf 的活动;图内“应用启动完成/切换”的标注保留为当时案例的示意,不能仅凭这几张裁图确认首帧已经物理呈现,也不能推广为所有转场的固定交接流程。

ActivityManagerService
AMS 和 WMS 是常见分析入口,但“最繁忙”取决于场景。Activity/进程管理相关埋点常用 TRACE_TAG_ACTIVITY_MANAGER,atrace 类别名是 am;旧图的 ActivityManager 轨道不表示这些工作只发生在一个名为 AMS 的线程上。Android 10 已有独立的 ActivityTaskManagerService 管理 Activity 及任务等容器,不能把新版 Activity 管理全部归为 AMS。
下面是历史图中的 Start proc: sample.tencent.matrix:Wall Duration 为 14.962 ms,CPU Duration 为 0.678 ms。它是该片段的记录,不是应用完整冷启动时间,也不是说 CPU 执行了 14.962 ms。
在进程和四大组件的各种场景一般都会有对应的 Trace 点来记录,比如大家熟悉的 activityStart、activityResume、activityStop 等,这些 Trace 点有一些在应用进程,有一些在 SystemServer 进程,所以大家在看 Activity 相关的代码逻辑的时候,需要不断在这两个进程之间进行切换,这样才能从一个整体的角度来看应用的状态变化和 SystemServer 在其中起到的作用。
WindowManagerService
WMS 埋点常用 TRACE_TAG_WINDOW_MANAGER,atrace 类别名是 wm。应用通过 Binder 请求窗口操作时,服务端入口可出现在 system_server 的 Binder 线程上;布局、动画或后续任务也可能转到 Handler 线程执行。下图展示 Binder:925_9 上的 relayoutWindow,不能据此把 WMS 等同于 Binder 线程池。

在 Window 的各种场景一般都会有对应的 Trace 点来记录,比如大家熟悉的 relayoutWindow、performLayout、prepareToDisplay 等
Input
输入系统涉及设备读取、事件分发、窗口路由和应用消费等环节。InputReader 和 InputDispatcher 是 system_server 中两条重要的 Native 线程,但不是整条输入链路的全部。关于这一部分在 Systrace 基础知识 - Input 解读 里面已经详细讲过,这里就不再详细讲了

Binder
system_server 提供许多 Binder 服务。同步 Binder 等待、线程池排队和共享锁竞争都可能扩大响应时间,但后台应用数量本身不是根因证据。oneway 不等待同步回复,也仍有排队与执行成本。应沿具体调用寻找对端和持锁者,不能看到 Binder 线程多就判定系统卡顿。关于这一部分在 Binder 和锁竞争解读 里面已经详细讲过,这里就不再详细讲了

HandlerThread
以下构造器和两个业务片段对照 AOSP android-10.0.0_r1。它们是 Framework 内部实现,不是应用可依赖的公开 API;截图里的搜索结果只代表当时源码,不是各版本完整调用清单。
BackgroundThread
com/android/internal/os/BackgroundThread.java
1 | private BackgroundThread() { |
Systrace 中的 BackgroundThread
BackgroundThread 是每个使用它的进程中的共享单例 HandlerThread,适合可延后的后台任务,不是“对性能完全没有要求”。同一个队列里一项耗时任务仍会拖延后续任务;识别时也要看 PID,不能仅凭 android.bg 这个名字认定它来自 system_server。

ServiceThread
ServiceThread 继承自 HandlerThread。下面的 UiThread、IoThread、DisplayThread、AnimationThread、FgThread 和 SurfaceAnimationThread 分别承担不同工作,并设置了相应的初始优先级。
每个已启动的 HandlerThread 有自己的 Looper/MessageQueue,通常串行分发该队列中的任务。这可以分开排队,但不能隔离共享锁、同步 Binder、CPU 竞争或跨线程等待,因此仍会互相影响。ServiceThread 的 allowIo=false 在这个版本中初始化 StrictMode 线程策略,并不是内核层禁止所有 I/O;allowIo=true 也不代表任务自动变成异步或并行。
构造器中的 priority 是 Android/Linux nice 优先级,不是 java.lang.Thread 的 1—10 优先级。按 Android 10 的 Process 常量,数值越小通常优先级越高;线程组/cpuset、调度策略及后续 boost 也会影响实际运行,构造器值不等于运行期间永远不变。
| 线程名 | 构造器优先级 | 阅读时的边界 |
|---|---|---|
| android.bg | BACKGROUND = 10 | 可延后任务,共享串行队列 |
| android.ui | FOREGROUND = -2 | 系统服务 UI 线程,非 App 主线程 |
| android.io | DEFAULT = 0 | I/O 相关工作,非并发线程池 |
| android.display | DISPLAY + 1 = -3 | 比 -4 的默认动画优先级低一级,非 SurfaceFlinger |
| android.anim | DISPLAY = -4 | 历史 WindowAnimator 等工作 |
| android.fg | DEFAULT = 0 | 名称不表示 nice 为 FOREGROUND |
| android.anim.lf | DISPLAY = -4 | 部分 Surface 动画,仍可能等待或竞争 |
UiThread
com/android/server/UiThread.java
1 | private UiThread() { |
Systrace 中的 UiThread。下面的 UiHandler 片段 Wall Duration 为 39.383 ms,内部能看到 monitor contention;Self Time 0.194 ms 不是整段 CPU 时间,不能据总跨度直接认定 UI 线程一直在执行。
UiThread 是系统服务共享的 UI 工作线程,既不是 system_server 主线程,也不是任意 App 的主线程。下面的搜索图包含 AMS、PreBootBroadcaster 和 ATMS 的调用点;同一 Looper 上的多个服务任务仍需串行处理。具体功能可以按相应版本搜索 UiThread.get()。
IoThread
com/android/server/IoThread.java
1 | private IoThread() { |
IoThread 用来承载相应服务的 I/O 相关任务,但它仍是一条串行 HandlerThread,不是无限并发 I/O 池。下面是历史调用点,具体版本可搜索 IoThread.get()。
DisplayThread
com/android/server/DisplayThread.java
1 | private DisplayThread() { |
Systrace 中的 DisplayThread

AnimationThread
com/android/server/AnimationThread.java
1 | private AnimationThread() { |
Systrace 中的 AnimationThread
Android 10 的 WindowAnimator 在 AnimationThread 上创建 Choreographer 并调度帧回调,相关路径仍会访问 WMS 全局锁。Android 9 / P 中已经存在 SurfaceAnimationThread,把部分 Surface 动画工作放到另一线程处理;它不保证所有窗口动画都免于锁竞争或不再卡顿。

FgThread
com/android/server/FgThread.java
1 | private FgThread() { |
Systrace 中的 FgThread
FgThread 用于不适合落入后台调度限制的串行任务,名称中的 fg 不意味着其 nice 值就是 THREAD_PRIORITY_FOREGROUND:下面构造器使用的是 DEFAULT。以下 UserController 片段来自 Android 10,目的是将用户密钥清理与相关解锁流程串行化,避免数据损坏;这里的 mLock 检查之后已释放锁,再调用 lockUserKey。
1 | FgThread.getHandler().post(() -> { |
SurfaceAnimationThread
com/android/server/wm/SurfaceAnimationThread.java
1 | private SurfaceAnimationThread() { |
Systrace 中的 SurfaceAnimationThread
SurfaceAnimationThread 的名字叫 android.anim.lf , 与 android.anim 有区别,
该线程执行部分 Surface 动画工作,减少对 android.anim/WMS 路径的依赖。“LockFreeAnimation”不能理解为代码完全没有锁:Android 10 的 SurfaceAnimationRunner 仍有 mLock 和 mCancelLock,且结束回调会回到 AnimationThread。历史延伸阅读:Android P——LockFreeAnimation
1 | SurfaceAnimationRunner( AnimationFrameCallbackProvider callbackProvider, |
上面的 SurfaceAnimationRunner 构造器通过 runWithScissors 在 android.anim.lf 上取得该线程的 Choreographer。getSfInstance() 表示这里使用 SF Vsync 来源的 Choreographer,不表示 Java 动画代码跑进了 SurfaceFlinger 进程;它最终仍需提交 SurfaceControl 事务,由显示链路处理。
现代 Android 的对应关系
以 AOSP android-16.0.0_r1 为例,文中这些线程类仍存在,构造器的基本命名/优先级也仍可对照;但不能只凭线程名推断整套窗口动画架构没有变化。ServiceThread 与 FgThread 的源码已在 core/java/com/android/server/,其余相关类仍需按各自路径查找。
- Activity 与窗口管理:结合 AMS、ATMS、WMS 的具体入口和调用线程,不按服务名猜线程。用 trace 中的 PID/TID 和 Binder 关联确认请求、等待和返回。
- StartingWindow:Android 16 的 StartingSurfaceController 通过 TaskOrganizerController 请求 starting window,不沿用“Launcher 自行创建”的解释。
- 转场动画:启用 Shell transitions 时,TransitionController 与 WM Shell 的 Transitions 协作,并可交给远端处理。要查看实际的 Shell/Launcher/SystemUI 进程及其线程,不能只盯 system_server 的 android.anim.lf。
- 图形状态与时序:Perfetto 用于关联调度、Binder 和已采集的帧数据;需要确认窗口/layer、事务、转场参与者时,可配合 Winscope。相应数据源和权限需要单独配置,旧截图不会自动获得这些信息。
判断瓶颈时分清 Wall Duration、CPU Duration 与 Self Time:前者是片段跨度,CPU 时间要依调度数据统计,Self Time 通常是扣除嵌套片段后的跨度。三者不能互换。找到等待者后还要找实际持锁者或 Binder 对端;只看到长片段、Sleep 或一组后台应用,都不足以确认根因。
关于我 && 博客
下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!
- 博主个人介绍 :里面有个人的微信和微信群链接。
- 本博客内容导航 :个人博客内容的一个导航。
- 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
- Android性能优化知识星球:付费社群已于 2026 年停止运营,不再招收新成员;此处保留历史介绍。
一个人可以走的更快 , 一群人可以走的更远
