Android Framework 到底是什么
第 0 课:Android Framework 到底是什么
在 Activity 里拿窗口服务,代码只有一行:
WindowManager windowManager = getSystemService(WindowManager.class);平时写 App,我们拿到 WindowManager 就继续调用,很少追问这段代码最后由谁执行。可一旦窗口位置不对、 焦点没切过来,或者 setContentView() 之后迟迟没有首帧,只盯着 Activity 很快就查不下去了。
问题不在于少记了一个类名,而是我们把“手里的对象”和“真正处理设备级状态的组件”当成了同一个东西。 应用看到的是 Framework API 入口。请求是否留在当前进程、是否通过 Binder 进入系统服务、是否继续走到 Native 服务或内核,要沿具体调用链判断。
这也是学习 Framework 时最先要建立的习惯:看到一行 API,不要只问“下一步调用哪个方法”,还要问它 属于哪一层、运行在哪个进程、当前由哪个线程执行。
本章目标:建立一张能用于源码阅读和问题定位的 Framework 地图,分清系统层、源码目录、进程和调用边界。
本章边界:这里只搭全景,不展开 Binder 驱动、Handler 循环、JNI、Context 或 WMS 的内部实现。
先把 Framework 放回 Android 系统里
很多入门资料会把 Android 画成几层,然后把 Framework 放在中间。这张图本身没错,真正容易误解的是: 一层不等于一个进程,一套 API 也不等于一段始终在本地执行的代码。

从最上面的应用代码往下看,Activity、Service、View 和业务代码通常运行在应用自己的 Linux 进程中。 应用直接调用的 Context、WindowManager、ActivityManager 等对象,也有一部分代码在应用进程里执行。 它们负责提供稳定 API,可能做参数整理、状态缓存或请求封装。
但设备级状态不能由每个 App 各管一份。应用生命周期、任务与进程、全局窗口状态等能力需要统一协调, 所以 Android 把许多主要 Java 系统服务放进 system_server。AMS、ATMS、WMS 属于这一类。这里先记住 边界:Framework API 是应用看到的入口,系统服务才可能是全局状态的实际管理者。两者可能通过 Binder 连接,也可能存在本地调用;不能只看类名判断。
再往下是 Native 服务和运行库。SurfaceFlinger 是独立进程中的 Native 服务,应用进程和 system_server 也会加载 Native 库。于是又出现一个常见误判:看到 C/C++ 就认为发生了跨进程。 其实 Native 描述代码形态和运行环境,是否跨进程还得看后续有没有 IPC。
Linux Kernel 提供进程调度、虚拟内存、文件系统和设备驱动。用户空间进程通过系统调用进入内核; Binder 驱动也在这里。不过“进入内核”和“进入另一个服务进程”是两种边界,排查时不能混写。
所以,Android Framework 不是某一个类,也不只是一个 Java API 包。对刚开始读源码的人,更实用的 理解是:它是一组连接应用与系统能力的 API、系统服务和协作机制,代码分布在 Java、Native 与内核相关 模块中,运行时也会落在不同进程和线程里。
从 AOSP 根目录找到 Framework
知道系统分层后再打开 AOSP,第二个坑马上就来了:frameworks/base 很重要,但它不是整个 Android Framework。
AOSP 根目录按源码模块和构建边界组织。Java API、Java 系统服务、Native 基础库、媒体、运行时、HAL 和内核并不放在同一个目录。排查问题时,更可靠的做法是先根据职责缩小目录范围,再结合调用上下文确认 代码最终运行在哪里。
下面这张表不是目录百科,而是一张“第一次应该去哪里找”的索引:
| AOSP 目录 | 主要负责什么 | 第一次可以看的入口 | 典型运行位置 |
|---|---|---|---|
frameworks/base/ | Java Framework API、主要 Java 系统服务、系统资源与部分命令 | core/java/、services/、packages/ | 应用进程、system_server 等 |
frameworks/native/ | Native Framework 基础库、Native Binder、Surface 与图形合成服务 | libs/binder/、libs/gui/、services/surfaceflinger/ | 应用或系统进程加载的 Native 库、SurfaceFlinger 进程 |
frameworks/av/ | 音视频采集、播放、编解码、媒体服务及相关客户端库 | media/、services/ | 应用进程、媒体相关服务进程 |
packages/modules/ | 通过 Mainline 等机制模块化交付的系统能力 | Connectivity/、Permission/ | 取决于模块,可能进入应用、系统服务或独立进程 |
system/core/ | Android 用户空间的基础程序和库,例如 init、adb、日志 | init/、adb/、liblog/ | init、adbd 及加载相关库的进程 |
art/ 与 libcore/ | ART 运行时、DEX 执行、垃圾回收,以及 Java 核心类库实现 | art/runtime/、libcore/ojluni/ | 每个使用 ART 的 Java 进程 |
hardware/interfaces/ | Framework 与硬件实现之间的标准 HAL 接口定义 | 各能力目录下的 AIDL/HIDL 接口 | Framework 客户端与 HAL 服务进程之间 |
| 内核源码 | 进程、内存、文件系统、设备驱动和 Binder 驱动 | drivers/android/ | Linux Kernel 内核空间 |
实际查代码时,我更建议先按问题类型选入口。
如果问题来自 App 使用的 Java API,先看 frameworks/base/core/java/。如果涉及 AMS、WMS 这类主要 Java 系统服务,再转到 frameworks/base/services/。图形、Native Binder 或 Surface 相关问题通常会 继续进入 frameworks/native/;媒体问题再看 frameworks/av/;运行时和核心类库分别从 art/、 libcore/ 缩小范围。
这套顺序的作用是减少无效搜索,不是给目录和进程做固定配对。Mainline 模块化还在持续调整代码边界, 一部分能力位于 packages/modules/。内核也可能来自单独的 Android Common Kernel 或设备厂商仓库, 不一定和平台源码放在同一个 checkout 中。
源码目录不等于运行进程
这是整篇文章最容易在实际排查中用到的结论。

frameworks/base/core/java/ 构建出的类可能加载进应用进程,也可能加载进 system_server; frameworks/native/libs/ 中的库也会被多个进程使用。目录回答的是“代码在哪里维护”,进程回答的是 “构建后的代码此刻在哪里执行”。这两个问题有关联,但不是一一对应。
反过来也一样。知道异常发生在 system_server,不能只搜索一个源码目录,因为这个进程同时会加载 Framework Java 类、ART、Native 库以及模块化组件。只用进程名猜源码位置,通常会漏掉真正的调用节点。
这里有个实用判断:
- 已知类名或接口时,先从源码路径确认它属于哪个模块,再沿调用方和实现方判断进程。
- 已知崩溃进程或 ANR 进程时,先看线程栈和调用上下文,再回到对应源码模块。
- 已知的是用户现象时,先找最靠近现象的稳定入口,不要一上来全局搜索一个宽泛词。
这种顺序能避免两个极端:只按目录读源码,看不见运行边界;只盯进程和日志,又找不到代码是从哪里构建出来的。
用一次窗口请求练习定位
回到开头的 getSystemService(WindowManager.class)。这篇概览不追具体方法内部,只用它演示应该怎样 缩小范围:
应用侧 WindowManager / Context API
→ frameworks/base/core/java/(应用进程中的 Java Framework 入口)
→ frameworks/base/services/(system_server 中的 WMS 等服务)
→ frameworks/native/libs/gui/ 与 services/surfaceflinger/
(进程内 Native 客户端能力或 SurfaceFlinger 独立进程)
→ 内核显示驱动、Binder 驱动等能力这不是说每个窗口 API 都会严格走完这些目录,也不是说 WMS 直接负责图形合成。它表达的是排查顺序: 先确认应用侧入口,再找管理全局状态的系统服务;如果问题已经进入图形提交或合成阶段,再继续追 Native 服务和内核能力。
如果窗口焦点不对,只在 View 或 Activity 中改代码通常不够,因为全局窗口状态由系统侧管理。反过来, 如果应用根本没有正确提交窗口请求,一开始就去改 WMS 风险更大,也很难维护。先判断链路停在哪一层, 再决定改 App 还是 Framework,这是源码阅读和实际改系统时都要守住的边界。
跨进程机制见 Binder 通信,窗口职责见 WindowManagerService,图形合成职责见 SurfaceFlinger 概念篇。
一次请求到底跨了什么边界
Framework 代码里经常同时出现 Handler、Binder、JNI 和系统调用。它们都能让执行位置发生变化,但变化 的维度不同。把它们统称为“系统处理”以后,调用链就失去了定位价值。

普通本地调用不会自动切线程,也不会自动跨进程。方法名叫 start、send 或 request,都不能作为 边界证据。
Handler解决同一进程内的线程协作。消息进入目标线程关联的队列,之后由目标线程取出执行。它跨的是 线程,不负责把请求送到另一个进程。
Binder用于进程间通信。调用方看起来可能仍像在调用一个方法,但服务端代码运行在另一个进程,并有 自己的线程上下文。阅读 Binder 链路时,至少要把调用进程、服务进程和两边线程分开记录。
JNI跨越 Java/Kotlin 与 C/C++ 的语言边界。Native 库如果加载在当前进程里,调用仍可能留在同一个 进程和线程;后续是否跨进程,要看有没有继续使用 Binder 等 IPC。
系统调用把执行从用户空间带入内核。应用进程、system_server 和独立 Native 服务都属于用户空间, 它们需要文件、内存、调度或驱动能力时才进入内核。进入内核不等于进入另一个用户空间服务。
工程上最常见的问题不是完全不知道这些概念,而是画调用链时只写类名,没把边界写在线上。等到排查 ANR、死锁或状态不同步,再回头猜线程和进程,成本会高很多。
以后读 Framework 调用链,按四个维度记
遇到一条长链,不要急着抄满屏方法名。先给每个关键节点写一行:
[系统层] [进程] [线程] 类.方法()跨过边界时,再在连接线上标记 Handler、Binder、JNI、回调或“系统调用”。如果当前源码只能证明 到某个节点,就停在那里,把后面写成待确认,不要用经验补齐。
一份能用于排查的笔记,至少应该回答下面几个问题:
- 请求从哪个 App API、系统事件或日志现象开始?
- 当前节点真正运行在哪个进程、哪个线程?
- 这一跳传递的是方法调用、消息、Binder 事务,还是语言/内核边界?
- 哪个对象持有状态,状态在什么条件下变化?
- 如果结果不对,当前链路上最后一个有证据的正常节点在哪里?
这套记录方式比背一串类名更慢一点,但后面查问题会省很多时间。它能直接告诉你该看应用日志、 system_server 线程栈、Native 服务状态,还是内核侧证据。
读完这篇,先确认三个判断
frameworks/base是重要入口,但不能代表整个 Android Framework。- Framework API、系统服务、源码目录和运行进程是四个不同维度,不能直接互相替换。
- Handler、Binder、JNI 和系统调用跨越的边界不同,调用链必须明确标出来。
如果这三点已经能用自己的话解释,下一篇就可以开始建立第一条系统时间线;如果还混在一起,先回到 三张图,把任意一个熟悉 API 的系统层、源码目录和运行位置分别标出来。
本章涉及的源码指针
本章只保留能承接后续专题的代表入口,不在这里展开内部实现:
| 路径 | 后续阅读问题 |
|---|---|
frameworks/base/core/java/android/content/Context.java | 应用看到的 Framework 能力入口如何定义 |
frameworks/base/services/java/com/android/server/SystemServer.java | 主要 Java 系统服务如何被组织和启动 |
frameworks/native/libs/binder/ | Java 服务之外的 Native Binder 基础能力如何组织 |
frameworks/native/services/surfaceflinger/ | 独立 Native 图形服务如何组织 |
frameworks/av/media/ | Android 媒体能力的客户端与公共实现从哪里进入 |
system/core/init/ | Android 用户空间的第一个进程如何建立运行环境 |
art/runtime/ 与 libcore/ojluni/ | Java 代码依赖的运行时和核心类库如何实现 |
hardware/interfaces/ | Framework 与硬件服务之间的标准接口在哪里定义 |
drivers/android/binder.c | Binder 驱动如何承接用户空间事务 |
源码基准为 Android 14 android-14.0.0_r75。系统分层与进程模型可对照 Android 官方的 AOSP 架构概览、 Binder 概览和 进程与线程概览。
下一步:从开机时间线继续
第一张地图有了,下一步先看系统怎样把这些层逐步拉起来: Android 系统如何从按下电源走到桌面。