Android系统架构深度解析:从Linux内核到Framework的分层设计与Binder通信机制

发布时间:2026/9/23 23:34:36
Android系统架构深度解析:从Linux内核到Framework的分层设计与Binder通信机制
1. 从一部手机说起Android 系统架构到底在解决什么问题很多人第一次接触 Android 系统架构是在面试或者看源码的时候。打开 AOSP 的目录看到frameworks、hardware、system、kernel一大堆文件夹瞬间就懵了。但如果你换一个角度——从你手里这部手机开机的那一瞬间开始想——事情会清晰很多。按下电源键屏幕亮起锁屏界面出现你滑动解锁点开微信发了一条消息。这短短几秒钟里至少有五六个不同层级的软件模块在协同工作引导程序加载内核内核初始化硬件驱动Native 层启动各种系统服务Framework 层拉起应用进程最后你的微信才出现在屏幕上。Android 系统架构本质上就是回答一个问题从硬件到应用这几层东西是怎么分工、怎么通信、怎么协作的。我做了十多年 Android 系统层开发从早期的 Android 4.4 一直跟到现在的 Android 15、16踩过的坑可以说遍布每一层。这篇文章不是教科书式的架构概述而是把我这些年对 Android 系统架构的理解、实操中遇到的真实问题、以及那些文档里不会写的经验系统地梳理一遍。无论你是刚入行的应用开发想往底层走还是做嵌入式想理解 Android 的全貌或者只是面试前想快速建立知识框架这篇内容都能给你一个可以直接参考的完整视角。核心关键词会贯穿全文Android、系统架构、Linux 内核、HAL、Framework。这五个词基本就是 Android 架构的骨架理解了它们之间的关系整个系统在你脑子里就是活的。2. Android 系统架构的整体分层设计2.1 五层架构的经典划分与背后的设计逻辑Google 官方给出的 Android 架构图是五层结构从下往上依次是Linux 内核层、硬件抽象层HAL、Native 库与 Android 运行时层、Java API Framework 层、系统应用层。这个划分不是随便定的每一层的存在都有明确的工程理由。先说最底层的Linux 内核。Android 选择 Linux 内核不是偶然2007 年 Android 立项的时候Linux 已经是一个成熟、稳定、驱动生态极其丰富的操作系统内核。用它做底座意味着 Android 不需要从零写驱动、写内存管理、写进程调度。内核层负责的东西很硬核进程调度、内存管理、网络协议栈、电源管理、以及各种硬件驱动显示、摄像头、蓝牙、音频等。你在应用层调用一个Camera.open()最终落到内核里就是摄像头驱动的寄存器操作。往上一层是HALHardware Abstraction Layer。这一层是 Android 架构里最容易被忽视、但工程价值极高的一层。它的核心作用是解耦Framework 层不需要知道具体硬件的实现细节只需要调用 HAL 提供的标准接口。比如摄像头 HAL 定义了camera_device_ops结构体里面有一组函数指针高通、联发科、三星各自实现自己的版本但上层调用方式完全一样。这就是为什么同一套 Android Framework 能跑在几百种不同硬件上。再往上是Native 层和 ART 运行时。Native 层用 C/C 写包含了一堆核心库libc、OpenGL ES、SQLite、WebKit、媒体框架等。ARTAndroid Runtime负责执行 Java/Kotlin 字节码早期是 DalvikAndroid 5.0 之后换成 ART引入了 AOT 预编译性能提升非常明显。每个应用进程都跑在自己的 ART 虚拟机实例里这是 Android 沙箱安全模型的基础。Java API Framework 层是应用开发者最熟悉的部分。ActivityManager、WindowManager、PackageManager、ContentProvider、NotificationManager 这些系统服务都在这一层。它们通过 Binder IPC 与底层服务通信向上提供 Java 接口。你写的startActivity()最终会通过 Binder 跨进程调用到 system_server 里的 ActivityManagerService。最上面是系统应用层包括桌面、设置、电话、相机这些预装应用。它们和第三方应用一样跑在 ART 上只是拥有更高的权限。2.2 为什么是分层而不是单体一次真实的架构权衡有人会问为什么要搞这么复杂的分层直接写一个大程序不行吗我举个实际例子你就明白了。假设你是一家手机厂商的工程师要支持一款新的指纹传感器。如果 Android 是单体架构你需要改动 Framework 里所有跟指纹相关的代码还要保证不影响其他功能风险极高。但在分层架构下你只需要做两件事写一个符合指纹 HAL 接口规范的.so库然后在 Framework 层配置一下加载路径。上层代码一行不用改其他厂商的指纹模块也完全不受影响。这就是分层的价值变更隔离。每一层只依赖下一层的接口不依赖实现。接口稳定实现随便换。Android 能形成今天这么庞大的设备生态分层设计功不可没。但分层也有代价。最直接的就是性能开销一次跨层调用可能涉及多次 IPC、序列化、反序列化。比如你从应用层读一个传感器数据路径是 App → Framework → SensorService → HAL → 内核驱动中间要过好几次 Binder。所以 Android 在性能敏感的场景如音频、图形渲染会尽量让数据走共享内存或者直接 Native 调用绕开 Java 层。另一个代价是调试复杂度。一个 bug 可能出现在任何一层定位起来需要你对整个调用链有清晰的认识。这也是为什么系统层开发的门槛比应用层高——你得同时懂 Java、C、C、甚至汇编和内核。2.3 各层之间的通信机制Binder 是绝对主角Android 各层之间怎么通信答案是Binder。这是 Android 架构里最重要的一个机制没有之一。Binder 是一个基于内核的 IPC进程间通信框架。它的核心是一个内核驱动/dev/binder所有跨进程调用都通过它中转。相比传统的管道、Socket、共享内存Binder 的优势是一次拷贝数据从发送方用户空间拷贝到内核接收方直接映射内核缓冲区、支持远程对象引用、自带线程池管理。在架构层面Binder 贯穿了 Framework 层和 Native 层。你在 Java 层拿到的ActivityManager对象其实是一个 Binder Proxy真正的实现在 system_server 进程里。你调用它的方法参数会被 Parcel 序列化通过 Binder 驱动传到 system_server那边反序列化后调用真实方法返回值再原路返回。理解 Binder 是理解 Android 架构的关键。我见过太多应用开发者写了几年代码却不知道getSystemService()背后发生了什么。一旦你理解了 Binder很多玄学问题就迎刃而解了——比如为什么跨进程传大 Bitmap 会崩Binder 事务缓冲区只有 1MB为什么某些系统服务调用会阻塞主线程。3. Linux 内核层Android 的地基3.1 Android 对标准 Linux 内核做了哪些改造Android 用的 Linux 内核不是原版Google 做了不少定制。这些定制主要集中在几个方面Binder 驱动。前面说了这是 Android IPC 的核心标准 Linux 内核里没有是 Android 特有的。它注册为/dev/binder字符设备提供ioctl接口给用户空间调用。Ashmem匿名共享内存。标准 Linux 有mmap和shm但 Android 需要一种更灵活、可回收的共享内存机制于是有了 Ashmem。它允许内核在内存紧张时回收某些共享内存页这对内存受限的移动设备很重要。不过从 Android 10 开始Ashmem 逐渐被标准的memfd替代。Low Memory KillerLMK。移动设备内存有限当内存不足时需要杀掉一些后台进程。标准 Linux 有 OOM Killer但它的策略不适合 Android 的场景。LMK 根据进程的oom_adj值后来改成oom_score_adj来决定杀谁前台进程优先级最高后台进程最先被杀。Android 10 之后 LMK 被移到用户空间叫 LMKD。Wakelock。这是 Android 电源管理的核心机制。标准 Linux 的休眠策略比较简单Android 需要更精细的控制应用可以申请 Wakelock 阻止系统休眠比如你正在听音乐或者下载文件。这个机制在内核里实现为/sys/power/wake_lock接口。日志系统Logger。Android 有自己的日志驱动提供logcat功能。不过新版本也逐渐迁移到pstore和debugfs。这些改造让 Linux 内核更适合移动场景但也带来一个问题Android 内核和上游 Linux 的同步变得困难。每次 Linux 发布新版本Google 都要把 Android 的补丁 rebase 上去工作量巨大。这也是为什么 Android 设备的内核版本往往落后于最新 Linux 好几年。3.2 内核驱动与硬件交互的实操细节做系统移植的时候最常打交道的就是内核驱动。我拿一个真实场景举例调试一块新的触摸屏。首先你要在设备树Device Tree里配置 I2C 总线地址和中断引脚。设备树是 ARM 架构下描述硬件的方式编译成.dtb文件由 bootloader 传给内核。配置大概长这样i2c1 { touchscreen38 { compatible vendor,touch-ft5x06; reg 0x38; interrupt-parent gpio1; interrupts 4 IRQ_TYPE_EDGE_FALLING; reset-gpios gpio1 5 GPIO_ACTIVE_LOW; }; };然后写驱动注册 input 设备在中断处理函数里读取触摸坐标通过input_report_abs()上报给 input 子系统。内核的 input 子系统会把这些事件通过/dev/input/eventX暴露给用户空间。用户空间这边Android 的EventHub在frameworks/native/services/inputflinger里会监听这些设备节点把原始事件转换成 Android 的MotionEvent再通过 InputDispatcher 分发给应用。这个链路很长任何一环出问题触摸都会失效。我踩过的坑包括设备树中断类型配错应该下降沿配成了高电平、I2C 地址冲突、驱动里坐标轴方向搞反、HAL 层没有正确上报ABS_MT_POSITION_X等。调试的时候getevent命令是你的好朋友它能直接打印/dev/input的原始事件帮你判断问题出在内核还是上层。3.3 内核版本选择与厂商定制的现实考量选内核版本是个技术活。理论上越新越好新版本有更好的性能、更多的驱动支持、更少的安全漏洞。但现实中你往往被 SoC 厂商绑死。高通、联发科这些 SoC 厂商会基于某个 Linux LTS 版本做自己的 BSPBoard Support Package然后手机厂商再基于 BSP 做定制。比如某款芯片用的是 Linux 5.10那你就只能用 5.10想升到 6.1 得等 SoC 厂商更新 BSP而他们通常只在旗舰芯片上做这种更新。这就导致一个尴尬的局面中低端设备的内核可能停留在三四年前的版本安全补丁靠 backport 打。作为系统工程师你能做的是定期同步上游的 CVE 修复、裁剪不需要的驱动减小攻击面、开启内核加固选项如CONFIG_STACKPROTECTOR、CONFIG_FORTIFY_SOURCE。还有一个现实问题是GKIGeneric Kernel Image。从 Android 12 开始Google 推行 GKI把内核分成通用的核心镜像和厂商的模块。这样 Google 可以独立更新内核核心不用等 SoC 厂商。这个方向是对的但过渡期很痛苦很多厂商的驱动还没完全模块化兼容性问题不少。4. HAL 层硬件与框架的翻译官4.1 HAL 的演进从传统 HAL 到 HIDL 再到 AIDLHAL 这一层这些年变化最大值得单独讲讲。传统 HALLegacy HAL是 Android 8.0 之前的做法。每个 HAL 就是一个.so库Framework 通过dlopen加载然后dlsym拿到hw_module_t结构体调用里面的函数指针。这种方式简单直接但问题很多HAL 和 Framework 跑在同一个进程里HAL 崩溃会拖垮整个系统服务HAL 接口没有版本管理升级困难不同厂商的 HAL 实现五花八门兼容性差。HIDLHAL Interface Definition Language是 Android 8.0 引入的。它把 HAL 定义成接口文件.hal用hidl-gen工具生成 C 或 Java 的桩代码。HAL 实现跑在独立的进程里叫hwservicemanager管理的 binderized HAL通过 Binder 通信。这样 HAL 崩溃不会影响 Framework接口也有了版本管理比如android.hardware.camera2.4。AIDL for HAL是 Android 11 之后推的方向。Google 发现 HIDL 和 AIDL 两套 IPC 机制维护成本太高干脆统一用 AIDL。新的 HAL 都用 AIDL 定义HIDL 逐步废弃。AIDL HAL 的好处是复用了成熟的 AIDL 工具链支持稳定版本stable AIDL而且 Java 和 C 都能用。这个演进过程反映了一个趋势Android 越来越重视模块化和可维护性。从单体到进程隔离从私有接口到标准化 IDL每一步都是为了让这个庞大的系统更容易演进。4.2 一个摄像头 HAL 的完整实现思路我拿摄像头 HAL 举例讲讲一个 HAL 模块从零到能用的完整过程。这是我在一个定制项目里真实做过的。首先定义接口。如果用 AIDL你会写一个ICameraProvider.aidl里面定义getCameraIdList()、getCameraDeviceInterface()等方法。用aidl工具生成桩代码后你实现BnCameraProvider这个类。核心工作是实现ICameraDevice和ICameraDeviceSession。前者负责打开摄像头、配置流后者负责实际的帧捕获。在configureStreams()里你要根据上层请求的分辨率、格式配置 ISP图像信号处理器的输出通道。在processCaptureRequest()里你要把请求下发给驱动等待帧数据回来再通过ICameraDeviceCallback回调给上层。这里最麻烦的是缓冲区管理。摄像头数据量很大1080p 一帧就是几 MB不能每次都拷贝。Android 用gralloc分配图形缓冲区HAL 直接把数据写进这个缓冲区上层通过ANativeWindow拿到。gralloc 的实现又依赖具体的 GPU 和显示驱动所以这块经常出问题——比如缓冲区格式不匹配、stride 对齐错误导致图像花屏。调试摄像头 HAL我常用的手段是先用v4l2-ctl直接测试驱动能不能出图排除内核问题然后在 HAL 里加日志打印每一帧的时间戳和缓冲区地址最后用dumpsys media.camera看 Framework 层的状态。这三步基本能定位 90% 的问题。4.3 HAL 开发中的常见陷阱与调试手段做 HAL 开发有几个坑几乎人人都会踩。第一个是接口版本不匹配。Android 的 HAL 接口是带版本的Framework 期望2.4版本你实现了2.3编译能过但运行时找不到接口。解决办法是仔细看manifest.xml里的配置确保 HAL 声明的版本和 Framework 请求的一致。第二个是 SELinux 权限。Android 从 5.0 开始强制 SELinuxHAL 进程有自己的域domain访问设备节点、文件、socket 都需要相应的策略。新手经常遇到 HAL 启动失败看 logcat 只有一句avc: denied。这时候要用audit2allow工具根据 avc 日志生成策略规则加到sepolicy里。第三个是进程生命周期。Binderized HAL 是懒加载的第一次被调用时才启动空闲一段时间后会被杀掉。如果你的 HAL 有初始化开销大的问题比如要加载固件每次重启都会卡一下。解决办法是在manifest.xml里配置oneshotfalse并设置合理的priority或者用init.rc里的class让它常驻。第四个是并发问题。HAL 会被多个客户端同时调用比如相机和录像可能同时请求。你的实现必须线程安全该加锁的地方加锁。我见过一个 bug两个客户端同时配置流导致 ISP 寄存器状态错乱图像直接黑屏。后来加了互斥锁才解决。调试 HAL 的工具链logcat看日志、dumpsys看状态、strace跟踪系统调用、perfetto做性能分析。如果怀疑是 Binder 通信问题可以打开 Binder 的 debug 开关看事务的详细过程。5. Framework 层应用开发者的主战场5.1 四大组件背后的系统服务支撑应用开发者天天用 Activity、Service、BroadcastReceiver、ContentProvider但很少有人深究它们背后是谁在支撑。答案是system_server 进程里的一堆系统服务。ActivityManagerServiceAMS是四大组件的中枢。你调用startActivity()请求通过 Binder 到 AMSAMS 负责决定要不要启动、启动在哪个进程、怎么调度。它还管理着所有进程的生命周期和优先级。AMS 是 system_server 里最复杂的服务之一代码量巨大逻辑盘根错节。WindowManagerServiceWMS管窗口。每个 Activity 对应一个窗口WMS 负责窗口的层级、位置、大小、动画。你看到的转场动画、状态栏、导航栏都是 WMS 在调度。WMS 和 SurfaceFlingerNative 层的合成服务配合把各个窗口的内容合成到屏幕上。PackageManagerServicePMS管应用安装和包信息。你getPackageManager().getPackageInfo()拿到的数据就是 PMS 在开机时扫描/data/app和/system/app建立起来的。PMS 还负责权限管理、组件解析。ContentProvider的底层是ActivityManagerService和ContentService。跨进程访问 ContentProvider 时AMS 负责找到目标进程并建立连接实际的数据传输走 Binder。理解这些服务的存在能帮你解释很多现象。比如为什么应用启动慢——因为要经过 AMS 的一系列检查、进程创建、Application 初始化。为什么后台 Service 会被杀——因为 AMS 根据内存压力调整进程优先级。5.2 Binder 机制在 Framework 中的实际运用Binder 在 Framework 层无处不在但它的使用有一套固定模式理解了这套模式看源码就轻松了。以ActivityManager为例。客户端调用ActivityManager.getService().startActivity(...)。getService()返回的是一个IActivityManager接口的 Proxy 对象。这个 Proxy 是ActivityManagerService的远程代理它的startActivity()方法会把参数写进 Parcel然后调用transact()通过 Binder 驱动发送。服务端这边ActivityManagerService继承自IActivityManager.StubonTransact()方法会根据 transaction code 分发到具体的实现方法。参数从 Parcel 里读出来调用真正的startActivity()返回值再写回 Parcel。这套机制的关键是AIDL 自动生成的代码。你定义IActivityManager.aidl编译时会生成IActivityManager.java里面包含Stub服务端基类和Proxy客户端代理。手写这套代码很容易出错所以 Android 大量使用 AIDL。有一个细节值得注意Binder 事务是同步的。客户端调用transact()后会阻塞直到服务端返回。这意味着如果你在主线程调用一个耗时的系统服务方法就会 ANR。所以 Android 提供了oneway关键字标记为 oneway 的方法调用后立即返回不等结果。比如IActivityManager里很多通知类的方法都是 oneway 的。还有一个坑是Binder 事务缓冲区大小。每个进程的 Binder 缓冲区默认是 1MB所有并发事务共享。如果你传一个 2MB 的 Bitmap 跨进程直接抛TransactionTooLargeException。解决办法是用 Ashmem 或者文件描述符传递大数据只传一个引用。5.3 系统服务的启动流程与定制修改system_server 是 Android 启动过程中最关键的进程它承载了几乎所有 Java 系统服务。理解它的启动流程对做系统定制非常重要。启动从Zygote开始。Zygote 是 Android 的进程孵化器开机时由 init 进程启动预加载了 Framework 的类和资源。当需要启动 system_server 时Zygote fork 出一个新进程执行SystemServer.main()。SystemServer.main()里会依次启动三类服务引导服务ActivityManagerService、PackageManagerService、PowerManagerService 等、核心服务WindowManagerService、DisplayManagerService 等、其他服务CameraService、AudioService 等。每个服务启动时都会调用ServiceManager.addService()注册到 ServiceManager这样其他进程才能通过名字找到它。启动顺序是有讲究的。比如 AMS 必须在 PMS 之后启动因为 AMS 需要 PMS 提供包信息。WMS 必须在 AMS 之后因为 WMS 需要 AMS 提供 Activity 信息。这个依赖关系在SystemServer.java里通过代码顺序保证。做系统定制时经常需要在这里加东西。比如你要加一个自己的系统服务就在startOtherServices()里加一行ServiceManager.addService(myService, new MyService())。但要注意加服务会增加开机时间而且如果服务初始化失败会拖垮整个 system_server导致设备起不来。所以我的经验是能不加就不加能延迟初始化就延迟。还有一个常见的定制需求是修改系统服务的默认行为。比如改默认亮度、改默认语言、改默认动画速度。这些通常在frameworks/base/core/res/res/values/config.xml里配置或者通过SettingsProvider的默认值设置。改完要重新编译 framework-res.apk刷机验证。6. 从架构视角排查真实问题6.1 应用崩溃如何一路追溯到内核我讲一个真实的排查案例展示如何用架构思维定位问题。现象某款设备上某个应用打开相机后偶尔崩溃logcat 显示FATAL EXCEPTION在Camera.open()附近。第一步看应用层日志。异常是CameraAccessException说明相机服务拒绝了请求。但为什么拒绝应用层看不出来。第二步看 system_server 日志。dumpsys media.camera显示相机设备被占用。但谁占用的继续查。第三步看 camera service 日志。发现有一个之前的会话没有正确关闭导致设备一直处于 busy 状态。为什么没关闭因为那个进程被杀了但 HAL 没有收到通知。第四步看 HAL 日志。发现 HAL 在等待一个永远不会到来的回调卡住了。为什么卡住因为内核驱动在某个 ioctl 上阻塞了。第五步看内核日志。dmesg显示摄像头驱动的 I2C 通信超时。原来是硬件接触不良导致驱动重试多次后卡死。这个案例说明一个应用层的崩溃根因可能在内核。如果你只懂应用层永远找不到真正的问题。架构知识在这里的价值就是让你知道每一层该看什么日志、该用什么工具、该怀疑什么。6.2 性能问题的分层定位方法性能问题同样需要分层定位。我总结了一套方法先看现象。是启动慢、滑动卡、还是耗电快不同现象指向不同的层。再看指标。用perfetto抓 trace看 CPU 占用、线程状态、Binder 调用。如果是 UI 卡顿看 SurfaceFlinger 的合成时间、RenderThread 的绘制时间。如果是启动慢看 AMS 的启动流程、应用的 Application 初始化。然后分层排查。应用层看有没有主线程 IO、有没有过度绘制Framework 层看系统服务有没有锁竞争、有没有频繁 GCNative 层看有没有内存拷贝、有没有锁等待内核层看有没有 CPU 调频问题、有没有 IO 阻塞。我遇到过一个典型案例某应用滑动列表卡顿。应用层优化了半天没用。后来用 perfetto 一看发现是 WMS 在处理输入事件时持有了一个大锁导致 InputDispatcher 阻塞。再往下查是某个系统服务的 Binder 调用超时。最后定位到是 HAL 层的一个传感器读取操作太慢拖累了整个输入链路。这种问题没有架构视角根本无从下手。6.3 系统定制中的架构决策经验做系统定制经常面临架构层面的决策。我分享几个经验。要不要改 Framework。改 Framework 影响面大升级困难能不改就不改。优先考虑用 HAL 或者应用层解决。比如你要加一个自定义的硬件功能优先做成 HAL通过标准接口暴露给应用。要不要加系统服务。加服务会增加开机时间和内存占用而且一旦出问题影响全局。如果功能简单考虑做成一个 Native 守护进程或者用现有的服务扩展。怎么保证兼容性。Android 的 CTSCompatibility Test Suite会检查系统是否符合规范。你改的东西如果影响了 CTS 测试项设备就过不了认证。所以改之前一定要跑 CTS确认没有破坏标准行为。怎么处理版本升级。Android 每年一个大版本API 和行为都在变。定制代码要尽量用稳定的接口避免依赖内部实现。我见过太多项目因为用了私有 API升级时全部推倒重来。7. 常见问题速查与避坑清单7.1 各层典型问题对照表层级典型问题排查工具常见原因应用层崩溃、ANRlogcat、StrictMode主线程 IO、内存泄漏Framework服务无响应、死锁dumpsys、perfetto锁竞争、Binder 超时Native内存泄漏、崩溃valgrind、asan野指针、缓冲区溢出HAL设备打不开、数据异常logcat、strace权限、版本、并发内核驱动失败、系统卡死dmesg、ftrace硬件、中断、内存7.2 我踩过的那些坑坑一Binder 缓冲区溢出。跨进程传大数组没注意 1MB 限制直接崩。后来改成传文件描述符用共享内存。坑二SELinux 权限。HAL 进程访问设备节点被拒logcat 只有一行 avc denied。用audit2allow生成策略但要注意不要过度授权否则过不了安全审查。坑三内核版本不匹配。拿了一个别人编译的驱动加载时报version magic错误。内核模块和内核版本必须严格对应包括编译配置。坑四HAL 接口版本。Framework 请求2.4HAL 只实现了2.3运行时找不到。看manifest.xml和dumpsys的版本信息。坑五system_server 崩溃。加了一个系统服务初始化时抛异常导致整个 system_server 挂掉设备无限重启。加服务一定要做异常保护。7.3 给不同阶段开发者的建议如果你是应用开发者想往系统层走建议从 Binder 和 AMS 入手先理解应用启动流程再逐步深入 WMS、PMS。不要一上来就看内核容易劝退。如果你是嵌入式工程师想理解 Android建议从 HAL 入手因为这是你已有的驱动知识和 Android Framework 的桥梁。理解了 HAL再往上往下都顺。如果你是面试准备重点掌握五层架构的划分、Binder 机制、四大组件的系统服务支撑、HAL 的演进。这几个是高频考点。如果你是系统定制工程师重点掌握 system_server 启动流程、SELinux 策略、HAL 开发、内核驱动调试。这些是日常工作的核心。8. 架构之外一些个人体会做了这么多年 Android 系统我最大的体会是架构知识不是用来背的是用来定位问题的。你不需要记住每个类的每个方法但你需要知道一个问题可能出在哪一层该用什么工具去看。另一个体会是Android 的架构一直在变但核心思想没变。从 Dalvik 到 ART从 HIDL 到 AIDL从 LMK 到 LMKD具体实现换了一茬又一茬但分层解耦、进程隔离、接口标准化这些原则始终如一。抓住这些不变的东西你就能以不变应万变。最后分享一个实用技巧遇到不懂的问题先画调用链。从应用层的 API 开始一层层往下画标出每一层的输入输出和通信方式。画着画着问题往往就自己浮现出来了。这个方法我用了十年屡试不爽。Android 系统架构是个深不见底的话题一篇文章不可能讲完所有细节。但只要你能建立起这个分层框架知道每一层大概在干什么、怎么交互剩下的就是在这个框架里不断填充细节。这个过程很漫长但也很有意思。