简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀
优质专栏:AAOS车载系统+AOSP14系统攻城狮入门实战课【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:在阅读Android14源码,BpBinder代码时,发现它的构造函数特别有意思,随分享之。
2.BPBinder介绍
- BPBinder是Android系统中Binder机制的一部分,负责在客户端和服务器之间进行进程间通信(Inter-Process Communication,IPC)。Binder机制是Android系统中实现跨进程通信的核心机制,它允许一个进程(客户端)调用另一个进程(服务器)中的方法,就像调用本地方法一样简单。
- BPBinder是Binder代理对象,它存在于客户端进程中。当客户端进程想要与服务器进程通信时,它会创建一个BPBinder对象,并通过这个对象发送请求给服务器进程。BPBinder内部会通过Binder驱动程序与服务器进程中的BBinder对象进行通信,从而完成客户端和服务器之间的通信。
- BPBinder的主要作用是封装客户端的请求,并将这些请求发送给服务器进程。它会将客户端的请求转化为一个IPC消息,然后将这个消息发送给Binder驱动程序。Binder驱动程序会将这个消息传递给服务器进程中的BBinder对象,由BBinder对象来处理这个请求,并将处理结果返回给客户端。
- BPBinder的实现主要涉及到以下几个类:
- IBinder:这是一个接口,定义了Binder对象的基本操作,如transact()和linkToDeath()等。BPBinder和BBinder都实现了这个接口。
- BBinder:这是Binder实体对象,存在于服务器进程中。它负责处理客户端发送的请求,并将处理结果返回给客户端。
- BpBinder:这是Binder代理对象,存在于客户端进程中。它负责将客户端的请求发送给服务器进程,并将服务器进程的返回结果返回给客户端。
- Parcel:这是一个数据容器,用于在客户端和服务器之间传递数据。客户端将请求数据写入Parcel对象,然后将这个对象发送给服务器。服务器处理完请求后,将结果写入Parcel对象,然后将这个对象返回给客户端。
- BPBinder的使用非常简单,客户端只需要创建一个BPBinder对象,然后调用它的transact()方法即可发送请求给服务器。transact()方法有两个参数:第一个参数是请求码,用于标识请求的类型;第二个参数是请求数据,通常是一个Parcel对象。服务器进程中的BBinder对象会根据请求码和请求数据进行处理,并将处理结果写入一个Parcel对象中返回给客户端。
- 总之,BPBinder是Android系统中Binder机制的重要组成部分,它实现了客户端和服务器之间的进程间通信。通过BPBinder,客户端可以像调用本地方法一样调用服务器进程中的方法,从而实现跨进程通信。
3.BpBinder构造函数拆解
<1>.先看BpBinder::BpBinder构造函数的参数
BpBinder::BpBinder(Handle&& handle)
: mStability(0),
mHandle(handle),
mAlive(true),
mObitsSent(false),
mObituaries(nullptr),
mDescriptorCache(kDescriptorUninit),
mTrackedUid(-1) {
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
}
- BpBinder构造函数只有一个参数,然后初始化列表给了mHandle。
<2>.再看Handle类型
struct BinderHandle {
int32_t handle;
};
struct RpcHandle {
sp<RpcSession> session;
uint64_t address;
};
using Handle = std::variant<BinderHandle, RpcHandle>;
- 这里使用了C++17标准库提供的模板类,它表示一种可以容纳多种不同类型的值的类型安全的联合体(Union)。
- 然后给std::variant<BinderHandle, RpcHandle>起了个别名,叫Handle,但是我们可以从别名Handle中取得联合体中的BinderHandle和RpcHandle两个结构体。
<3>.Bpbidner用Handle之前,需要判断下
bool BpBinder::isRpcBinder() const {
return std::holds_alternative<RpcHandle>(mHandle);
}
- 这里使用检查 std::holds_alternative模板类,判断mHandle是否包含 BinderHandle 类型,如果包含返回true;
- 如果不包含则返回false。
<4>.判断完了mHandle,看看到底怎么用?
uint64_t BpBinder::rpcAddress() const {
return std::get<RpcHandle>(mHandle).address;
}
- 这里直接调用std::get(mHandle).address,可以分为两个步骤:
- 第一:先通过std::get(mHandle)获取联合体mHandle中的RpcHandle结构体对象。
- 第二:调用RpcHandle结构体的address变量。
<5>.再看俩例子
const sp<RpcSession>& BpBinder::rpcSession() const {
return std::get<RpcHandle>(mHandle).session;
}
int32_t BpBinder::binderHandle() const {
return std::get<BinderHandle>(mHandle).handle;
}
- 和在第四步用法一样,没啥说的。
3.仿BpBinder构造函数用法实例
v1.0
#include <iostream>
#include <variant>
#include <string>
using namespace std;
struct BinderHandle {
BinderHandle(int han) : handle(han){}
int32_t handle;
};
struct RpcHandle {
RpcHandle(string han) : address(han){}
string address;
};
// 定义 Handle 类型别名,表示可以是 BinderHandle 或 RpcHandle 类型的变量
using Handle = std::variant<BinderHandle, RpcHandle>;
int main() {
// v1.0 使用 BinderHandle
Handle handle1 = BinderHandle(123);
BinderHandle binder = std::get<BinderHandle>(handle1); // 提取 handle1 中的 BinderHandle 类型值
std::cout << "BinderHandle with id: " << binder.handle << std::endl;
// v2.0 使用RpcHandle
Handle handle2 = RpcHandle("Hello Handle."); // 创建一个 Handle 变量,并用 RpcHandle 初始化
RpcHandle rpc = std::get<RpcHandle>(handle2); // 提取 handle2 中的 RpcHandle 类型值
std::cout << "RpcHandle with id: " << rpc.address << std::endl;
return 0;
}
v2.0
#include <iostream>
#include <variant>
#include <string>
using namespace std;
struct BinderHandle {
BinderHandle(int han) : handle(han){}
int32_t handle;
};
struct RpcHandle {
RpcHandle(string han) : address(han){}
string address;
};
// 定义 Handle 类型别名,表示可以是 BinderHandle 或 RpcHandle 类型的变量
using Handle = std::variant<BinderHandle, RpcHandle>;
int main() {
// v1.0 使用 BinderHandle
Handle handle1 = BinderHandle(123);
if (std::holds_alternative<BinderHandle>(handle1)) { // 检查 handle1 是否包含 BinderHandle 类型的值
BinderHandle binder = std::get<BinderHandle>(handle1); // 提取 handle1 中的 BinderHandle 类型值
std::cout << "BinderHandle with id: " << binder.handle << std::endl;
}
// v2.0 使用RpcHandle
Handle handle2 = RpcHandle("Hello Handle."); // 创建一个 Handle 变量,并用 RpcHandle 初始化
if (std::holds_alternative<RpcHandle>(handle2)) { // 检查 handle1 是否包含 RpcHandle 类型的值
RpcHandle rpc = std::get<RpcHandle>(handle2); // 提取 handle2 中的 RpcHandle 类型值
std::cout << "RpcHandle with id: " << rpc.address << std::endl;
}
return 0;
}