【VirtualAPP 双开系列04】VirtualAPP 可扩展 AIDL 分析
目录:
- 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 分析相关推荐
- 【VirtualAPP 双开系列08】如何实现多开 - UID
目录: 1. Android UID 介绍 2. 多开基本原理 3. 常用的多开方案 4. VirtualAPP 如何实现多开 1. Android UID 介绍 Android 系统中修改了 Lin ...
- 【VirtualAPP 双开系列03】动态代理-hook系统服务(Java层)
目录: 1. Hook 简述 2. VirtualAPP Java Hook 类图 3. VirtualAPP Java Hook 实例 (ActivityManagerService) 1. Hoo ...
- 【VirtualAPP 双开系列02】进程管理
目录: 1. 运行 VirtualAPP,查看进程 2. VirtualAPP 分成四种类型的进程 3. 关于 Stub 4. 关于 ServiceManager 1. 运行 VirtualAPP,查 ...
- 【VirtualAPP 双开系列07】第三方 APP Service、Provider 加载分析
目录: 1. Service 加载分析 2. Provider 加载分析 1. Service 加载分析 2. Provider 加载分析
- dubbo源码分析系列(1)扩展机制的实现
1 系列目录 dubbo源码分析系列(1)扩展机制的实现 dubbo源码分析系列(2)服务的发布 dubbo源码分析系列(3)服务的引用 dubbo源码分析系列(4)dubbo通信设计 2 SPI扩展 ...
- Java 集合系列04之 fail-fast总结
转载自 Java 集合系列04之 fail-fast总结 概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内 ...
- 狂神学习系列04:MySQL+JDBC
狂神学习系列04:MySQL+JDBC 声明: MySQL是基于杜老师的课程所编写,JDBC是基于狂神的课程所编写,本人才疏学浅,内容仅作参考 文章目录 狂神学习系列04:MySQL+JDBC 1. ...
- 联想拯救者y7000(2020款)安装ubuntu18.04,无法扩展屏幕,WiFi无法使用问题
电脑配置: 拯救者y7000(2020款) 显卡:GTX1650 问题1:安装完之后扩展屏幕检测不到,WiFi模块没有. 解决方案:通过两天的折腾,筛选了很多教程,不幸的是ppa安装,手动安装,在so ...
- Dubbo系列(二)源码分析之SPI机制
Dubbo系列(二)源码分析之SPI机制 在阅读Dubbo源码时,常常看到 ExtensionLoader.getExtensionLoader(*.class).getAdaptiveExtensi ...
最新文章
- android写代码截屏微信,android 模仿微信头像裁剪
- 2020年,5种将死的编程语言
- RNA-Seq Transcriptome Profiling Identifies CRISPLD2 as a Glucocorticoid Responsive Gene that Modulat
- RAC安装时需要执行4个脚本及意义
- oracle查看执行最慢与查询次数最多的sql语句及其执行速度很慢的问题分析
- ios下获取所有实体/虚拟网卡的信息,并以此判断设备所处的网络状态
- lsof查看进程占用文件_lsof命令查看进程socket相关信息
- LeetCode 287. Find the Duplicate Number
- Docker : Docker安装Kibana报错 Unable to revive connection: http://localhost:9200 No living connections
- CCFollow和ActionCallFunc
- orb特征 稠密特征_特征点的基本概念和如何找到它们
- js Promise理解,同时请求多个接口等
- discuz论坛引入iframe
- 红外接收管硬件电路曲折的调试过程,错误的使用过程记录
- 昵图网源码php,【PHP】仿我图,千图,昵图网素材下载,素材销售平台最新宽屏商业版:含新版vip会员中心,全开源...
- 电阻转换温度值c语言,PT1000电阻值转化为温度值的计算公式
- matlab堆积式玫瑰图,用SAS实现堆积式南丁格尔玫瑰图Nightingale Rose Diagram (上)...
- PS实例之制作晶莹剔透气泡
- leetcode 16 -- 3Sum Closest
- 躲避雪糕刺客?通过爬虫爬取雪糕价格