Android14之BpBinder构造函数Handle拆解(二百零四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质专栏:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

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的实现主要涉及到以下几个类:
  1. IBinder:这是一个接口,定义了Binder对象的基本操作,如transact()和linkToDeath()等。BPBinder和BBinder都实现了这个接口。
  2. BBinder:这是Binder实体对象,存在于服务器进程中。它负责处理客户端发送的请求,并将处理结果返回给客户端。
  3. BpBinder:这是Binder代理对象,存在于客户端进程中。它负责将客户端的请求发送给服务器进程,并将服务器进程的返回结果返回给客户端。
  4. 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 使用 BinderHandleHandle handle1 = BinderHandle(123);BinderHandle binder = std::get<BinderHandle>(handle1); // 提取 handle1 中的 BinderHandle 类型值std::cout << "BinderHandle with id: " << binder.handle << std::endl;// v2.0 使用RpcHandleHandle 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 使用 BinderHandleHandle 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 使用RpcHandleHandle 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/588374.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第四百三十八回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 们在上一章回中介绍了"不同平台上换行的问题"相关的内容&#xff0c;本章回中将介绍如何在页面上显示蒙板层.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们…

MQ消息队列详解以及MQ重复消费问题

MQ消息队列详解以及MQ重复消费问题 1、解耦2、异步调用3、流量削峰4、MQ重复消费问题&#xff0c;以及怎么解决&#xff1f;4.1、重复消费产生4.2、解决方法&#xff1a; https://blog.csdn.net/qq_44240587/article/details/104630567 核心的就是&#xff1a;解耦、异步、削锋…

用html写一个爱心

<!DOCTYPE html> <html lang"zh-CN"><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8" /><title>爱您</title><style>* {padding: 0;margin: 0;}body {background-color: pin…

采用大语言模型进行查询重写——Query Rewriting via Large Language Models

文章&#xff1a;Query Rewriting via Large Language Models&#xff0c;https://arxiv.org/abs/2403.09060 摘要 查询重写是在将查询传递给查询优化器之前处理编写不良的查询的最有效技术之一。 手动重写不可扩展&#xff0c;因为它容易出错并且需要深厚的专业知识。 类似地…

SSRS错误:打开Web服务URL http 500 错误

安装完SSRS后&#xff0c;点击如下链接&#xff0c;出现 http 500 错误 查看 windows 的事件日志 发现是这个文件夹的读取权限出了问题&#xff0c;下面修改权限

Php_Code_challenge13

题目&#xff1a; 答案&#xff1a; 解析&#xff1a; 开启一个会话&#xff0c;在SESSION变量"nums"为空时则对"nums","time","whoami"进行赋值&#xff0c;并在120秒后关闭会话&#xff0c;创建一个变量"$value"…

STM32应用开发——使用PWM+DMA驱动WS2812

STM32应用开发——使用PWMDMA驱动WS2812 目录 STM32应用开发——使用PWMDMA驱动WS2812前言1 硬件介绍1.1 WS2812介绍1.1.1 芯片简介1.1.2 引脚描述1.1.3 工作原理1.1.4 时序1.1.5 传输协议 1.2 电路设计 2 软件编程2.1 软件原理2.2 测试代码2.2.1 底层驱动2.2.2 灯效应用 2.3 运…

Pulsar服务端处理消费者请求以及源码解析

引言 处理读写是Pulsar服务端最基本也是最重要的逻辑&#xff0c;今天就重点看看服务端是如何处理的读请求也就是消费者请求 正文 Pulsar服务端处理消费者请求的流程大致如下图所示 消费者通过TCP向服务端发起消息拉取请求Broker会根据请求中携带的ID来获取在服务端对应的…

华为交换机配置指引(包含安全配置部分)以 S5735S-L48T4S-A1 配置为例

华为S5735S-L48T4S-A1 是一款千兆以太网交换机: 端口结构: 48个10/100/1000BASE-T以太网端口和4个千兆SFP光接口供电方式: 交流电源背板带宽: 432Gbps包转发率: 87/166Mpps机箱高度: 1U重量: 2.76kg(不含包材)功耗: 典型功耗为43.3W接口: 48个10/100/1000BASE-T以太网电接口…

Incus:新一代容器与虚拟机编排管理引擎

Incus是什么&#xff1f; Incus是一个用于编排管理应用型容器、系统型容器及虚拟机实例的管理工具。它是对 Canonical LXD 的继承与发展&#xff0c;引入了更多的存储驱动支持。 Incus项目的产品地址&#xff1a;Linux Containers - Incus - Introduction 在 LXC-Incus 项目…

FebHost:人工智能时代的新宠儿.AI域名

近年来,人工智能技术在各行各业迅猛发展,正在深刻改变着我们的生活。作为AI领域的专属域名,.AI域名正成为越来越多企业和个人的首选。 那么,.AI域名到底是什么呢?它是一种特殊的顶级域名(Top-Level Domain, TLD),于2013年由 安哥拉政府正式退出。与其他通用顶级域名如.com、.…

QT网络调试助手

QT网络调试助手 1.开发流程 2.QTtcp服务器   1.1 服务端数据读取   1.2 服务端发送数据-所有客户端   1.3 服务端自动刷新ip地址   1.4 服务端检测客户端断开状态   1.5 服务端发送数据-指定特定客户端发送数据   1.6 服务端停止监听和断开 3.QTtcp客户端 1…