第 12 章:原生服务

📅 2026/8/12 17:14:21
第 12 章:原生服务
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.cppint main(int /* argc */, char** /* argv */) { signal(SIGPIPE, SIG_IGN); // 发布GpuService spGpuService gpuservice = new GpuService(); spIServiceManager sm(defaultServiceManager()); sm-addService(String16(GpuService::SERVICE_NAME), gpuservice, false); // 将binder线程池最大线程数限制为4 ProcessState::self()-setThreadPoolMaxThreadCount(4); // 启动线程池 spProcessState ps(ProcessState::self()); ps-startThreadPool(); ps-giveThreadPoolName(); IPCThreadState::self()-joinThreadPool(); return 0; }这套模式分为 5 步:步骤代码作用1signal(SIGPIPE, SIG_IGN)防止管道断裂引发崩溃2new GpuService()实例化服务对象3sm-addService(...)向 servicemanager 注册服务4setThreadPoolMaxThreadCount(N)配置 Binder 线程池大小5joinThreadPool()主线程阻塞,处理 Binder 调用部分服务使用略有差异的写法。SensorService使用BinderServiceT模板,将第 2‑5 步封装为一次调用:frameworks/native/services/sensorservice/main_sensorservice.cppint main(int /*argc*/, char** /*argv*/) { signal(SIGPIPE, SIG_IGN); SensorService::publishAndJoinThreadPool(); return 0; }模板函数BinderServiceT::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 三类 servicemanagerAndroid 实际存在 3 个servicemanager实例:实例二进制程序Binder 设备节点用途servicemanager/system/bin/servicemanager/dev/binder框架层服务vndservicemanager/vendor/bin/vndservicemanager/dev/vndbinder厂商 HAL 服务servicemanager(recovery 模式)编译时定义__ANDROID_RECOVERY__/dev/binderRecovery 恢复模式厂商服务管理器用于落实 Treble 边界约束:厂商进程不能直接访问框架层服务,框架进程也不能直接访问厂商服务。该隔离由内核层面不同 Binder 设备节点强制实现。12.1.6 Binder 线程池大小配置每个原生服务会根据预期并发量精细配置 Binder 线程池大小。该配置十分关键:线程过少:客户端等待线程,延迟升高。线程过多:内存浪费,上下文切换开销增大。源码中的实际线程池配置:服务最大线程数设计理由servicemanager0(基于 Looper)单线程,避免死锁surfaceflinger可变(通常 4)VSYNC 驱动,并发量有限gpuservice4统计与查询,中等并发media.codec64大量并行编解码会话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_NICESELinux 强制访问控制:每一次 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:s0seccomp‑bpf 沙箱:媒体服务使用,限制系统调用。SetUpMinijail()函数加载 seccomp 过滤器,限制进程可执行的系统调用,缩小恶意媒体内容的攻击面。12.1.9 原生服务关系图Java 侧system_server内部的WindowManagerService、InputManagerService、PackageManagerService通过 Binder 连接各个原生服务。原生服务位于上层 Java 框架与下层 HAL 实现之间,将高层 API 调用转换为硬件操作。12.2 SurfaceFlingerSurfaceFlinger 是显示合成服务,可以说是 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.hclass 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.cppLayer::Layer(const surfaceflinger::LayerCreationArgs args) : sequence(args.sequence), mFlinger(spSurfaceFlinger::fromExisting(args.flinger)), mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)), mWindowType(static_castWindowInfo::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 调度器与 VSYNCframeworks/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::vectorstd::unique_ptrRequestedLayerState); void applyTransactions(const std::vectorQueuedTransactionState, bool ignoreUnknownLayers = false); void onHandlesDestroyed(const std::vectorstd::pairuint32_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::optionalhal::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显示屏插拔创建 / 销毁 DisplayDeviceonRefreshHWC 请求刷新调度一次立即合成onVsyncPeriodTimingChanged刷新率变更过程中更新时序参数onVsyncIdle显示屏进入空闲(VRR 可变刷新率)调整空闲调度逻辑onHdcpLevelsChangedHDCP 保护等级变更更新内容保护状态12.2.11 ISurfaceComposer APISurfaceFlinger 通过 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 LatchUnsignaledLatchUnsignaledConfig控制 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 InputFlingerInputFlinger 处理全部用户输入:触摸、按键、手写笔、鼠标移动、游戏手柄按键,将事件分发到正确的应用窗口。它是 Android 中对延迟最敏感的服务之一,几毫秒额外延迟就可以被用户感知。12.3.1 源码目录结构InputFlinger 源码路径frameworks/native/services/inputflinger/目录用途reader/EventHub+InputReader:读取内核原始事件dispatcher/InputDispatcher:将事件路由到窗口reporter/InputReporter:上报未处理 / 丢弃按键(InteractionReporter 在 inputflinger 根目录,不在此处)trace/Perfetto 追踪集