目录:

  • 1. 什么是 AIDL?
  • 2. 为什么要用 AIDL?
  • 3. VirtualAPP AIDL 使用
  • 4. IPC 总线(IPCBus)动态扩展
  • 5. 总结

1. 什么是 AIDL?

AIDL: Android Interface Definition Language, 即 Android 接口定义语言。

2. 为什么要用 AIDL?

Android 中每个应用都是独立的进程,拥有自己的虚拟机,虚拟地址,应用之间的内存不止不能互相访问,存在应用隔离,因此两个应用不能像面向对象语言一样直接进行接口的调用。两个进程之间的调用叫做 IPC(进程间通信)。Android 中进程之间的 IPC 调用有:管道、共享内存、消息队列、信号量、socket、binder,从性能、安全角度最终选择了 Binder.

3. VirtualAPP AIDL 使用

我们以获取已安装的应用列表为例。

3.1 AIDL

IAppManager.aidl:

package com.android.dockercore.server;import com.android.dockercore.remote.InstalledAppInfo;interface IAppManager {// ...List<InstalledAppInfo> getInstalledApps(int flags);// ...
}

InstallAppInfo.aidl:

package com.android.dockercore.remote;parcelable InstalledAppInfo;

3.2 Java

InstalledAppInfo 对应的 java 类:

public final class InstalledAppInfo implements Parcelable {public String packageName;public String apkPath;public String libPath;public boolean dependSystem;public int appId;public InstalledAppInfo(String packageName, String apkPath, String libPath, boolean dependSystem, boolean skipDexOpt, int appId) {this.packageName = packageName;this.apkPath = apkPath;this.libPath = libPath;this.dependSystem = dependSystem;this.appId = appId;}public File getOdexFile() {return VEnvironment.getOdexFile(packageName);}public ApplicationInfo getApplicationInfo(int userId) {return VPackageManager.get().getApplicationInfo(packageName, 0, userId);}public PackageInfo getPackageInfo(int userId) {return VPackageManager.get().getPackageInfo(packageName, 0, userId);}public int[] getInstalledUsers() {return DockerCore.get().getPackageInstalledUsers(packageName);}public boolean isLaunched(int userId) {return DockerCore.get().isPackageLaunched(userId, packageName);}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(this.packageName);dest.writeString(this.apkPath);dest.writeString(this.libPath);dest.writeByte(this.dependSystem ? (byte) 1 : (byte) 0);dest.writeInt(this.appId);}protected InstalledAppInfo(Parcel in) {this.packageName = in.readString();this.apkPath = in.readString();this.libPath = in.readString();this.dependSystem = in.readByte() != 0;this.appId = in.readInt();}public static final Creator<InstalledAppInfo> CREATOR = new Creator<InstalledAppInfo>() {@Overridepublic InstalledAppInfo createFromParcel(Parcel source) {return new InstalledAppInfo(source);}@Overridepublic InstalledAppInfo[] newArray(int size) {return new InstalledAppInfo[size];}};
}

再看看编译生成的 IAppManager java 类:

public interface IAppManager extends android.os.IInterface {/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.android.dockercore.server.IAppManager {private static final java.lang.String DESCRIPTOR = "com.android.dockercore.server.IAppManager";/** Construct the stub at attach it to the interface. */public Stub() {this.attachInterface(this, DESCRIPTOR);}/*** Cast an IBinder object into an com.android.dockercore.server.IAppManager interface,* generating a proxy if needed.*/public static com.android.dockercore.server.IAppManager asInterface(android.os.IBinder obj) {if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof com.android.dockercore.server.IAppManager))) {return ((com.android.dockercore.server.IAppManager) iin);}return new com.android.dockercore.server.IAppManager.Stub.Proxy(obj);}@Overridepublic android.os.IBinder asBinder() {return this;}@Overridepublic 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 TRANSACTION_getInstalledAppInfo: {data.enforceInterface(descriptor);java.lang.String _arg0;_arg0 = data.readString();int _arg1;_arg1 = data.readInt();com.android.dockercore.remote.InstalledAppInfo _result = this.getInstalledAppInfo(_arg0, _arg1);reply.writeNoException();if ((_result != null)) {reply.writeInt(1);_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);} else {reply.writeInt(0);}return true;}default: {return super.onTransact(code, data, reply, flags);}}}private static class Proxy implements com.android.dockercore.server.IAppManager {private android.os.IBinder mRemote;Proxy(android.os.IBinder remote) {mRemote = remote;}@Overridepublic android.os.IBinder asBinder() {return mRemote;}public java.lang.String getInterfaceDescriptor() {return DESCRIPTOR;}@Overridepublic com.android.dockercore.remote.InstalledAppInfo getInstalledAppInfo(java.lang.String pkg, int flags) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();com.android.dockercore.remote.InstalledAppInfo _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeString(pkg);_data.writeInt(flags);mRemote.transact(Stub.TRANSACTION_getInstalledAppInfo, _data, _reply, 0);_reply.readException();if ((0 != _reply.readInt())) {_result = com.android.dockercore.remote.InstalledAppInfo.CREATOR.createFromParcel(_reply);} else {_result = null;}} finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_getInstalledAppInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);}public com.android.dockercore.remote.InstalledAppInfo getInstalledAppInfo(java.lang.String pkg, int flags) throws android.os.RemoteException;
}

 

3.3 如何添加 IBinder

3.4 获取 IInterface 进行使用

4. IPC 总线(IPCBus)动态扩展

AIDL 虽然让跨进程通信变得很简单,但无法实现运行时,动态扩展功能。每次 AIDL 的接口变化,都需要重新编译。在 VirtualApp 里,通过 IPC 总线,实现了运行时动态的扩展能力。

AIDL 自动生成的 Stub 和 Stub.Proxy 的主要功能:

  • 生成 code,如TRANSACTION_getPid, TRANSACTION_getMyData,用于传输方法名的传输
  • 传输方法名 (即 code) 和方法参数,调用真正实现类对应的方法

通过 IPC 总线实现这两个能力后,就可以实现运行时增加通信能力,整体框架如下:

5. 总结

客户端要获取 IBinder 对象有两种方式:

  • 异步获取:通过绑定 Service 获取
  • 同步获取:通过 ContentProvider 获取

整体过程如下图所示:

参考:

https://handsomeliuyang.github.io/2020/08/09/%E7%BB%8F%E9%AA%8C%E6%80%BB%E7%BB%93/%E5%8F%8C%E5%BC%80%E7%B3%BB%E5%88%97%EF%BC%9AAIDL%E5%8E%9F%E7%90%86%E7%AE%80%E4%BB%8B%E5%8F%8A%E5%8A%A8%E6%80%81%E6%89%A9%E5%B1%95%E5%AE%9E%E7%8E%B0/

【VirtualAPP 双开系列04】VirtualAPP 可扩展 AIDL 分析相关推荐

  1. 【VirtualAPP 双开系列08】如何实现多开 - UID

    目录: 1. Android UID 介绍 2. 多开基本原理 3. 常用的多开方案 4. VirtualAPP 如何实现多开 1. Android UID 介绍 Android 系统中修改了 Lin ...

  2. 【VirtualAPP 双开系列03】动态代理-hook系统服务(Java层)

    目录: 1. Hook 简述 2. VirtualAPP Java Hook 类图 3. VirtualAPP Java Hook 实例 (ActivityManagerService) 1. Hoo ...

  3. 【VirtualAPP 双开系列02】进程管理

    目录: 1. 运行 VirtualAPP,查看进程 2. VirtualAPP 分成四种类型的进程 3. 关于 Stub 4. 关于 ServiceManager 1. 运行 VirtualAPP,查 ...

  4. 【VirtualAPP 双开系列07】第三方 APP Service、Provider 加载分析

    目录: 1. Service 加载分析 2. Provider 加载分析 1. Service 加载分析 2. Provider 加载分析

  5. dubbo源码分析系列(1)扩展机制的实现

    1 系列目录 dubbo源码分析系列(1)扩展机制的实现 dubbo源码分析系列(2)服务的发布 dubbo源码分析系列(3)服务的引用 dubbo源码分析系列(4)dubbo通信设计 2 SPI扩展 ...

  6. Java 集合系列04之 fail-fast总结

    转载自   Java 集合系列04之 fail-fast总结 概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内 ...

  7. 狂神学习系列04:MySQL+JDBC

    狂神学习系列04:MySQL+JDBC 声明: MySQL是基于杜老师的课程所编写,JDBC是基于狂神的课程所编写,本人才疏学浅,内容仅作参考 文章目录 狂神学习系列04:MySQL+JDBC 1. ...

  8. 联想拯救者y7000(2020款)安装ubuntu18.04,无法扩展屏幕,WiFi无法使用问题

    电脑配置: 拯救者y7000(2020款) 显卡:GTX1650 问题1:安装完之后扩展屏幕检测不到,WiFi模块没有. 解决方案:通过两天的折腾,筛选了很多教程,不幸的是ppa安装,手动安装,在so ...

  9. Dubbo系列(二)源码分析之SPI机制

    Dubbo系列(二)源码分析之SPI机制 在阅读Dubbo源码时,常常看到 ExtensionLoader.getExtensionLoader(*.class).getAdaptiveExtensi ...

最新文章

  1. android写代码截屏微信,android 模仿微信头像裁剪
  2. 2020年,5种将死的编程语言
  3. RNA-Seq Transcriptome Profiling Identifies CRISPLD2 as a Glucocorticoid Responsive Gene that Modulat
  4. RAC安装时需要执行4个脚本及意义
  5. oracle查看执行最慢与查询次数最多的sql语句及其执行速度很慢的问题分析
  6. ios下获取所有实体/虚拟网卡的信息,并以此判断设备所处的网络状态
  7. lsof查看进程占用文件_lsof命令查看进程socket相关信息
  8. LeetCode 287. Find the Duplicate Number
  9. Docker : Docker安装Kibana报错 Unable to revive connection: http://localhost:9200 No living connections
  10. CCFollow和ActionCallFunc
  11. orb特征 稠密特征_特征点的基本概念和如何找到它们
  12. js Promise理解,同时请求多个接口等
  13. discuz论坛引入iframe
  14. 红外接收管硬件电路曲折的调试过程,错误的使用过程记录
  15. 昵图网源码php,【PHP】仿我图,千图,昵图网素材下载,素材销售平台最新宽屏商业版:含新版vip会员中心,全开源...
  16. 电阻转换温度值c语言,PT1000电阻值转化为温度值的计算公式
  17. matlab堆积式玫瑰图,用SAS实现堆积式南丁格尔玫瑰图Nightingale Rose Diagram (上)...
  18. PS实例之制作晶莹剔透气泡
  19. leetcode 16 -- 3Sum Closest
  20. 躲避雪糕刺客?通过爬虫爬取雪糕价格

热门文章

  1. ls-gl安装ssh
  2. Android Camera 开发你该知道的秘密㊙️-新手入门必备
  3. 2021年上半年软件设计师上午真题及答案解析(六)
  4. 冰火两重天版格斗场(热血格斗场+冷血格斗场)
  5. 码农吃饭的家伙电池充不了电了-拯救ThinkPadT470电池
  6. new placement
  7. jfreechart实现动态图表
  8. SpringMVC 核心技术帮助文档
  9. Python 绘制散点密度图
  10. 腾讯云服务器标准型SA1和SA2区别_腾讯云AMD服务器两款机型哪个更好