Android 整机系统开发到底要学什么?

330 阅读14分钟

Android 整机系统开发到底要学什么?

很多人一听到 Android 开发,第一反应是 App 开发:Activity、Fragment、View、Jetpack、网络请求、数据库、性能优化。但如果进入的是整机系统开发,面对的问题会完全不同。

整机系统开发关注的不是“如何写一个 App”,而是“如何让一台 Android 设备作为一个完整系统稳定运行”。它要处理的是 Framework、Native Service、HAL、Vendor、Kernel、Modem、权限、安全、编译、系统服务、日志分析、版本差异、厂商定制、运营商需求,以及各种跨模块问题。

所以,Android 整机系统开发到底要学什么?它不是简单地多看几份源码,也不是把 Android 所有模块都背下来,而是要建立一套系统视角:知道一台设备从开机到应用运行,中间经过了哪些层;知道问题发生时,应该从哪个层级切入;知道不同模块之间如何通信、如何协作、如何被调试。

一、先建立整体分层:Android 不是一个单层系统

学习整机系统开发,第一步不是直接钻进某个源码文件,而是先建立 Android 的整体分层模型。

可以粗略理解为:

image-20260705124610005.png

App 层负责用户可见的功能,比如短信、电话、设置、相机、蓝牙入口等。

Framework 层提供系统能力的统一抽象,比如 ActivityManager、PackageManager、TelephonyManager、ConnectivityManager、PowerManager 等。

System Server 是大量核心系统服务的运行容器。很多 Framework 层能力最终都落到 System Server 中的具体 Service。

Native Service 则承载更底层、更贴近系统资源的服务,例如 SurfaceFlinger、AudioFlinger、netd、vold、installd 等。

HAL 是 Android Framework 和厂商硬件实现之间的接口边界。Framework 不应该直接关心具体硬件怎么实现,而是通过 HAL 访问厂商能力。

Kernel 和 Driver 则负责进程调度、内存、文件系统、网络协议栈、设备驱动、中断、电源管理等底层能力。

整机系统开发最重要的能力之一,就是知道一个问题可能位于哪一层,而不是看到现象就直接猜结论。

比如“网络不可用”这个现象,可能是 App 没有权限,可能是 Framework 状态机异常,可能是 netd 配置问题,可能是 DNS 问题,可能是 modem 注册状态异常,也可能是运营商网络侧行为导致。系统开发不能只看表面现象,而要逐层建立证据链。

延伸阅读

二、必须理解进程、线程和 Binder

Android 系统不是一个单进程程序。系统里有大量进程:普通 App 进程、system_server、surfaceflinger、netd、vold、mediaserver、vendor 进程、hal 进程等。

这些进程之间需要通信,而 Android 最核心的跨进程通信机制就是 Binder。

如果不了解 Binder,很容易出现几个典型误解:

第一,把远程服务当成本地对象理解。

第二,把 handle 当成真实对象地址理解。

第三,以为 Framework 调用某个 Manager 方法,就一定是在当前进程完成全部逻辑。

第四,不清楚 ServiceManager、BpBinder、BBinder、BnInterface、binder_node、binder_ref 之间的关系。

整机系统开发并不要求一开始就把 Binder 驱动每一行代码都看懂,但至少要理解:

客户端拿到的是代理对象
服务端持有的是真实服务对象
ServiceManager 负责服务注册和查询
Binder Driver 负责跨进程通信和引用关系维护

很多系统问题本质上都是跨进程调用链问题。比如 App 调用 Framework API,Framework 通过 Binder 进入 system_server,system_server 再调用 native service 或 HAL,最后返回结果。任何一个节点异常,都可能表现为上层功能失败。

所以学习 Android 系统,Binder 是主干,不是细节。 binder-ipc-flow.png

延伸阅读

三、必须理解 Handler、Looper 和系统线程模型

Android Framework 大量逻辑运行在消息循环之上。应用主线程有 Looper,system_server 中很多系统服务也有自己的 HandlerThread。

理解 Handler 不是为了背 API,而是为了理解系统如何“排队处理事情”。

一个系统服务经常会面对多种事件来源:

Binder 调用
广播
定时任务
底层回调
状态机事件
配置变化
用户操作

这些事件不可能全部在同一个调用栈里立即完成。很多时候,系统会把事件封装成 Message,投递到某个 Handler,由对应线程串行处理。

这就引出了几个重要问题:

某个逻辑到底在哪个线程执行?

为什么不能在 Binder 线程里做耗时操作?

为什么有些状态不是马上变化,而是异步更新?

为什么 log 看起来顺序不符合直觉?

为什么某个回调触发了,但最终状态没有变化?

如果不理解 Handler 和 Looper,很容易只看到函数调用,而看不到真正的执行时序。整机系统开发里,时序问题、异步问题、状态机问题非常常见,这些都离不开线程和消息机制。

handler-looper-queue.png

延伸阅读

四、必须理解 System Server 和核心系统服务

System Server 是 Android 系统中非常核心的进程。很多 Framework 能力都由 system_server 中的系统服务提供。

常见服务包括:

ActivityManagerService
PackageManagerService
WindowManagerService
PowerManagerService
DisplayManagerService
ConnectivityService
TelephonyRegistry
NotificationManagerService
InputManagerService

学习这些服务时,不建议一开始就平铺式阅读源码。更好的方式是从问题入口进入。

比如:

应用为什么能启动?

权限是在哪里检查的?

应用安装后 Package 信息如何被系统识别?

网络状态变化如何通知到应用?

亮灭屏状态如何传递?

输入事件如何分发?

电话状态如何广播给上层?

每个问题都可以牵出一条系统链路。链路看多了,System Server 的结构自然会变清晰。

整机系统开发者不一定要成为每个服务的专家,但要知道核心服务分别负责什么,遇到问题时应该先查哪个服务、哪个 log、哪个 dumpsys。

system-server-services.png

延伸阅读

五、必须理解 Native Service 和 HAL 边界

Android 并不是全部由 Java 实现。越靠近系统资源和硬件,C++ 与 Native 层越重要。

例如:

SurfaceFlinger 负责图形合成。

AudioFlinger 负责音频相关处理。

netd 负责网络配置相关能力。

vold 负责存储卷管理。

installd 负责应用安装相关的底层操作。

这些服务通常通过 Binder、Socket、HIDL、AIDL HAL 等机制与上层或厂商实现通信。

学习 Native Service 的关键是理解“边界”:

Framework 到底负责什么?

Native Service 到底负责什么?

HAL 到底负责什么?

Vendor 实现到底负责什么?

Kernel Driver 到底负责什么?

整机系统开发中,很多争议都发生在边界处。一个问题到底归 Framework、Vendor、Modem、Kernel、网络侧还是 App?这不能靠感觉判断,而要靠调用链、状态机、日志和对系统边界的理解。

native-hal-boundary.png

延伸阅读

六、必须补 Linux 基础

Android 是建立在 Linux Kernel 之上的系统。做整机系统开发,如果完全不懂 Linux,很容易卡在底层问题上。

需要掌握的 Linux 基础包括:

进程、线程、调度、内存、文件描述符、Socket、epoll、权限、SELinux、日志、设备节点、文件系统、网络协议栈、驱动基本概念。

这些知识不一定要一开始学到内核专家级别,但至少要能理解:

进程为什么会卡住?

线程为什么会死锁?

fd 泄漏是什么?

socket 通信如何定位?

epoll 为什么常见于 native service?

SELinux denied 为什么会导致功能失败?

设备节点权限为什么会影响 HAL?

系统资源不足为什么会造成随机异常?

Android 的很多问题表面在 Framework,根因却可能在 Linux 层。没有 Linux 基础,就很难把问题查到底。

linux-foundation.png

延伸阅读

七、必须掌握系统调试工具

整机系统开发不是只看代码,更重要的是会定位真实设备问题。

常用工具包括:

logcat
dmesg
bugreport
dumpsys
dumpsys activity
dumpsys package
dumpsys window
dumpsys power
dumpsys connectivity
dumpsys telephony.registry
ps / top
ss / netstat
getprop / setprop
cmd
service call
atrace / systrace / perfetto
tombstone
ANR traces

真正的调试能力不是知道这些命令的名字,而是知道什么时候用什么。

比如:

应用行为异常,先看 logcat 和 dumpsys activity。

网络状态异常,要看 ConnectivityService、netd、ip rule、路由、DNS、modem 状态。

系统卡顿,要看 trace、CPU、锁等待、主线程阻塞。

Native crash,要看 tombstone。

权限问题,要看 App 权限、系统权限、SELinux、UID、进程上下文。

服务不存在,要看 ServiceManager、init、进程是否启动、rc 配置、权限和崩溃记录。

整机系统开发的调试目标不是“找到一条可疑 log”,而是把现象、时间点、调用链、状态变化和责任边界串起来。

debug-evidence-chain.png

延伸阅读

八、必须理解编译、分区和版本

整机开发离不开版本管理和系统构建。

需要理解:

Android 编译系统如何组织模块?

system、vendor、product、odm、system_ext 分区分别放什么?

为什么同一个功能在不同项目、不同 Android 版本上表现不同?

GSI、VTS、CTS、兼容性要求意味着什么?

系统属性 property 如何影响功能开关?

overlay 和配置文件如何改变系统行为?

一套 Android 代码落到不同项目上,往往会有大量厂商定制和项目差异。如果不理解编译和分区,就容易出现“源码里明明是这样,设备上却不是这样”的困惑。

整机系统开发必须同时看源码和实际镜像,不能只相信代码仓库里的静态内容。

build-partitions-compat.png

延伸阅读

九、学习路线应该是 T 型结构

Android 整机系统太大,不可能一开始全部精通。更合理的方式是建立 T 型能力。

横向要知道系统分层和主要模块:

Framework
System Server
Binder
Handler
Native Service
HAL
Kernel
SELinux
Build
Debug Tools

纵向要选择一两个方向深入,比如:

Telephony

Connectivity

Audio

Display

Camera

Power

Package / Permission

Input

Storage

如果只横向了解,会变成“什么都知道一点,但无法解决深问题”。

如果只纵向钻一个模块,又容易被单一业务困住,看不到系统全局。

比较理想的状态是:

有一条自己熟悉的业务主线,同时不断把这条主线向上下游扩展。

例如做网络问题,就不能只看 Settings 里的开关,也要理解 ConnectivityService、NetworkAgent、netd、DNS、路由、iptables、modem 状态、运营商配置等。

例如做电话短信问题,就不能只看上层 UI,也要理解 Telephony Framework、RIL、IMS、Subscription、CarrierConfig、广播通知、数据库和权限。

t-shaped-learning-path.png

延伸阅读

十、最终要形成的是“问题定位模型”

Android 整机系统开发的核心能力,不是背源码,而是建立问题定位模型。

一个成熟的定位过程通常包括:

1. 明确现象:用户到底看到什么?
2. 确认范围:必现还是偶现?单项目还是多项目?单版本还是多版本?
3. 锁定时间点:异常发生在什么时候?
4. 建立链路:从上层入口到下层实现经过哪些模块?
5. 查状态:每一层当时的状态是否符合预期?
6. 查调用:关键调用有没有发生?返回值是什么?
7. 查边界:问题属于 App、Framework、Native、HAL、Kernel、Vendor、Modem 还是网络侧?
8. 给结论:结论必须由证据支撑,而不是猜测。

这也是整机系统开发和普通功能开发最大的区别之一。

普通功能开发更关注“如何实现”。

整机系统开发更关注“系统为什么表现成这样”。

problem-diagnosis-model.png

延伸阅读

结语:Android 整机系统开发学的是系统思维

Android 整机系统开发要学的东西很多,但可以总结成一句话:

它学的不是某一个 API,也不是某一个模块,而是如何理解一台 Android 设备作为完整系统运行的方式。

要学 Framework,因为它定义了系统能力的上层抽象。

要学 Binder,因为它连接了不同进程和服务。

要学 Handler,因为它解释了大量异步时序问题。

要学 System Server,因为核心系统服务大多运行在这里。

要学 Native Service 和 HAL,因为很多真实能力最终会落到系统底层和厂商实现。

要学 Linux,因为 Android 的根基仍然是操作系统。

要学调试工具,因为真实问题不会按照教程出现。

要学编译和分区,因为设备上的系统不是单一源码文件,而是一套复杂的工程产物。

最终,整机系统开发者要建立的是一种能力:面对一个复杂问题,能够从现象出发,沿着系统分层逐步拆解,找到证据,明确边界,给出可靠结论。

这就是 Android 整机系统开发真正要学的东西。

system-thinking-map.png

延伸阅读

  • AOSP Docs:后续继续扩展时,优先回到官方文档,而不是先找零散文章。
  • Android Code Search:系统思维最终要能被源码验证,Code Search 适合持续追踪调用链和版本差异。