1. Android系统概述:从零到一,理解这个庞大的生态
大家好,我是你们的老朋友。今天咱们正式开篇,聊聊Android系统到底是个什么东西。
说实话,我刚开始接触Android时,也觉得它就是个手机操作系统。但干得越久,越发现它其实是一个庞大的、分层清晰的软件栈。你想想看,从你手指触摸屏幕,到App做出响应,中间经历了多少层?每一层都在干什么?
嗯,这节课我们就来拆解它。
1.1 Android发展史:一个开源项目的逆袭
先简单回顾一下历史。Android最初不是Google做的,而是Andy Rubin创办的Android公司。2005年被Google收购,2007年正式对外发布。
我记得当时市面上还是塞班和Windows Mobile的天下。Android 1.0发布时,说实话,功能很简陋。但它的杀手锏是什么?开源。任何厂商都可以免费使用、修改。
这直接导致了后来三星、HTC、华为等厂商的疯狂涌入。我经历过Android 2.3(Gingerbread)到4.0(Ice Cream Sandwich)的过渡期,那会儿碎片化问题特别严重。但Google后来通过CTS(兼容性测试套件)和GMS(Google移动服务)逐渐规范了生态。
到了Android 5.0(Lollipop),ART运行时替换了Dalvik,性能有了质的飞跃。再往后,Android 10开始引入Project Treble,把系统框架和厂商驱动解耦,升级难的问题才真正得到缓解。
我个人习惯把Android发展史分为三个阶段:
- 野蛮生长期(1.0-4.4):功能快速迭代,但碎片化严重
- 成熟稳定期(5.0-9.0):ART、Material Design、权限管理逐步完善
- 现代架构期(10.0-至今):Treble、动态分区、隐私保护成为核心
小提示:如果你在调试老设备,比如Android 4.4以下的系统,很多现代调试工具(如adb shell dumpsys)可能不支持。我建议你至少准备一台Android 10以上的设备做主力调试机。
1.2 Android系统架构分层:五层结构,各司其职
Android架构从上到下分为五层。我画个简图帮你理解:
+-----------------------------+
| 应用层 (App) | ← 你写的APK
+-----------------------------+
| 应用框架层 (Framework) | ← ActivityManager, WindowManager等
+-----------------------------+
| 系统服务层 (Services) | ← SurfaceFlinger, AudioFlinger等
+-----------------------------+
| 硬件抽象层 (HAL) | ← Camera HAL, Audio HAL等
+-----------------------------+
| Linux内核层 (Kernel) | ← 驱动、内存管理、进程调度
+-----------------------------+
每一层都只依赖下一层,不跨层调用。这样做的好处是:解耦。你换一个厂商的硬件,只要HAL层实现对了,上面的Framework和App完全不用改。
我曾经在一个项目中遇到过:某厂商换了摄像头传感器,结果上层拍照App直接闪退。查了半天,发现是HAL层返回的数据格式和Framework预期的不一致。这就是分层没做好的典型问题。
1.2.1 Linux内核层(Kernel)
这是Android的根基。说白了,Android就是跑在Linux内核上的。内核负责什么?
- 进程调度:决定哪个App先跑
- 内存管理:分配和回收内存
- 驱动:屏幕、触摸、Wi-Fi、蓝牙等硬件驱动
- 安全:基于Linux的权限模型
但Android对Linux内核做了不少改动。比如添加了Binder驱动,这是Android进程间通信(IPC)的核心。还有ashmem(匿名共享内存)、wakelock(唤醒锁)等。
重点:Binder是Android的灵魂。所有跨进程通信,比如App调用系统服务,底层都是通过Binder完成的。调试时,你可以用 adb shell lsof | grep binder 查看哪些进程在使用Binder。
1.2.2 硬件抽象层(HAL)
HAL层是连接内核和Framework的桥梁。为什么需要它?
你想想看,不同厂商的摄像头驱动接口可能完全不同。如果Framework直接调用内核驱动,那每换一个厂商,Google就得改一次Framework代码。这显然不现实。
所以HAL层定义了一套标准接口。厂商只需要实现这些接口,Framework就可以统一调用。比如Camera HAL,定义了 open()、startPreview()、takePicture() 等函数。
我记得在Android 8.0之前,HAL是以共享库(.so)的形式直接加载到系统服务进程中的。这导致一个问题:如果HAL崩溃,整个系统服务也跟着挂。后来Treble项目把它改成了HAL Server,独立进程运行,互不影响。
避坑指南:调试HAL层时,千万不要直接修改内核驱动来验证问题。我曾经这么干过,结果把设备搞成砖了。正确的做法是:先确认HAL接口是否被正确调用,用 adb shell lshal 查看当前设备支持的HAL服务。
1.2.3 系统服务层(System Services)
这一层是Android的核心大脑。它运行在System Server进程中,里面包含了上百个服务。
常见的系统服务有:
| 服务名称 | 职责 |
|---|---|
| ActivityManagerService (AMS) | 管理Activity生命周期、进程调度 |
| WindowManagerService (WMS) | 管理窗口、触摸事件分发 |
| PackageManagerService (PMS) | 管理App安装、卸载、权限 |
| SurfaceFlinger | 合成所有应用的UI图层,输出到屏幕 |
| AudioFlinger | 音频混音和输出 |
这些服务之间通过Binder通信。比如你打开一个App,AMS会通知WMS创建窗口,WMS再通知SurfaceFlinger开始渲染。
调试时,我经常用 adb shell dumpsys 来查看各个服务的状态。比如 dumpsys activity 可以看当前运行的Activity栈,dumpsys window 可以看窗口层级。
1.2.4 应用框架层(Application Framework)
这一层是给App开发者用的。它封装了系统服务的调用,提供了一套Java API。
比如你想在屏幕上显示一个按钮,你只需要写 new Button(context),Framework会帮你调用WMS去创建窗口、调用SurfaceFlinger去渲染。
常见的框架组件:
- Activity:用户界面的基本单元
- Service:后台任务
- ContentProvider:数据共享
- BroadcastReceiver:广播接收
- View系统:UI绘制和事件处理
我个人觉得,Framework层是Android最复杂的一层。因为它既要向上提供简洁的API,又要向下管理复杂的系统服务。很多性能问题,比如界面卡顿,根源都在这一层。
1.2.5 应用层(Application Layer)
这就是你写的App了。它运行在应用进程中,每个App默认有一个独立的进程和用户ID(UID)。
应用层通过Framework API与系统交互。比如:
// 启动一个Activity
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
// 底层发生了什么?
// 1. 当前App通过Binder调用AMS
// 2. AMS检查Intent和权限
// 3. AMS通知WMS创建窗口
// 4. AMS启动SecondActivity的进程(如果未启动)
// 5. SecondActivity执行onCreate()
你看,一个简单的 startActivity(),背后经历了这么多层。这就是分层架构的魅力:每一层只关心自己的事,通过标准接口协作。
1.3 各层核心职责与交互:一张图看懂
为了让你更直观地理解,我画了一个交互流程图:
用户触摸屏幕
↓
应用层 (App) 捕获触摸事件
↓ 通过Binder
应用框架层 (Framework) 解析事件,调用WMS
↓ 通过Binder
系统服务层 (WMS) 处理窗口焦点,通知SurfaceFlinger
↓ 通过HAL接口
硬件抽象层 (HAL) 调用GPU驱动
↓ 通过内核驱动
Linux内核层 驱动GPU渲染,输出到屏幕
这个过程中,每一层都可能成为性能瓶颈。比如:
- 如果App层主线程做了耗时操作,触摸事件会延迟处理
- 如果Framework层Binder通信阻塞,窗口无法及时更新
- 如果HAL层驱动有bug,渲染会卡顿或花屏
调试技巧:遇到卡顿问题时,我习惯先用 adb shell dumpsys gfxinfo 查看App的帧率,再用 adb shell dumpsys SurfaceFlinger 看合成耗时,最后用 adb shell dumpsys meminfo 看内存情况。逐层排查,定位问题。
1.4 总结:为什么你要理解架构分层?
说白了,搞懂Android架构分层,不是为了考试,而是为了快速定位问题。
你想想看,一个App崩溃了,原因可能出在哪一层?
- 如果是NullPointerException,大概率是App层代码问题
- 如果是TransactionTooLargeException,可能是Binder通信数据量过大
- 如果是SurfaceFlinger hang住,可能是HAL层驱动死锁
没有分层思维,你就像无头苍蝇一样乱撞。有了分层思维,你就能快速缩小排查范围。
嗯,这节课就到这里。下一节我们深入Linux内核层,聊聊Binder驱动的实现细节。到时候我会分享一个我当年调试Binder死锁的案例,保证让你印象深刻。
记住:架构是地图,调试是导航。没有地图,导航就是瞎转悠。