aidl原理

news2024/11/19 19:23:38

aidl 流程

为了方便理解,先将binder看做是一个黑盒子 aidl的流程图如下
在这里插入图片描述
demo连接添加链接描述

Androidstudio 会帮我们生成emotionAidlService,具体目录在n\build\generated\aidl_source_output_dir\debug\out\com\example\emotion\emotionAidlService.java

emotionAidlService.java 代码讲解:

其中核心代码:

stub内部类里面有两个关键函数:

1、asInterface

    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.example.emotion.emotionAidlService))) {
        return ((com.example.emotion.emotionAidlService)iin);
      }
      return new com.example.emotion.emotionAidlService.Stub.Proxy(obj);   //核心代码1
    }

该核心代码就是创建一个Proxy对象,同时将IBinder对象的obj传递给Proxy
2,onTransact()

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
    {
      java.lang.String descriptor = DESCRIPTOR;
      switch (code)
      {
        case INTERFACE_TRANSACTION:
        {
          reply.writeString(descriptor);
          return true;
        }
        case TRANSACTION_RobotLookUp:
        {
          data.enforceInterface(descriptor);
          int _arg0;
          _arg0 = data.readInt();
          int _arg1;
          _arg1 = data.readInt();
          this.RobotLookUp(_arg0, _arg1);    //核心代码2
          reply.writeNoException();
          return true;
        }
        case TRANSACTION_RobotWarning:
        {
          data.enforceInterface(descriptor);
          this.RobotWarning();
          reply.writeNoException();
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }

onTransact函数功能主要是接收来自binder底层的调用,通过binder底层onTransact函数,将函数执行到核心代码2中

Prox类里面的关键函数 RobotLookUp

   @Override public void RobotLookUp(int y, int p) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeInt(y);
          _data.writeInt(p);
          boolean _status = mRemote.transact(Stub.TRANSACTION_RobotLookUp, _data, _reply, 0);  //核心代码
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().RobotLookUp(y, p);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }

这个函数是和aidl文件里面定义的函数名字是一样的,后面进行跨进程通信会引用到则个函数,这个的功能是创建一个parcel数据_data
,为什么必须是Parcel数据了,因为Android跨进程传递的数据必须序列化,而序列化所采用的方式就是parcel。parcel序列化,主要实现
是在native层,而binder 通信主要的部分是在nativee层。另外,如果跨进程的调用RobotLookUp有返回值,那么这个返回值将以_replay来存储和传递

emotionAidlService的类结构图:

在这里插入图片描述

总结

binder基于AIDL的通信流程图如下:
Client端:MainActivity;
Server端:Service;
Service的对外aidl接口如上面的案例所示,
MainActivity已经通过BindService拿到了Service的IBinder对象。
在这里插入图片描述
aidl通信的基本步骤如下:

  1. Client通过ServiceConnection获取到Server的Binder,并且封装成一个Proxy。
  2. 通过Proxy来同步调用IPC方法(testFunction),同时通过Parcel将参数传给Binder,最终触发Binder的
    transact方法。
  3. Binder的transact方法最终会触发到Server上Stub的onTransact方法。
  4. Server上Stub的onTransact方法中,会先从Parcel中解析中参数,然后将参数带入真正的方法中执行,然后将
    结果写入Parcel后传回。
  5. 请注意:Client的Ipc方法中,执行Binder的transact时,是阻塞等待的,一直到Server逻辑执行结束后才会继
    续执行。当然,如果IPC方法是oneWay的方式,那么就是非阻塞的等待。
  6. 当Server返回结果后,Client从Parcel中取出返回值,于是实现了一次IPC调用。

Aidl是同步调用还是异步调用?

经过上述分析:aidl的的调用过程是同步调用的。
当我们需要服务端做耗时操作时,肯定是不能使用同步调用的,否则轻者影响用户体验,重者直接 ANR 或者应用崩溃。那么如何使 AIDL 的调用过程是异步的呢?
只需要把调用放到非 UI 线程即可,如果要对调用的返回做 UI 更新的话,再通过 Handler 处理即可。或者通过回调去更新UI

AIDL通信出现DeadObjectException解决方法

1、这个方案比较简单粗暴,就是在多有调用跨进程接口的地方,都加一个Binder是否存活的判断。

   mEmotionAidlService.asBinder().isBinderAlive();

2、监听Binder死亡通知
先初始化一个DeathRecipient,用来监听死亡通知

   IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            // 解绑当前监听,重新启动服务
            mEmotionAidlService.asBinder().unlinkToDeath(mDeathRecipient, 0);
            if (mEmotionAidlService != null){
               bindService(intent, serviceConnection, BIND_AUTO_CREATE);
            }
        }
    };```
在onServiceConnected方法中,注册死亡监听:

```go
 serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i(TAG,"onServiceConnected");
                 mEmotionAidlService =  emotionAidlService.Stub.asInterface(service);
//                mEmotionAidlService.asBinder().isBinderAlive();
                if(mEmotionAidlService != null){
                    try {
                        mEmotionAidlService.asBinder().linkToDeath(mDeathRecipient,0);
                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }  
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i(TAG,"onServiceDisconnected");
                mEmotionAidlService=null;
            }
        };

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

swiftUI和swift的区别

概述 SwiftUI是苹果公司推出的一种用于构建iOS、macOS、watchOS和tvOS应用程序界面的框架。它是基于Swift编程语言开发的,旨在简化UI开发过程并提供实时预览功能,使开发人员可以更快地构建出漂亮的应用程序界面。 Swift是苹果公司推出的一种面向对象的…

【QT】混合UI设计

虽然利用Designer和代码的设计方式都可以开发GUI,但是毫无疑问的是最有效的开发方式是利用两者进行混合开发。 下面这个实验例子来自《QT5.9 C开发指南》,我做了小部分修改,最终效果是这样: 图标导入 这次我们要开发的是一个有工…

AprilTag码估算平面法向量+相机标定

由于本人部分原创博客发布在古月居论坛,详细内容点击链接跳转: 1. AprilTag探索和原理分析 2. 相机标定,基于AprilTag估算平面法向量

web安全php基础_php常量及可变变量(魔术变量)

常量 php中常量是一个简单值的标识符。该值在脚本中不能改变。 一个常量由英文字母、下划线、和数字组成,但数字不能作为首字母出现。 (常量名不需要加 $ 修饰符)。 常量有两点需要特别注意的地方 常量在整个脚本中都可以使用。常量值被定义后,在脚本的其他任何…

企业级CDP数据工程实践(一):建设中的最佳实践

大家好,许久未见,我是云祁~ 今天想和大家分享下 企业级CDP项目 建设中的数据工程实践。 在很多情况下,大家可能会将数据工程与ETL的过程画上等号,但实际上ETL只是数据工程的一部分,其工作量通常仅占整个数据…

I.MX6ULL_Linux_驱动篇(40)异步通知

在前面使用阻塞或者非阻塞的方式来读取驱动中按键值都是应用程序主动读取的,对于非阻塞方式来说还需要应用程序通过 poll 函数不断的轮询。最好的方式就是驱动程序能主动向应用程序发出通知,报告自己可以访问,然后应用程序在从驱动程序中读取…

Linux——进程信号(下)

目录 总结 一,信号保存 1.1 阻塞信号 2.2 信号在内核(操作系统)中的表示 2.3 系统接口 2.3.1 sigset_t信号集 2.3.2 信号集的操作函数 2.3.3 sigprocmask 2.3.4 sigpending 2.4 实验样例 三,信号处理 3.1 信号捕捉 3.2 sigaction接口 3.3 实验…

2022年真题 - 17 - 系统优化

系统优化 题目配置验证配置 题目 StorageSrv - 系统优化 系统资源限制设置:设置所有用户的硬件跟软件的最大进程数、最大文件打开数为65535;开启 IPv4 恶意 icmp 错误消息保护;开启 SYN 洪水攻击保护;允许系统打开的端口范围为 …

服务网关 Gateway

服务网关 Gateway 服务网关介绍Gateway 介绍Gateway 和 Nginx 网关的区别Gateway 核心概念Gateway工作流程 Gateway 案例Predicate(断言)After 路由谓词工厂Before路由谓词工厂Between 路由谓词工厂Cookie路由谓词工厂Header 路由谓词工厂Host 路由谓词工…

支付宝支付(六):小程序支付(Go+Gin+内网穿透)

一、前置条件 (1)go语言,1.18 (2)Gin、第三方依赖包:gopay【github.com/go-pay/gopay/alipay】https://github.com/go-pay/gopay/blob/main/doc/wechat_v3.md (3)支付宝支付相关信…

Java面向对象程序开发——JDK8新特性

文章目录 网络编程入门知识JDK8新特性Lambda表达式以多线程为例:Lambda结合for循环: Stream流获取一个流的2种常用的方式:常用方法终结方法延迟方法 案例 网络编程入门知识 软件结构、协议分类、网络通信协议、网络编程三要素、TCP通信协议、…

爬虫的分布式思维与实现思路

爬虫的分布式思维与实现思路 基本构架 scrapy-redis实现分布式,其实从原理上来说很简单,这里为描述方便,我们把自己的核心服务器称为master,而把用于跑爬虫程序的机器称为slave 我们知道,采用scrapy框架抓取网页&…

netty学习(4):通过SpringBoot Web发送消息实现netty实现多个客户端与服务器通信

1. 基于netty学习(3):SpringBoot整合netty实现多个客户端与服务器通信的学习,要想通过http在netty客户端之间发送消息,需要实现spring-boot-starter-web,封装消息格式,自动调用netty客户端 2. 封装一个简单…

算法笔记——哈希表篇

一般哈希表都是用来快速判断一个元素是否出现集合里,哈希表并不意味着一定要使用HashMap,有时候使用数组更方便,有时候要使用set,依据具体情况而定,哈希表是典型的空间换时间。 数组作为哈希表 一些应用场景就是为数组…

工具 | 应用程序无法启动,应为应用程序的并行配置不正确

工具 | 应用程序无法启动,应为应用程序的并行配置不正确 “E:\02-Doc\朱老师物联网大讲堂-全部视频\朱有鹏老师嵌入式linux核心课程\开发版光盘资料\X210V3S_A\tools\x210_Fusing_Tool.exe”的激活上下文生成失败。 找不到从属程序集 Microsoft.VC90.MFC,processorA…

DNS-去中心化域名系统,创建您在DeSoc 社会中的YUAN ID

传统域名系统 (DNS) 是一个分层的分散信息存储,用于将用户在网络浏览器中输入可读名称(例如 www.baidu.com)解析为IP地址,来访问互联网上的计算机。传统DNS使用一种分布式数据库,有严格的上下级关系,上级仅…

[Android JNI] --- JNIEnv和JavaVM

1 JVMEnv 1.1 JNIEnv 是什么 JNIEnv 即 Java Native Interface Environment,Java 本地编程接口环境。JNIEnv 内部定义了很多函数用于简化我们的 JNI 编程。 JNIEnv是提供JNI Native函数的基础环境,线程相关,不同线程的JNIEnv相互独立&#…

SpringBoot快速回顾(@value读取配置文件)

目录 1.定义配置文件2. 定义Controller类3. 测试4. 优化4.1 封装实体类4.3 定义controller类4.2 测试 本文将介绍如何使用value读取配置文件的内容。 在实际项目中,往往会在配置文件中写项目部署需要配置的环境信息(数据库驱动,数据库账号密码…

医疗金融法律大模型:从ChatDoctor到FinBERT/FinGPT/BloombergGPT、ChatLaw/LawGPT_zh

第一部分 各种医疗类ChatGPT:或中英文数据微调LLaMA、或中文数据微调ChatGLM 1.1 基于LLaMA微调的中英文版ChatDoctor 1.1.1 ChatDoctor:通过self-instruct技术提示API的数据和医患对话数据集微调LLaMA Github上有一个基于LLaMA模型的医疗微调模型&am…

zabbix (自定义监控内容-配置邮件报警-自动发现与自动注册)

目录 zabbix 客户端主机配置自定义监控内容设置邮件报警zabbix 自动发现与自动注册zabbix 自动发现(对于 agent2 是被动模式)//zabbix 自动发现(对于 agent2 是被动模式)zabbix 自动注册(对于 agent2 是主动模式&#…