Android 的系统功能并非由单一巨型进程提供。system_server承载基于 Java 实现的系统服务(ActivityManagerService、WindowManagerService、PackageManagerService以及数十个其他服务),同时平台大量核心功能运行在由 C++ 编写的独立原生进程中。这些原生服务承担各类工作:屏幕像素合成、触摸事件路由、磁盘 APK 安装等。
本章探究这些原生服务的架构与实现,分析它们如何向servicemanager注册、如何通过 Binder 通信,以及如何与硬件(通过 HAL)和框架其余部分交互。我们将研读真实 AOSP 源码,追踪完整业务链路的数据流,理解各个服务背后的设计决策。
12.1 原生服务架构
12.1.1 什么是原生服务
原生服务是一个 C++ 进程,具备如下特征:
- 作为独立进程启动(由 init 通过
.rc配置文件拉起)。 - 向
servicemanager注册一个或多个 Binder 接口。 - 进入 Binder 线程池或事件循环处理请求。
- 随系统整个生命周期运行;发生崩溃时由 init 重新启动。
Java 系统服务全部运行在system_server的 JVM 内部,与之不同,原生服务运行在各自独立的地址空间。由此带来进程隔离:SurfaceFlinger崩溃不会导致AudioFlinger随之崩溃;同时每个服务仅被授予完成工作所需的最小 Linux 能力集与 SELinux 权限。
12.1.2 servicemanager 注册机制
Android 服务发现机制的核心是servicemanager,它是第一个也是最基础的原生服务。其余所有服务,无论原生还是 Java 实现,都向它注册;所有客户端都通过它查找服务。
该架构保证:
- 注册鉴权:
servicemanager在执行addService()或getService()前校验 SELinux 标签。 - 中心化发现:所有服务都可通过同一个已知 Binder 上下文查找。
- 死亡通知传播:服务死亡时,
servicemanager通知全部已注册回调。
12.1.3 标准服务生命周期
所有原生服务遵循一套通用模式。以 GPU 服务作为极简实例来分析,入口文件:
frameworks/native/services/gpuservice/main_gpuservice.cpp
int main(int /* argc */, char** /* argv */) { signal(SIGPIPE, SIG_IGN); // 发布GpuService sp<GpuService> gpuservice = new GpuService(); sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false); // 将binder线程池最大线程数限制为4 ProcessState::self()->setThreadPoolMaxThreadCount(4); // 启动线程池 sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); IPCThreadState::self()->joinThreadPool(); return 0; }这套模式分为 5 步:
| 步骤 | 代码 | 作用 |
|---|---|---|
| 1 | signal(SIGPIPE, SIG_IGN) | 防止管道断裂引发崩溃 |
| 2 | new GpuService() | 实例化服务对象 |
| 3 | sm->addService(...) | 向 servicemanager 注册服务 |
| 4 | setThreadPoolMaxThreadCount(N) | 配置 Binder 线程池大小 |
| 5 | joinThreadPool() | 主线程阻塞,处理 Binder 调用 |
部分服务使用略有差异的写法。SensorService使用BinderService<T>模板,将第 2‑5 步封装为一次调用:
frameworks/native/services/sensorservice/main_sensorservice.cpp
int main(int /*argc*/, char** /*argv*/) { signal(SIGPIPE, SIG_IGN); SensorService::publishAndJoinThreadPool(); return 0; }模板函数BinderService<T>::publishAndJoinThreadPool()调用T::getServiceName()获取注册名称,实例化服务对象,调用addService(),之后进入线程池。
12.1.4 进程隔离与 init.rc 配置
每一个原生服务都在开机时由 init 解析的.rc文件中定义。典型配置示例:
service surfaceflinger /system/bin/surfaceflinger class core animation user system group graphics drmrpc readproc capabilities SYS_NICE onrestart restart --only-if-running zygote task_profiles HighPerformance关键属性:
class:控制服务在开机流程中何时启动,例如core、main、late_start。user/group:实现进程隔离的 Linux 用户 ID / 用户组 ID。capabilities:受限的 Linux 能力集合。onrestart:服务重启时执行的动作,通常用于级联重启依赖服务。task_profiles:CPU 调度的 cgroup 配置。
12.1.5 三类 servicemanager
Android 实际存在 3 个servicemanager实例:
| 实例 | 二进制程序 | Binder 设备节点 | 用途 |
|---|---|---|---|
| servicemanager | /system/bin/servicemanager | /dev/binder | 框架层服务 |
| vndservicemanager | /vendor/bin/vndservicemanager | /dev/vndbinder | 厂商 HAL 服务 |
| servicemanager(recovery 模式) | 编译时定义__ANDROID_RECOVERY__ | /dev/binder | Recovery 恢复模式 |
厂商服务管理器用于落实 Treble 边界约束:厂商进程不能直接访问框架层服务,框架进程也不能直接访问厂商服务。该隔离由内核层面不同 Binder 设备节点强制实现。
12.1.6 Binder 线程池大小配置
每个原生服务会根据预期并发量精细配置 Binder 线程池大小。该配置十分关键:
- 线程过少:客户端等待线程,延迟升高。
- 线程过多:内存浪费,上下文切换开销增大。
源码中的实际线程池配置:
| 服务 | 最大线程数 | 设计理由 |
|---|---|---|
| servicemanager | 0(基于 Looper) | 单线程,避免死锁 |
| surfaceflinger | 可变(通常 4) | VSYNC 驱动,并发量有限 |
| gpuservice | 4 | 统计与查询,中等并发 |
| media.codec | 64 | 大量并行编解码会话 |
| installd | 默认值(约 15) | 多包并发操作 |
| sensorservice | 默认值(约 15) | 大量传感器并发客户端 |
servicemanager调用setThreadPoolMaxThreadCount(0)值得重点关注。线程池线程数为 0,所有 Binder 处理全部在主线程通过 Looper 完成。这是刻意设计:servicemanager绝对不能同步调用其他服务(会引发死锁),因此所有向外调用均为 one‑way 单向调用,入站调用顺序串行处理。
12.1.7 死亡通知与服务恢复
原生服务崩溃后的恢复流程:
rc 文件中的onrestart指令会触发级联重启。例如SurfaceFlinger崩溃时:
onrestart restart --only-if-running zygote该配置会重启 zygote 进程(连带所有应用进程),因为SurfaceFlinger内部状态无法恢复,所有图层句柄、缓冲区队列全部丢失。
12.1.8 权限与能力
原生服务多层安全防护:
- Linux UID/GID:rc 文件中
user、group指令配置。例如 SurfaceFlinger 以 system 用户运行,附加 graphics、drmrpc、readproc 用户组。 - Linux Capabilities:细粒度权限控制。SurfaceFlinger 拥有
SYS_NICE能力用于实时调度:
capabilities SYS_NICE- SELinux 强制访问控制:每一次 IPC 调用都会校验 SELinux 策略。
service_contexts文件将服务名映射为 SELinux 类型:
SurfaceFlinger u:object_r:surfaceflinger_service:s0 installd u:object_r:installd_service:s0 gpu u:object_r:gpu_service:s0- seccomp‑bpf 沙箱:媒体服务使用,限制系统调用。
SetUpMinijail()函数加载 seccomp 过滤器,限制进程可执行的系统调用,缩小恶意媒体内容的攻击面。
12.1.9 原生服务关系图
Java 侧system_server内部的WindowManagerService、InputManagerService、PackageManagerService通过 Binder 连接各个原生服务。原生服务位于上层 Java 框架与下层 HAL 实现之间,将高层 API 调用转换为硬件操作。
12.2 SurfaceFlinger
SurfaceFlinger 是显示合成服务,可以说是 Android 中最复杂、对性能要求最高的原生服务。它接收来自各个应用与系统 UI 组件的图形缓冲区,将它们合成,在垂直同步信号(VSYNC)的正确时机输出到显示屏。
12.2.1 源码目录结构
SurfaceFlinger 源码位于frameworks/native/services/surfaceflinger/,代码量庞大,约 546 个文件,目录分工如下:
| 目录 | 用途 |
|---|---|
| CompositionEngine/ | 合成流水线抽象层 |
| Display/ | 显示设备管理、显示模式切换 |
| DisplayHardware/ | HWComposer HAL 接口、电源控制 |
| Effects/ | 色彩校正(面向色弱用户的 Daltonizer) |
| FrameTracer/ | 逐帧性能追踪 |
| FrontEnd/ | 图层生命周期、快照构建、事务处理 |
| Jank/ | 卡顿检测与上报 |
| PowerAdvisor/ | 向内核发送 ADPF 电源提示 |
| Scheduler/ | VSYNC 预测、帧调度、刷新率选择 |
| TimeStats/ | 帧时序统计 |
| Tracing/ | Perfetto 集成,图层与事务追踪 |
| Utils/ | 通用工具(栅栏、dump 工具) |
仅SurfaceFlinger.cpp主实现文件就超过 10600 行。头文件SurfaceFlinger.h展示类继承关系:
frameworks/native/services/surfaceflinger/SurfaceFlinger.h
class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, private IBinder::DeathRecipient, private HWC2::ComposerCallback, private ICompositor, private scheduler::ISchedulerCallback, private compositionengine::ICEPowerCallback {继承关系说明:
BnSurfaceComposer:客户端使用的 AIDL 接口ISurfaceComposer的 Binder 服务端实现。PriorityDumper:支持带优先级分段的dumpsys SurfaceFlinger输出。HWC2::ComposerCallback:接收硬件合成器 HAL 回调(热插拔、VSYNC、刷新率变更)。ICompositor:调度器用于触发合成的接口。ISchedulerCallback:接收调度决策(模式切换、帧率更新)。
12.2.2 高层架构
12.2.3 合成周期
SurfaceFlinger 主循环由 Scheduler 驱动。每一次 VSYNC 周期执行如下步骤:
- 提交阶段(commit ())
- 执行待处理事务(图层创建、属性变更、缓冲区更新)。
- 根据前端状态构建图层快照。
- 更新图层树层级。
- 合成阶段(composite ())
- 对每一块显示屏,计算可见图层集合。
- 将图层下发 HWComposer 执行
validateDisplay()。 - HWC 决定哪些图层走硬件 Overlay 合成,哪些需要回退到 GPU 客户端合成。
- 如果需要客户端合成,调用 RenderEngine(Skia/OpenGL)将对应图层渲染至帧缓冲区。
- 调用
presentDisplay()将最终帧提交给显示屏。 - 合成后处理
- 向应用发送释放栅栏信号,应用可以复用缓冲区。
- 更新帧时序统计数据。
- 如果发生丢帧,上报卡顿指标。
关键性能要点:HWC Overlay 硬件合成几乎零开销,显示屏硬件完成图层混合,不消耗 GPU 资源。GPU 合成作为兜底方案,用于 HWC 无法处理的图层,例如复杂混合模式、图层数量超限、色彩空间转换。
12.2.4 图层管理
一个Layer代表一块矩形图形内容。每个图层拥有:
BufferQueue:接收生产者送来的图形缓冲区。- 绘制状态与当前状态(双缓冲,支持并发更新)。
- 几何属性:位置、尺寸、裁剪、变换、Z 轴层级。
- 视觉属性:透明度、颜色、混合模式、色彩空间。
摘自frameworks/native/services/surfaceflinger/Layer.cpp
Layer::Layer(const surfaceflinger::LayerCreationArgs& args) : sequence(args.sequence), mFlinger(sp<SurfaceFlinger>::fromExisting(args.flinger)), mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)), mWindowType(static_cast<WindowInfo::Type>( args.metadata.getInt32(gui::METADATA_WINDOW_TYPE, 0))) { ALOGV("Creating Layer %s", getDebugName()); mDrawingState.crop = {0, 0, -1, -1}; mDrawingState.sequence = 0; mDrawingState.transform.set(0, 0); mDrawingState.frameNumber = 0; // ... }FrontEnd/子系统通过如下组件管理图层生命周期:
LayerLifecycleManager:跟踪图层创建与销毁。LayerSnapshotBuilder:生成不可变图层快照提供给合成引擎,避免事务线程与合成线程锁竞争。TransactionHandler:队列化并原子执行事务。
SurfaceFlinger 设置图层上限 4096(MAX_LAYERS = 4096),防止资源耗尽。
12.2.5 调度器与 VSYNC
frameworks/native/services/surfaceflinger/Scheduler/下的调度子系统职责:
- VSYNC 预测:
VSyncPredictor基于历史时间戳预估未来 VSYNC 时刻。 - 刷新率选择:根据活跃图层帧率,选择最优显示屏刷新率(60Hz、90Hz、120Hz 等)。
- 帧调度:在 VSYNC 到来前合适时刻唤醒 SurfaceFlinger 执行合成。
核心类:
Scheduler(Scheduler.h):总控时序,继承IEventThreadCallback与MessageQueue。VSyncPredictor(VSyncPredictor.cpp):对硬件 VSYNC 时间戳做线性拟合,预测未来事件。VSyncDispatchTimerQueue(VSyncDispatchTimerQueue.cpp):管理不同 VSYNC 客户端的定时器唤醒。RefreshRateSelector(RefreshRateSelector.cpp):选择最适配所有活跃图层的显示模式(刷新率 + 分辨率)。EventThread(EventThread.cpp):通过DisplayEventConnection向应用分发 VSYNC 事件。
12.2.6 HWComposer HAL 交互
SurfaceFlinger 通过 HWComposer(硬件合成器)HAL 与显示硬件通信。HAL AIDL 接口定义路径:
hardware/interfaces/graphics/composer/aidl/DisplayHardware/HWComposer.h封装层将 SurfaceFlinger 内部数据结构转换为 HAL 调用:SurfaceFlinger→ HWComposer 封装层 →IComposerHAL → DRM/KMS 驱动 → 显示面板
关键 HAL 接口方法:
| HAL 方法 | 用途 |
|---|---|
createLayer() | 分配硬件 Overlay 平面 |
setLayerBuffer() | 为图层绑定图形缓冲区 |
setLayerCompositionType() | 标记为 DEVICE 硬件合成或 CLIENT GPU 合成 |
validateDisplay() | 让 HWC 评估图层栈 |
acceptDisplayChanges() | 接受 HWC 的合成类型决策 |
presentDisplay() | 提交帧到显示屏 |
getReleaseFences() | 获取缓冲区回收栅栏 |
12.2.7 CompositionEngine 合成引擎
CompositionEngine/目录下的合成引擎,将合成算法与 SurfaceFlinger 策略逻辑解耦。它接收一组CompositionRefreshArgs,为每一块显示屏输出合成完成的帧。
引擎内部合成流程:
引擎中每一个Output对象代表一块物理显示屏或者虚拟显示屏。OutputLayer对象封装图层快照,附带该显示屏对应的合成状态,例如 HWC 为此图层分配的合成类型。
预测式合成策略现代优化手段预测式合成,由下面的标志控制:
// 如果开启,合成引擎尝试基于上一帧HWC输出预测合成策略。 // 如果预测成功,GPU合成将与hwc validateDisplay并行执行;预测失败则重新执行。 bool mPredictCompositionStrategy = false;开启后,合成引擎基于上一帧 HWC 决策预判哪些图层需要 GPU 回退。GPU 合成与validateDisplay()并行执行。预测正确时,validateDisplay()返回时 GPU 工作已经完成,GPU 合成路径节省一帧延迟。
12.2.8 RenderEngine:GPU 合成
当 HWC 无法完成全部图层合成(图层过多、不支持的混合模式、需要色彩空间转换),SurfaceFlinger 使用 RenderEngine 完成 GPU 合成。RenderEngine 实现后端:
- Skia:主力渲染后端,支持 Vulkan 或 GLES。
- 线程渲染:RenderEngine 可运行在独立线程,避免阻塞主合成线程。
核心接口drawLayers()接收图层配置(源缓冲区、几何、混合模式、颜色矩阵),将多个图层合成为单一输出缓冲区,再作为 “客户端目标图层” 交给 HWC。
12.2.9 事务模型
应用通过事务修改图层属性。事务是一组原子变更,会一次性全部生效。
TransactionHandler维护待处理事务队列。事务分为:
- 立即事务:下一次 VSYNC 生效。
- 延迟事务:在指定帧号或者栅栏信号到来后生效。
- 同步事务:跨多个 surface,多组变更原子同时生效。
重点类LayerLifecycleManager:
frameworks/native/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
// 管理一组RequestedLayerStates,处理它们的生命周期与状态变更 // // RequestedLayerStates会被跟踪;若无父节点、无存活句柄,则被销毁。 class LayerLifecycleManager { public: void addLayers(std::vector<std::unique_ptr<RequestedLayerState>>); void applyTransactions(const std::vector<QueuedTransactionState>&, bool ignoreUnknownLayers = false); void onHandlesDestroyed(const std::vector<std::pair<uint32_t, std::string>>&, bool ignoreUnknownHandles = false); void fixRelativeZLoop(uint32_t relativeRootId); void commitChanges(); // ... };12.2.10 HWComposer 回调
SurfaceFlinger 接收来自 HWComposer HAL 的多个回调:
// HWC2::ComposerCallback重写接口 void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp, std::optional<hal::VsyncPeriodNanos>) override; void onComposerHalHotplugEvent(hal::HWDisplayId, DisplayHotplugEvent) override; void onComposerHalRefresh(hal::HWDisplayId) override; void onComposerHalVsyncPeriodTimingChanged(hal::HWDisplayId, const hal::VsyncPeriodChangeTimeline&) override; void onComposerHalSeamlessPossible(hal::HWDisplayId) override; void onComposerHalVsyncIdle(hal::HWDisplayId) override; void onRefreshRateChangedDebug( const RefreshRateChangedDebugData&) override; void onComposerHalHdcpLevelsChanged(hal::HWDisplayId, const HdcpLevels& levels) override;| 回调函数 | 触发时机 | SurfaceFlinger 处理逻辑 |
|---|---|---|
onVsync | 硬件 VSYNC 脉冲 | 更新 VSyncPredictor 模型 |
onHotplugEvent | 显示屏插拔 | 创建 / 销毁 DisplayDevice |
onRefresh | HWC 请求刷新 | 调度一次立即合成 |
onVsyncPeriodTimingChanged | 刷新率变更过程中 | 更新时序参数 |
onVsyncIdle | 显示屏进入空闲(VRR 可变刷新率) | 调整空闲调度逻辑 |
onHdcpLevelsChanged | HDCP 保护等级变更 | 更新内容保护状态 |
12.2.11 ISurfaceComposer API
SurfaceFlinger 通过 AIDL 接口ISurfaceComposer对外暴露丰富 API。主要方法分类:
显示管理
createVirtualDisplay()/destroyVirtualDisplay()getPhysicalDisplayIds()/getPhysicalDisplayToken()setDesiredDisplayModeSpecs()(刷新率策略)setPowerMode()(ON、OFF、DOZE、DOZE_SUSPEND)setDisplayBrightness()
图层操作
setTransactionState()(所有图层变更的主入口)setFrameRate()(每个 surface 期望帧率)setGameModeFrameRateOverride()(游戏专用帧率覆盖)
屏幕捕获
captureDisplay()(截取整个显示屏截图)captureLayers()(截取指定图层)
监控监听
addFpsListener()/addHdrLayerInfoListener()addRegionSamplingListener()(自动亮度的亮度采样)addWindowInfosListener()(给 InputFlinger 的窗口信息更新)
12.2.12 可变刷新率(VRR)支持
现代显示屏支持可变刷新率 VRR,刷新周期可以动态变化。SurfaceFlinger 处理逻辑:
VsyncSchedule负责 VRR 感知调度:
- 内容活跃更新时,VSYNC 跟随内容帧率。
- 无新内容到达,显示屏进入空闲,触发
onComposerHalVsyncIdle()。 vrrDisplayIdle()回调通知调度器停止不必要唤醒。KernelIdleTimerController管理内核侧显示空闲定时器,可将面板切到低功耗自刷新模式。
VsyncModulator根据负载调整 VSYNC 偏移量:
class VsyncModulator { // Early偏移:SurfaceFlinger需要提前唤醒,例如触摸事件到来预期新帧 VsyncConfig mEarlyConfig; // Late偏移:负载可预测的常规运行模式 VsyncConfig mLateConfig; // EarlyGpu偏移:预期会发生GPU回退合成时使用 VsyncConfig mEarlyGpuConfig; };12.2.13 LatchUnsignaled
LatchUnsignaledConfig控制 SurfaceFlinger 是否可以在 acquire 栅栏未信号化时直接使用缓冲区:
enum class LatchUnsignaledConfig { Disabled, // 绝不使用未信号的缓冲区 AutoSingleLayer, // 仅单图层纯缓冲区更新场景允许 Always, // 总是允许,存在风险 };生产环境默认使用AutoSingleLayer。当只有单个图层提交缓冲区更新,没有其他待处理事务,SurfaceFlinger 直接把缓冲区 acquire 栅栏交给 HWC。栅栏在显示屏截止时间前就绪就正常显示本帧;否则显示屏继续显示上一帧。该机制为简单缓冲区更新减少一帧延迟。
12.2.14 电源管理
SurfaceFlinger 与 Android 电源管理集成点:
- PowerAdvisor:与 PowerHAL 通信,发送 ADPF(Android 动态性能框架)提示。合成前上报预期工作负载时长;合成完成上报实际耗时。PowerHAL 据此调整 CPU/GPU 频率。
- 显示电源模式
OFF:显示屏关闭,SurfaceFlinger 停止合成。ON:正常工作。DOZE:息屏显示,低功耗低亮度。DOZE_SUSPEND:类似 DOZE,但 SurfaceFlinger 停止合成,显示控制器输出静态图像。
- CPU 负载通知:
ICEPowerCallback::notifyCpuLoadUp(),当 CPU 负载即将升高(例如大量事务涌入)向电源系统告警。
12.2.15 显示亮度与色彩管理
SurfaceFlinger 管理整条显示色彩流水线:
- 广色域:支持 Display‑P3、BT.2020 色彩空间。
defaultCompositionDataspace、wideColorGamutCompositionDataspace控制渲染色彩空间。 - HDR:处理 HDR 内容合成,包含 SDR 转 HDR、HDR 转 SDR 色调映射。
HdrLayerInfoReporter向监听方上报屏幕上出现 HDR 内容。 - 颜色矩阵:4×4 颜色变换矩阵作用于整个显示输出,用于无障碍功能:颜色反转、色弱校正 Daltonizer。
- 区域采样:
RegionSamplingThread采样屏幕指定区域像素值,状态栏用它调整文字颜色,保证在背景上可读。
12.2.16 开机阶段
SurfaceFlinger 跟踪 3 个开机状态:
enum class BootStage { BOOTLOADER, // 显示bootloader开机动画 BOOTANIMATION, // 播放开机动画 FINISHED, // 系统完全开机 };BOOTLOADER阶段 SurfaceFlinger 完成初始化,但尚未驱动显示屏。进入BOOTANIMATION后开始合成开机动画帧。system_server调用bootFinished()切换至FINISHED,进入正常业务流程。
12.2.17 交叉引用
SurfaceFlinger 与其他章节图形流水线深度关联:
- 第 13 章(图形渲染流水线):向 SurfaceFlinger 输送缓冲区的 BufferQueue 生产者消费者模型;详细讲解 CompositionEngine、RenderEngine (Skia)、逐帧合成算法。
- 第 10 章(HAL):HWComposer HAL 接口与 AIDL 定义。
12.3 InputFlinger
InputFlinger 处理全部用户输入:触摸、按键、手写笔、鼠标移动、游戏手柄按键,将事件分发到正确的应用窗口。它是 Android 中对延迟最敏感的服务之一,几毫秒额外延迟就可以被用户感知。
12.3.1 源码目录结构
InputFlinger 源码路径frameworks/native/services/inputflinger/
| 目录 | 用途 |
|---|---|
| reader/ | EventHub+InputReader:读取内核原始事件 |
| dispatcher/ | InputDispatcher:将事件路由到窗口 |
| reporter/ | InputReporter:上报未处理 / 丢弃按键(InteractionReporter 在 inputflinger 根目录,不在此处) |
| trace/ | Perfetto 追踪集 |