EN

Android Systrace 基础知识 - SystemServer 解读

字数统计: 3.7k阅读时长: 14 min
2019/06/29
loading

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 这个图形化的角度,你可以理解的更深入一些。

本文目录

系列文章目录

  1. Systrace 简介
  2. Systrace 基础知识 - Systrace 预备知识
  3. Systrace 基础知识 - Why 60 fps ?
  4. Systrace 基础知识 - SystemServer 解读
  5. Systrace 基础知识 - SurfaceFlinger 解读
  6. Systrace 基础知识 - Input 解读
  7. Systrace 基础知识 - Vsync 解读
  8. Systrace 基础知识 - Vsync-App :基于 Choreographer 的渲染机制详解
  9. Systrace 基础知识 - MainThread 和 RenderThread 解读
  10. Systrace 基础知识 - Binder 和锁竞争解读
  11. Systrace 基础知识 - Triple Buffer 解读
  12. Systrace 基础知识 - CPU Info 解读
  13. Systrace 流畅性实战 1 :了解卡顿原理
  14. Systrace 流畅性实战 2 :案例分析: MIUI 桌面滑动卡顿分析
  15. Systrace 流畅性实战 3 :卡顿分析过程中的一些疑问
  16. Systrace 响应速度实战 1 :了解响应速度原理
  17. Systrace 响应速度实战 2 :响应速度实战分析-以启动速度为例
  18. Systrace 响应速度实战 3 :响应速度延伸知识
  19. Systrace 线程 CPU 运行状态分析技巧 - Runnable 篇
  20. Systrace 线程 CPU 运行状态分析技巧 - Running 篇
  21. 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 动画
-w1019

此时对应的,App 正在启动
-w1025

Contacts 图能看到 activityStart、activityResume 和 Choreographer#doFrame 等阶段。下图继续展示 android.anim 与 android.anim.lf 的活动;图内“应用启动完成/切换”的标注保留为当时案例的示意,不能仅凭这几张裁图确认首帧已经物理呈现,也不能推广为所有转场的固定交接流程。

-w1236

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。
-w826

在进程和四大组件的各种场景一般都会有对应的 Trace 点来记录,比如大家熟悉的 activityStart、activityResume、activityStop 等,这些 Trace 点有一些在应用进程,有一些在 SystemServer 进程,所以大家在看 Activity 相关的代码逻辑的时候,需要不断在这两个进程之间进行切换,这样才能从一个整体的角度来看应用的状态变化和 SystemServer 在其中起到的作用。
-w660

WindowManagerService

WMS 埋点常用 TRACE_TAG_WINDOW_MANAGER,atrace 类别名是 wm。应用通过 Binder 请求窗口操作时,服务端入口可出现在 system_server 的 Binder 线程上;布局、动画或后续任务也可能转到 Handler 线程执行。下图展示 Binder:925_9 上的 relayoutWindow,不能据此把 WMS 等同于 Binder 线程池。

-w957

在 Window 的各种场景一般都会有对应的 Trace 点来记录,比如大家熟悉的 relayoutWindow、performLayout、prepareToDisplay 等
-w659

Input

输入系统涉及设备读取、事件分发、窗口路由和应用消费等环节。InputReader 和 InputDispatcher 是 system_server 中两条重要的 Native 线程,但不是整条输入链路的全部。关于这一部分在 Systrace 基础知识 - Input 解读 里面已经详细讲过,这里就不再详细讲了

-w725

Binder

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

-w1028

HandlerThread

以下构造器和两个业务片段对照 AOSP android-10.0.0_r1。它们是 Framework 内部实现,不是应用可依赖的公开 API;截图里的搜索结果只代表当时源码,不是各版本完整调用清单。

BackgroundThread

com/android/internal/os/BackgroundThread.java

1
2
3
private BackgroundThread() {
super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
}

Systrace 中的 BackgroundThread
-w1082

BackgroundThread 是每个使用它的进程中的共享单例 HandlerThread,适合可延后的后台任务,不是“对性能完全没有要求”。同一个队列里一项耗时任务仍会拖延后续任务;识别时也要看 PID,不能仅凭 android.bg 这个名字认定它来自 system_server。

-w654

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
2
3
private UiThread() {
super("android.ui", Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
}

Systrace 中的 UiThread。下面的 UiHandler 片段 Wall Duration 为 39.383 ms,内部能看到 monitor contention;Self Time 0.194 ms 不是整段 CPU 时间,不能据总跨度直接认定 UI 线程一直在执行。
-w1049

UiThread 是系统服务共享的 UI 工作线程,既不是 system_server 主线程,也不是任意 App 的主线程。下面的搜索图包含 AMS、PreBootBroadcaster 和 ATMS 的调用点;同一 Looper 上的多个服务任务仍需串行处理。具体功能可以按相应版本搜索 UiThread.get()。
-w650

IoThread

com/android/server/IoThread.java

1
2
3
private IoThread() {
super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);
}

IoThread 用来承载相应服务的 I/O 相关任务,但它仍是一条串行 HandlerThread,不是无限并发 I/O 池。下面是历史调用点,具体版本可搜索 IoThread.get()。
-w654

DisplayThread

com/android/server/DisplayThread.java

1
2
3
4
5
private DisplayThread() {
// DisplayThread runs important stuff, but these are not as important as things running in
// AnimationThread. Thus, set the priority to one lower.
super("android.display", Process.THREAD_PRIORITY_DISPLAY + 1, false /*allowIo*/);
}

Systrace 中的 DisplayThread
-w1108

-w656

AnimationThread

com/android/server/AnimationThread.java

1
2
3
private AnimationThread() {
super("android.anim", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
}

Systrace 中的 AnimationThread
-w902

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

-w657

FgThread

com/android/server/FgThread.java

1
2
3
private FgThread() {
super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);
}

Systrace 中的 FgThread
-w1018

FgThread 用于不适合落入后台调度限制的串行任务,名称中的 fg 不意味着其 nice 值就是 THREAD_PRIORITY_FOREGROUND:下面构造器使用的是 DEFAULT。以下 UserController 片段来自 Android 10,目的是将用户密钥清理与相关解锁流程串行化,避免数据损坏;这里的 mLock 检查之后已释放锁,再调用 lockUserKey。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FgThread.getHandler().post(() -> {
synchronized (mLock) {
if (mStartedUsers.get(userIdToLockF) != null) {
Slog.w(TAG, "User was restarted, skipping key eviction");
return;
}
}
try {
mInjector.getStorageManager().lockUserKey(userIdToLockF);
} catch (RemoteException re) {
throw re.rethrowAsRuntimeException();
}
if (userIdToLockF == userId) {
for (final KeyEvictedCallback callback : keyEvictedCallbacks) {
callback.keyEvicted(userId);
}
}
});

SurfaceAnimationThread

com/android/server/wm/SurfaceAnimationThread.java

1
2
3
private SurfaceAnimationThread() {
super("android.anim.lf", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
}

Systrace 中的 SurfaceAnimationThread
-w1148

SurfaceAnimationThread 的名字叫 android.anim.lf , 与 android.anim 有区别,
-w657

该线程执行部分 Surface 动画工作,减少对 android.anim/WMS 路径的依赖。“LockFreeAnimation”不能理解为代码完全没有锁:Android 10 的 SurfaceAnimationRunner 仍有 mLock 和 mCancelLock,且结束回调会回到 AnimationThread。历史延伸阅读:Android P——LockFreeAnimation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SurfaceAnimationRunner(@Nullable AnimationFrameCallbackProvider callbackProvider,
AnimatorFactory animatorFactory, Transaction frameTransaction,
PowerManagerInternal powerManagerInternal) {
SurfaceAnimationThread.getHandler().runWithScissors(() -> mChoreographer = getSfInstance(),
0 /* timeout */);
mFrameTransaction = frameTransaction;
mAnimationHandler = new AnimationHandler();
mAnimationHandler.setProvider(callbackProvider != null
? callbackProvider
: new SfVsyncFrameCallbackProvider(mChoreographer));
mAnimatorFactory = animatorFactory != null
? animatorFactory
: SfValueAnimator::new;
mPowerManagerInternal = powerManagerInternal;
}

上面的 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 或一组后台应用,都不足以确认根因。

关于我 && 博客

下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!

  1. 博主个人介绍 :里面有个人的微信和微信群链接。
  2. 本博客内容导航 :个人博客内容的一个导航。
  3. 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
  4. Android性能优化知识星球:付费社群已于 2026 年停止运营,不再招收新成员;此处保留历史介绍。

一个人可以走的更快 , 一群人可以走的更远

微信扫一扫

CATALOG
  1. 1. 本文目录
  • 系列文章目录
  • 正文
    1. 1. 窗口动画
    2. 2. ActivityManagerService
    3. 3. WindowManagerService
    4. 4. Input
    5. 5. Binder
    6. 6. HandlerThread
      1. 6.1. BackgroundThread
    7. 7. ServiceThread
      1. 7.1. UiThread
      2. 7.2. IoThread
      3. 7.3. DisplayThread
      4. 7.4. AnimationThread
      5. 7.5. FgThread
      6. 7.6. SurfaceAnimationThread
    8. 8. 现代 Android 的对应关系
  • 关于我 && 博客