前言
作为一个 Android 应用开发者,是否想过当你按下 Android 电源键打开设备,从硬件到软件会发生什么?是否会有以下疑问:
- 当设备开机动画出现时,屏幕后面到底发生了什么?
- 手机或者汽车等设备究竟如何加载、引导并启动 Android 操作系统?
接下来的文章将会通过图文结合的方式来探索 Android 操作系统的启动流程。
Android 启动流程
每次 Android 设备开机时都会经过一次完整的启动流程。
大致可分为 6 大步骤:
- Boot ROM 代码执行
- Bootloader 程序执行
- Linux 内核启动
- Init 进程启动
- Zygote 进程 和 Dalvik VM 虚拟机启动
- System Servers 和 Service Manager 启动
Boot ROM 代码执行
Android 设备上电之后,首先会从 SoC 上 Boot ROM 的启动引导代码开始执行。在此阶段会发生以下两件事:
- 初始化设备硬件并尝试扫描和检测引导介质。这块代码是固写在 Boot ROM 中无法改变的,类似于计算机启动过程中的 BIOS 功能。
- 将初始的引导程序 Bootloader 复制到内部 RAM。
Bootloader 程序执行
Bootloader 是在 Android 系统启动前运行的一个微型程序,但它并不属于 Android 操作系统。OEM 通常会在该程序中设置锁定和限制。
Bootloader 程序存在于台式计算机、笔记本电脑和移动设备中,并且它们的功能相似。在 Android 设备上,引导加载程序分为两个阶段:
- Initial Program Load (IPL)
- Second Program Load (SPL)
Initial Program Load (IPL)
IPL 负责检测能够进行 SPL 的外部 RAM。一旦检测到有外部 RAM 可用,SPL 就会被复制到该 RAM 中执行。
Second Program Load (SPL)
SPL 负责加载主 Android 操作系统并提供对其他启动模式的访问,例如fastboot
和recovery
。SPL 还会初始化多个硬件组件,例如显示器、键盘、文件系统、虚拟内存、控制台和其他功能。此后,SPL 会尝试查找 Linux 内核。内核会在启动介质中被找到的,然后将其复制到 RAM。此后,SPL 会将执行转移到内核。
Linux 内核
Android 内核的启动方式与 Linux 内核类似。当内核启动时,它首先会进行一系列系统设置:缓存、受保护的内存、调度和加载驱动程序。当内核完成系统设置后,接下来就会在系统文件中查找init
。
然而, Android 内核与 Linux 内核也有一些区别。以下是 Android 内核中新增定制的部分:
- Binder: Android 特有的进程间通信机制和远程方法调用系统。
- ASHMEM: Android 共享内存,类似于 POSIX SHM,但具有不同的行为并具有更简单的基于文件的 API。
- PMEM: 进程内存分配器,用于管理用户空间和内核驱动程序之间共享的大型(1-16+ MB)物理连续内存区域。
- Logger: 内核对 logcat 命令的支持。
- Paranoid Networking: 根据呼叫进程组限制对某些网络功能的访问。
- Wake locks: 应用程序在手机空闲时保持 CPU/屏幕/其他设备处于唤醒状态以执行特定后台任务的方法。通常用于电源管理文件。
- OOM Handling: 内存管理模块,用以检查系统是否有足够的内存可用于执行任务,验证系统何时内存不足,并终止进程以释放内存。
- Alarm Manager: 允许用户空间在想要唤醒时与内核进行通信。
- Timed output / Timed GPIO: GPIO 是一种允许程序从用户空间访问和操作 GPIO 寄存器的机制。
- RAM Console: RAM 中在启动时保留的区域。该区域是拥有持久属性,用于在内核重新启动或崩溃时存储最后的内核日志消息。此处存储的日志对于内核调试非常有用,可以在崩溃或意外重启之前立即深入了解内核进程。在
/proc/last_kmsg
中查看。 - USB Gadget Driver for ADB
- yaffs2 flash filesystem
- 等…
Init Process
Init
是 Android 系统的第一个进程,又称为根进程,是所有其他进程的爷爷(Init 启动了 Zygote,Zygote fork 出其他进程)。Init 进程主要有两个职责。
- 挂载目录,如
/sys
,/dev
或/proc
- 解析运行
init.rc
脚本
init
进程在:/system/core/init
init.rc
文件在:/system/core/rootdir/
Android 对于init.rc
文件的解释和执行有一套特定规则,会在后续文章中详细介绍。
启动流程到了这个阶段,终于可以在设备屏幕上看到 Android Logo 了。
Zygote 和 Dalvik
在 Java 中,会为每一个应用程序在内存中分配出单独的虚拟机实例。而 Android 的 Dalvik(虚拟机)有所不同,因为它需要尽可能快。这就带来了一个问题。
如果有多个应用程序启动了多个 Dalvik 实例,导致可用内存耗尽,会发生什么?
Android 通过一个名为 Zygote 的系统解决了这个问题。
Zygote 是设备启动后 init 进程最先创建的进程之一。Zygote 支持跨 Dalvik VM 共享代码,从而实现更低的内存占用和最短的启动时间。它是一个虚拟机进程,在系统启动时启动,并尝试创建多个实例来支持每个 Android 进程。Zygote 会预加载并初始化核心库类。
Zygote 加载过程
-
Load
ZygoteInitclass
:加载 ZygoteInit 类。源码:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
-
registerZygoteSocket()
:为 zygote 注册一个服务器套接字,供其他客户端建立跨进程连接。 -
preloadClasses()
:这是一个简单的文本文件,其中包含需要预加载的类列表。文件位置:
/frameworks/base
-
preloadResources()
资源文件,包括 android.R 文件的所有内容都将使用此方法加载:
启动流程到了这个阶段,设备屏幕将会显示启动动画。
System service
Zygote 进程会先 fork 出 SystemServer 进程,然后 SystemServer 进程负责将所有 Android 核心服务启动起来。
startBootstrapServices()
服务名 | 功能简介 |
---|---|
Installer | 创建具有合适权限的关键目录,如/data/user |
ActivityManagerService | 简称AMS,管理着Android四大组建的生命周期,同时也管理着各个应用程序进程 |
PowerManagerService | 电源管理服务 |
LightsService | 管理设备各种led灯和显示背光等 |
DisplayManagerService | 管理设备显示的生命周期,会根据当前连接的物理显示设备控制其逻辑显示,当状态变化时,会向系统和应用程序发送通知 |
PackageManagerService | 简称PMS,用于APK的权限验证、安装、删除等操作 |
UserManagerService | 主要功能是创建和删除用户,以及查询用户信息 |
startCoreServices()
服务名 | 功能简介 |
---|---|
BatteryService | 对设备电池状态进行监控的服务,当电池,充电状态,温度等信息发生变化时,会以广播的形式通知其他相关的进程和服务。 |
UsageStatsService | 收集用户对每一个APP的使用频率、使用时常等信息; |
WebViewUpdateService | 用于WebView的更新 |
startOtherService()
服务名 | 功能简介 |
---|---|
CameraService | 管理设备相机功能 |
VibratorService | 管理设备震动功能 |
ConsumerIrService | 远程控制服务,如红外遥控 |
AlarmManagerService | Android定时服务,提供闹铃和定时器等功能 |
InputManagerService | 事件传递分发服务 |
WindowManagerService | 对系统中的所有窗口进行管理窗口的管理服务 |
VrManagerService | VR相关功能服务 |
BluetoothService | 蓝牙服务 |
InputMethodManagerService | 输入法服务 |
AccessibilityManagerService | 辅助管理程序截获所有的用户输入,并根据这些输入给用户一些额外的反馈,起到辅助的效果,View的点击、焦点等事件分发管理服。 |
MountService | 用于媒体/ usb通知 / 外接设备的插入拔出等事件的监听 |
UiModeManagerService | 管理设备UI模式,汽车模式、电视模式、手表模式、黑夜模式等 |
LockSettingsService | 管理用户的锁屏功能,锁屏密码等 |
PersistentDataBlockService | 管理数据块的服务?之后有空详细看下 |
DeviceIdleController | 设备idle(空闲状态)的控制,例如低功耗模式就基于这个服务 |
DevicePolicyManagerService | 提供一些系统级别的设置及属性 |
StatusBarManagerService | 系统状态栏服务 |
ClipboardService | 剪贴板服务 |
NetworkManagementService | 网络管理服务,提供对物理网络接口的管理服务。Android 系统网络连接和管理服务由四个系统服务ConnectivityService、NetworkPolicyManagerService、NetworkManagementService、NetworkStatsService共同配合完成网络连接和管理功能。 |
TextServicesManagerService | 文本服务,例如文本拼写检查服务 |
NetworkScoreService | 网络状态分服务?待理解 |
NetworkStatsService | 网络传输数据统计服务 |
NetworkPolicyManagerService | 网络策略管理服务 |
WifiP2pService | Wifi Direct服务 |
WifiService | Wifi服务 |
WifiScanningService | Wifi扫描服务 |
RttService | wifi RTT服务(Wi-Fi Round-Trip-Time),让应用可以利用室内定位功能 |
EthernetService | 以太网服务 |
ConnectivityService | 网络连接状态服务 |
NsdService | 网络服务搜索 |
UpdateLockService | 锁屏更新服务 |
RecoverySystemService | recovery系统模式,在一些情况下可能会使用此服务重启系统 |
NotificationManagerService | 通知服务 |
DeviceStorageMonitorService | 设备存储器监听服务 |
LocationManagerService | 位置服务,用于GPS、定位等。 |
CountryDetectorService | 国家检测服务,类ComprehensiveCountryDetector.java,检测顺序:移动网络、位置、sim卡的国家、手机的位置 |
SearchManagerService | 全局搜索服务 |
DropBoxManagerService | 用于系统运行日志和错误日志的存储管理服务 |
WallpaperManagerService | 壁纸管理服务 |
AudioService | AudioFlinger的上层管理封装,主要是音量、音效、声道及铃声等的管理。 |
DockObserver | 看网上的解释,如果系统有个座子,当手机装上或拔出这个座子的话,可以靠该服务进行管理 |
UsbService | usb设备服务,管理所有USB设备相关的状态,包括host(UsbHostManager)和device(UsbDeviceManager)模式 |
SerialService | 串口服务 |
HardwarePropertiesManagerService | 提供访问设备硬件状态的机制:CPU,GPU和电池温度,每个内核的CPU使用率,风扇速度等 |
TwilightService | 指出用户当前所在位置是否为晚上,被UiModeManager等用来调整夜间模式。 |
NightDisplayService | 设备夜晚显示模式服务 |
JobSchedulerService | 这个没太明白是干啥用的 |
SoundTriggerService | 语音识别架构? |
BackupManagerService | 备份服务 |
AppWidgetService | widge管理服务,Widget安装,删除,更新等等 |
VoiceInteractionManagerService | 手势启动服务 |
SensorNotificationService | 传感器通知服务 |
ContextHubSystemService | 主要是为了启动ContextHubService |
DiskStatsService | 磁盘统计服务,使用adb shell dumpsys diskstats时会被调用 |
SamplingProfilerService | 用于耗时统计等 |
NetworkTimeUpdateService | 监视网络时间,当网络时间变化时更新本地时间 |
CommonTimeManagementService | 管理本地常见的时间服务的配置,在网络配置变化时重新配置本地服务 |
EmergencyAffordanceService | 紧急呼叫服务 |
DreamManagerService | 管理屏保 |
AssetAtlasService | 负责将预加载的bitmap组装成纹理贴图,生成的纹理贴图可以被用来跨进程使用,以减少内存。 |
GraphicsStatsService | 用来汇总屏幕卡顿数据的,通过adb shell dumpsys graphicsstats调用查看汇总结果 |
PrintManagerService | 打印服务 |
RestrictionsManagerService | 限制管理服务 |
MediaSessionService | 多媒体会话服务 |
HdmiControlService | hdmi控制服务 |
TvInputManagerService | 电视输入服务 |
MediaResourceMonitorService | 媒体资源监控服务 |
TrustManagerService | 信任管理器服务 |
FingerprintService | 指纹服务 |
BackgroundDexOptService | dex后台优化服务,在PackManager中有调用 |
LauncherAppsService | Launcher应用相关的服务 |
ShortcutService | 快捷方式服务 |
MediaProjectionManagerService | 媒体投影服务,可用于录屏或者屏幕投射 |
WearBluetoothServicea | 穿戴设备蓝牙服务 |
WearWifiMediatorService | 穿戴设备Wi-Fi中介服务 |
WearCellularMediatorService | 穿戴设备蜂窝网络服务 |
WearTimeService | 穿戴设备时间服务 |
MmsServiceBroker | 彩信服务 |
RetailDemoModeService |
注:这些 Android 服务并没有各自运行在独立的进程中,它们由 SystemServer 以线程的方式创建,所以都运行在同一个进程中,即 SystemServer 进程,并由它管理。
至此系统启动流程已完结。
此时系统将发送一个名为ACTION_BOOT_COMPLETED
的广播,通知所有相关进程 boot process 已完成。
设备会显示 Home 主屏幕并准备好与用户交互。