Framework开发专题系列四:Binder基础

1. 引言

Android 系统基于 Binder 实现了"透明"的进程间通信。从应用调用系统服务(startActivity),到 Wi‑Fi 驱动向 WifiService 上报事件,再到硬件抽象层(HAL)与系统服务的数据交换,Binder 无处不在。因此,理解 Binder 及其上层封装,是 ROM 开发者进行系统定制、性能分析、功能扩展的必备能力

Binder 本身是一个庞大的主题。本期"Framework 开发专题系列四"不深究内核驱动细节,而是聚焦于 Framework 中五种最常见的 Binder 应用形态,帮助你在阅读和修改源码时能够快速识别并选择最合适的 IPC 方式。

2. Binder 架构分层总览

Android 的 Binder 体系从下到上可分为三层:
内核层
硬件抽象层
Native 框架层
应用与框架层
AIDL

Java 接口定义
Messenger

Handler 信使
AsyncChannel

双向异步通道
Native Binder

libbinder C++ 接口
系统服务: AMS/WMS/...
HIDL

硬件接口定义语言
Binder 驱动 /dev/binder

  • 内核 Binder 驱动 :提供基础 IPC 能力,管理跨进程的 transaction
  • Native Binder (libbinder) :C++ 封装,提供 BpBinderBnBinder 等核心类。
  • Java Binder 框架 :通过 JNI 调用 libbinder,提供 IBinderBinderBinderProxy 等类。
  • 上层 IPC 封装:为了让开发者更方便地使用 Binder,Android 提供了多种高级封装,例如 AIDL、Messenger、AsyncChannel;而在硬件抽象层,则使用 HIDL(正逐步向 AIDL 迁移)。

下文逐一剖析这五种形态。

3. AIDL ------ Java 层 IPC 标准姿势

AIDL(Android Interface Definition Language) 是 Android 官方推荐的跨进程接口定义语言,底层基于 Binder 实现。它允许开发者像定义普通接口一样声明远程服务的方法,由 aidl 编译器自动生成 Java 代理类和桩类。

3.1 基本使用流程

  1. 定义 .aidl 文件,声明接口和方法。
  2. 在 Service 端实现 Stub 抽象类。
  3. 在 Client 端通过 bindService 获取 Proxy 对象并调用。

生成的代码中,Stub 继承自 Binder 并实现接口,Proxy 持有 IBinder 对象并使用 transact 发送请求。

3.2 AIDL 定向 tag

Android 10+ 的 AIDL 支持方法参数的定向标注:

  • in:数据从客户端流向服务端(可跨进程传递)。
  • out:数据从服务端流回客户端(服务端修改后客户端可见)。
  • inout:双向流动。

Framework 中大量系统服务接口都使用了这些标注以优化拷贝次数。

3.3 Stable AIDL(稳定 AIDL)

从 Android 10 开始,AIDL 支持声明为 stable,其接口被版本化管理,可像 SDK API 一样保证跨系统更新兼容。System 分区的 Framework 服务与 Vendor 分区的 HAL 实现之间的通信,正逐步从 HIDL 迁移到 Stable AIDL。

java 复制代码
// 稳定 AIDL 接口声明
@VintfStability
interface IMyService {
    int getValue();
}

4. Native Binder ------ C++ 世界中的原始力量

许多系统服务(如 SurfaceFlingermedia 相关服务)本身就是 Native 进程,它们使用 libbinder 提供的 C++ Binder 接口进行通信。

4.1 核心类架构

Server Side
Client Side
transact
onTransact
Client 进程
BpBinder
Binder 驱动
BBinder
Server 进程
BpRefBase
具体服务实现

  • BBinder :服务端桩,需重写 onTransact 方法处理请求。
  • BpBinder :客户端代理,通过 handle 对象与驱动交互。
  • BpRefBase:为代理提供引用计数。

4.2 Framework 实例:SurfaceFlinger

SurfaceFlinger 是一个独立的 Native 进程,其服务端继承自 BBinder,客户端通过 ISurfaceComposer 接口调用。以获取显示信息为例:

cpp 复制代码
// 客户端调用
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
sf->getDisplayConfigs(displayToken, &configs);

内部通过 BpSurfaceComposer::transact 将请求序列化并发送给 Service 进程,BnSurfaceComposer::onTransact 解包并调用实际函数。

4.3 与 AIDL 的关系

实际上,AIDL 编译器生成的 Java 代码底层也是通过 JNI 调用 libbindertransact 方法。而 C++ 服务同样可以使用 AIDL 来定义接口(C++ 后端),使得 Native 服务开发也具备接口标准化和版本管理能力。

5. HIDL ------ 硬件抽象层的接口定义语言

HIDL(HAL Interface Definition Language) 是 Android 8.0 引入的,用于定义 HAL 与 Framework 之间的接口。它的诞生源于 Project Treble,目的是将 HAL 实现放置在 Vendor 分区,与 System 分区的 Framework 完全解耦。

5.1 HIDL 架构

HIDL 调用
Binder IPC
应用
Framework 服务
HIDL 客户端存根
HIDL 服务端实现
HAL 硬件模块

HIDL 接口定义在 .hal 文件中,编译后自动生成 C++(或 Java)的客户端/服务端代码。服务端注册到 hwservicemanager,客户端通过 getService 获取代理。

5.2 常用 HIDL 接口示例

  • IComposer:显示屏合成接口
  • ICameraProvider:相机服务接口
  • ISensor:传感器接口

5.3 从 HIDL 到 AIDL 的迁移

Android 14 之后,Google 宣布 HIDL 已废弃,转而使用 Stable AIDL 来定义 HAL 接口。与 HIDL 相比,AIDL 的优势在于:

  • 语法更简洁,生态系统更健全。
  • 支持 C++ 和 Java,而 HIDL 主要面向 C++。
  • 可直接复用上层 AIDL 工具链。

因此,作为 ROM 开发者在维护旧平台时仍需理解 HIDL,但在新平台中应优先使用 Stable AIDL。

6. AsyncChannel ------ 双向异步通信通道

AsyncChannel 是 Framework 内部使用的一套基于 Handler + Binder 的双向异步消息通道 。它允许两个实体(可能位于不同进程)互相发送消息,每个实体都有自己的 Handler 线程来接收和处理消息。

6.1 设计目的

普通 Service 通过 Binder 调用是同步的(客户端调用服务端方法后等待返回),但在系统中有些场景需要 异步、双向、无返回值 的通信,比如:

  • Wi‑Fi 驱动状态变化需要实时告知 WifiService
  • WifiService 也需要向状态机发送控制命令。

AsyncChannel 就是为此而生。

6.2 连接模型

Server AsyncChannel Client Server AsyncChannel Client loop [双向消息传递] connect(context, handler, messenger) CMD_CHANNEL_HALF_CONNECTED sendReply(STATUS_SUCCESSFUL) CMD_CHANNEL_FULL_CONNECTION sendMessage(msg) msg 投递到 Server Handler sendMessage(msg) msg 投递到 Client Handler

建立连接后,双方都持有一个 AsyncChannel 对象,通过 sendMessage(msg) 发送 Message,对方的 Handler 会收到并处理。底层仍使用 Binder 进行跨进程传输,但所有细节被封装。

6.3 Framework 中的实际应用

WifiStateMachineWifiService 之间即通过 AsyncChannel 通信:

  • WifiService 的客户端(SystemUI、Settings)通过 Binder 调用 WifiService 暴露的 API。
  • WifiStateMachine 跑在 WifiService 所属进程中,WifiService 使用 AsyncChannel 向状态机发送命令(如 CMD_START_SCAN)。
  • WifiStateMachine 的状态变化则通过 AsyncChannel 异步通知到 WifiService

另一个典型应用是 Telephony 中的 RILPhone 之间的通信。

7. Messenger ------ 轻量级的 Handler 通信

Messenger 是一个基于 Binder 和 Handler 的轻量级 IPC 机制,适用于简单的单向或双向消息传递,不需要定义复杂的 AIDL 接口。

7.1 实现原理

Messenger 内部包含一个 Handler 引用,对外提供 IMessenger 接口(AIDL 定义):

java 复制代码
// frameworks/base/core/java/android/os/Messenger.java
private final IMessenger mTarget;

public Messenger(Handler target) {
    mTarget = new IMessengerImpl(target);
}

当客户端调用 Messenger.send(Message) 时,消息被序列化,通过 Binder 发送到服务端,服务端的 IMessengerImpl 收到后直接 handler.sendMessage()

7.2 双向通信

两个进程各持有一个 Messenger 对象的话,即可实现双向通信。典型做法是在 Message.replyTo 中放置客户端自己的 Messenger,服务端收到后可向该 Messenger 回复消息。

7.3 应用场景

  • 跨进程通知 :比如音乐播放服务通过 Messenger 向客户端发送播放进度。
  • 绑定服务:不想显式定义 AIDL 时的便利选择。
  • Messenger 在 Framework 中常见于系统通知、MediaRouter 等组件。

与 AsyncChannel 的区别

特性 AsyncChannel Messenger
使用范围 Framework 内部专用 应用层、Framework 均可
通信模式 全双工异步通道,自动管理连接确认 基于 Message 传递,需手动处理 replyTo
底层 仍基于 Binder,但封装了完整的状态机 直接依赖 Binder(IMessenger.aidl)
灵活性 功能强大,但使用复杂,未开放给应用 简单易用,轻量级

8. 五种 Binder 应用形态对比与选型指南

形态 层次 适用场景 主要优点 主要局限
AIDL Java / C++ 系统服务接口、应用间 IPC 类型安全、支持复杂对象、可版本化 需要定义接口,编译步骤多
Native Binder C++ (libbinder) Native 服务(SurfaceFlinger等) 性能极高,直接操作 C++ 对象 学习曲线陡,手动管理引用
HIDL HAL / Framework 硬件抽象层接口(旧) 与 Treble 架构融合,自动生成代码 语法独立,已废弃,迁移成本高
AsyncChannel Java Framework 系统内部异步双向通道 双向异步,自动连接确认,Handler 驱动 未公开为 API,仅限 Framework
Messenger Java 简单的跨进程消息传递 无需 AIDL,快速开发,支持双向 不类型安全(Message.what),不适合复杂数据

选型建议

  • 对于体系化、需要多版本支持的新接口 ,优先选择 Stable AIDL
  • 在 Native 进程中,若已有成熟接口,可使用 Native Binder ;新设计应使用 AIDL C++ 后端
  • 对于 Framework 内部组件间的异步命令通信,使用 AsyncChannel(照搬已有模块模式)。
  • 当只是传递简单的 Message 且不想引入 AIDL 时,Messenger 是最佳选择。
  • HIDL 仅维护旧平台,新平台应向 AIDL 迁移。

9. 总结与学习建议

Binder 是 Android 系统的"神经系统",掌握其上层封装比死磕驱动层更实用。建议 ROM 开发者按照以下路径学习:

  1. 从 AIDL 实操开始 :手写一个简单的 AIDL 服务,查看生成的代码,理解 StubProxy 的运行机制。
  2. 阅读 Framework 中的 Native Binder 服务 :从 SurfaceFlinger 入手,跟踪一下 createDisplay 的 IPC 流程。
  3. 分析 AsyncChannel 典型用例 :打开 WifiStateMachineWifiService,理解其双向通信机制。
  4. 关注 HIDL → AIDL 迁移:了解 Google 的最新架构演进方向,避免在新平台上走弯路。
相关推荐
andr_gale8 天前
04_rc文件语法规则
android·framework·aosp
帅次8 天前
Android 高级工程师专题深挖:WebView、Context 与初始化链
android·binder·webview·zygote·web app·dalvik
帅次10 天前
Android 高级工程师面试速记版
android·java·面试·kotlin·binder·zygote·android runtime
帅次15 天前
Android 高级工程师面试参考答案:Framework、生命周期、View 与 Binder
android·面试·binder
su_ym811016 天前
Android属性系统
android·framework·property
千里马学框架16 天前
Android Automotive CarService 和 CarManager 源码剖析
android·车载系统·framework·系统开发·car framework
Grackers19 天前
Android Perfetto 系列 10:Binder 调度与锁竞争
android·binder
su_ym811021 天前
Android 系统源码阅读与编译构建实战指南
android·framework
su_ym811021 天前
Android 与 Linux 对比
android·linux·framework