Android 之 AIDL

1.Android Binder 框架中 BpXXX 与 BnXXX 架构总结

一、核心类关系

  1. 接口层
    ├─ IXXX: 定义业务逻辑接口(如图中 IMediaPlayer)

    ├─ BpXXX: 客户端代理 (Proxy)
    │ ├─ 继承关系: public IXXX, public BpRefBase
    │ └─ 核心成员: mRemote (BpBinder*)

    └─ BnXXX: 服务端实现 (Native)
    ├─ 继承关系: public IXXX, public BBinder
    └─ 业务载体: MediaPlayerService::Client

  2. 通信基类
    ├─ IBinder: 进程间通信核心接口
    ├─ BpBinder: 客户端通信实体
    └─ BBinder: 服务端通信实体

  3. 驱动交互层
    └─ BinderDriver: 通过 ioctl 系统调用交互

二、BpXXX (客户端代理) 核心机制

  1. 工作流程:
    客户端调用 → 打包 binder_transaction_data → mRemote.transact() → Binder驱动

  2. 核心组件:

    • BpRefBase::remote(): 获取 BpBinder 驱动接口
    • IPCThreadState: 通过 transact() 发起通信
    • Parcel 数据封装: 序列化调用参数
  3. 功能特点:
    ▸ 对客户端透明隐藏 IPC 细节
    ▸ 同步等待服务端返回结果
    ▸ 维护与远程服务的连接状态

三、BnXXX (服务端实现) 核心机制

  1. 工作流程:
    Binder驱动接收请求 → BBinder::transact() → BnXXX::onTransact() → 执行业务逻辑

  2. 核心组件:

    • onTransact() 方法: 解析请求并分派到具体业务
    • 业务实现类: 如 MediaPlayerService::Client
    • ObjectManager: 管理服务对象生命周期
  3. 功能特点:
    ▸ 实现具体业务逻辑(如音视频播放控制)
    ▸ 响应客户端请求并返回结果
    ▸ 运行在服务端进程的 Binder 线程池中

四、IPC 通信全流程

客户端进程 Binder驱动 服务端进程
┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐
│ BpXXX │ │ │ │ BnXXX │
│ - 方法调用 │1 │ │3 │ - onTransact() │
│ - Parcel打包 ├─────►│ 消息路由 ├─────►│ - 业务执行 │
│ │ │ │ │ │
│ 等待响应 ◄────────┤4 │ │2 │ 返回结果 ◄───────┤
└─────────────────┘ └──────────────┘ └─────────────────┘
步骤说明:

  1. BpRefBase::remote() 调用 BpBinder
  2. BinderDriver 通过 ioctl 传递消息
  3. IPCThreadState 唤醒服务端线程
  4. 反向路径返回执行结果

五、架构设计

  1. 接口统一性

    • BpXXX 和 BnXXX 共享相同的 IXXX 接口
    • 保证客户端调用与服务端实现的一致性
  2. 双向通信

    • 客户端可调用服务端方法(BpXXX → BnXXX)
    • 服务端可主动通知客户端(通过 callback 接口)
  3. 线程模型

    • PoolThread: 维护 Binder 线程池
    • ProcessState: 管理进程级 Binder 资源
    • IPCThreadState: 管理线程级通信状态

2.transact()onTransact()

一. 函数定义与角色定位

  • transact()

    • 定义:位于客户端代理对象(Proxy类)中,由AIDL自动生成。
    • 作用:将客户端的调用请求打包为Parcel数据,通过Binder驱动发送到服务端。
    • 调用路径:客户端调用接口方法 → Proxy类方法 → transact() → Binder驱动 → 服务端。
  • onTransact()

    • 定义:位于服务端Stub类(继承Binder)中,由AIDL自动实现。
    • 作用:接收Binder驱动转发的Parcel数据,解析请求参数,调用服务端实际业务逻辑,并将结果返回。
    • 调用路径:Binder驱动 → Stub.onTransact() → 服务端业务方法 → 结果返回客户端。

二. 执行流程与线程模型

  1. 客户端发起请求

    • 客户端调用AIDL接口方法(如getSum())。
    • Proxy类创建Parcel对象(_data写入参数,_reply预留返回结果),调用transact()
    • 客户端线程阻塞,等待服务端响应。
  2. 服务端处理请求

    • Binder驱动将请求路由到服务端进程的Binder线程池
    • 线程池中某个线程执行Stub.onTransact()
      • 解析Parcel中的方法标识符code参数,如TRANSACTION_addBook)。
      • Parcel中读取参数,调用服务端对应的业务方法(如addBook())。
      • 将返回值写入_reply
  3. 结果返回客户端

    • 服务端处理完成后,Binder驱动将_reply返回客户端。
    • 客户端线程唤醒,从_reply中读取结果并返回。
线程模型对比
函数执行位置线程特性
transact()客户端进程调用线程阻塞(如主线程需防ANR)
onTransact()服务端Binder线程池异步执行,需线程安全设计

三. 参数解析与数据封装

  • transact()的关键参数

    • code:方法标识符(由AIDL自动生成),用于服务端区分调用的方法。
    • data:输入型Parcel,封装方法参数。
    • reply:输出型Parcel,预留结果存储空间。
    • flags:控制调用行为(如FLAG_ONEWAY表示异步调用)。
  • onTransact()的关键参数

    • code:与transact()中的code对应,标识目标方法。
    • data:接收客户端发送的Parcel,需按顺序读取参数。
    • reply:向其中写入结果,返回给客户端。
Parcel的作用
  • 作为跨进程数据传输的容器,支持基本类型、Parcelable对象、Binder引用等。
  • 序列化/反序列化由系统自动处理,开发者只需按顺序读写数据。

四. 设计原理与异常处理

  • 协同关系
    transact()onTransact()通过相同的code标识符对称的Parcel读写顺序实现方法映射与参数传递,构成一套类RPC(远程过程调用)的IPC机制。

  • 异常场景

    • 服务端进程崩溃transact()抛出RemoteException,客户端需通过linkToDeath()监听Binder死亡通知以重连。
    • 跨进程类型安全:自定义Parcelable对象需严格保持读写一致性,否则会导致Parcel数据解析错位。
  • 性能优化

    • 单向调用FLAG_ONEWAY):添加oneway关键字可使调用非阻塞,但无返回值。
    • Binder线程池:默认最大16个线程,高并发时需优化服务端业务逻辑的耗时。
  • 两者关系图示

客户端进程                         服务端进程
│                                  │
│ 1. 调用AIDL接口方法               │
│ 2. Proxy.transact()              │
│    - 打包Parcel (_data)          │
│    - 发送请求 → Binder驱动 →       │
│                                  │ 3. Binder线程池调用Stub.onTransact()
│                                  │    - 解析code标识方法
│                                  │    - 从_data读取参数
│                                  │    - 执行实际业务逻辑
│                                  │    - 结果写入_reply
│ 4. 收到响应 ← Binder驱动 ←         │
│    - 从_reply解析结果             │
│ 5. 返回结果                      │

核心关系transact()是跨进程调用的发起端onTransact()执行端,两者通过Binder驱动和Parcel数据容器协作,实现跨进程通信的透明化调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值