Binder跨进程通讯机制以及在PMS签名获取中的应用
Binder跨进程通讯
Binder跨进程通讯需要四部分参与工作:Client端,Server端,ServiceManager和Binder驱动,整体工作流程如下。
- Server端创建Binder本地对象,然后通过Binder驱动向ServiceManager进程中注册添加服务。
- Client端通过Binder驱动向ServiceManager进程中查询并请求服务,然后Binder驱动会返回一个BinderProxy代理对象。
- 数据传递:Client端通过BinderProxy代理对象向binder驱动copy序列化数据,然后binder驱动自动进行BinderProxy和Binder本地对象的转换,将传递的序列化数据map映射到Service端。
- RPC远程过程调用:Client端通过BinderProxy代理对象向binder驱动copy序列化数据(传递需要调用函数的flag和参数),然后binder驱动自动进行BinderProxy和Binder本地对象的转换,将传递的序列化数据map映射到Service端并调用对应的函数。

PMS签名获取过程中的Binder通讯过程
systeam_server进程中的PackageManagerService就是Binder通讯中的Server端,而获取签名信息的APP进程就是Binder通讯中的Client端。
PackageManagerService在初始化的时候会调用ServiceManager.addService("package", m)向ServiceManager进程中添加一个服务,服务对应的Binder本地对象就是PackageManagerService

APP进程中一般通过getApplicationContext().getPackageManager().getPackageInfo(packagename, PackageManager.GET_SIGNATURES),实际是通过Context类对象获取到ApplicationPackageManager(继承PackageManager)类对象,而ApplicationPackageManager类中的mPM成员是一个IPackageManager.Stub.Proxy类对象,是Server端PackageManagerService的BinderProxy代理对象的封装类。

ApplicationPackageManager类中的mPM是通过调用android.app.ActivityThread的getPackageManager获取的,getPackageManager通过调用ServiceManager.getService("package")从ServerManager进程中查询并利用Binder驱动返回一个BinderProxy代理对象。

进一步调用asInterface将BinderProxy代理对象封装成android.content.pm.IPackageManager.Stub.Proxy对象。

Stub是com.android.server.pm.IPackageManager抽象内部类,继承自android.os.Binder类,实现了com.android.server.pm.IPackageManager接口

Proxy是Stub的内部类,实现了com.android.server.pm.IPackageManager接口。其包含了private android.os.IBinder mRemote , 即Binder驱动返回的BinderProxy代理对象。

当APP进程调用getApplicationContext().getPackageManager().getPackageInfo(packagename, PackageManager.GET_SIGNATURES)的时候,ApplicationPackageManager.getPackageInfo()的内部实际是直接调用mPM成员的getPackageInfo函数,而mPM成员的类型是com.android.server.pm.IPackageManager.Stub.Proxy,所以调用的就是Proxy类的getPackageInfo函数。此函数会将数据进行序列化为Parcel类型后保存在_data中,并设置code为TRANSACTION_getPackageInfo然后调用mRemote成员,也就是BinderPorxy代理对象的transact函数,最终transact函数会将序列化后的数据copy到binder驱动中,binder驱动再将数据映射到PackageManagerService即Server进程中。

binder驱动将数据映射完后会调用PackageManagerService的onTransact函数,PackageManagerService类继承IPackageManager.Stub,onTransact函数也在com.android.server.pm.IPackageManager.Stub中实现。onTransact函数会判断Client端调用BinderProxy代理对象的transact函数时传入的code进行分类处理,如果是TRANSACTION_getPackageInfo说明是调用getPackageInfo。其会将_data中的数据取出来并调用PackageManagerService的getPackageInfo的函数,将返回值写入reply中

最后onTransact调用super.onTransact返回给Binder驱动,驱动唤醒挂起的Client进程(获取签名的APP进程)里面的线程并将结果返回。也就是唤醒Proxy类的getPackageInfo函数调用BinderPorxy代理对象的transact函数位置。

整个PMS的Binder通讯架构如下图所示

PMS中Binder的通讯流程如下图所示
- Client最终会通过
BinderProxy代理对象的transcat函数向Server发送数据 - Server接收到数据后
onTranscat函数会被调用,然后针对不同的调用做出响应 - 最终Server将响应结果返回给Client,
transcat调用处被唤醒继续执行

IPC获取APK签名
根据上面的分析应用程序获取签名其实就是向与PackageManagerService服务端进行IPC通信,所以可以参考com.android.server.pm.IPackageManager.Stub.Proxy类的getPackageInfo函数,获取到BinderProxy代理对象后调用transact函数获取PackageInfo数据。其中获取BinderProxy代理对象可以利用ActivityThread.getPackageManager从ServerManager中查询获取的方式获取,也可以通过反射得到android.content.pm.IPackageManager$Stub$Proxy类中的mRemote成员(BinderProxy代理对象),但是这种需要突破SDK API限制。
public PackageInfo my_getPackageInfo(){
PackageInfo packageInfo = null;
try {
//通过反射获取android.content.pm.IPackageManager$Stub$Proxy类中的mRemote成员(BinderProxy代理对象),需要突破SDK API限制
/*
PackageManager packageManager = getBaseContext().getPackageManager();
Class ApplicationPackageManagerClass = getClassLoader().loadClass("android.app.ApplicationPackageManager");
Field mPMField = ApplicationPackageManagerClass.getDeclaredField("mPM");
mPMField.setAccessible(true);
Object mPM_object = mPMField.get(packageManager);
Class ProxyClass = getClassLoader().loadClass("android.content.pm.IPackageManager$Stub$Proxy");
@SuppressLint("SoonBlockedPrivateApi") Field mRemoteField = ProxyClass.getDeclaredField("mRemote");
mRemoteField.setAccessible(true);
IBinder mRemote = (IBinder) mRemoteField.get(mPM_object);
*/
//获取BinderProxy代理对象mRemote
Class ServiceManagerClass = this.getClassLoader().loadClass("android.os.ServiceManager");
//public static IBinder getService(String name)
Method getServiceMethod = ServiceManagerClass.getDeclaredMethod("getService", String.class);
//ServiceManager.getService("package");
IBinder mRemote = (IBinder) getServiceMethod.invoke(null, "package");
//序列化数据,写入_data
Parcel _data = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
_data = Parcel.obtain(mRemote);
}
else{
_data = Parcel.obtain();
}
Parcel _reply = Parcel.obtain();
_data.writeInterfaceToken("android.content.pm.IPackageManager");
_data.writeString(getPackageName());
_data.writeLong(PackageManager.GET_SIGNATURES);
_data.writeInt(android.os.Process.myUid());
//调用transact发送数据到PackageManagerService(Server端)
mRemote.transact(TRANSACTION_getPackageInfo, _data, _reply, 0);
//读取_reply中返回的数据
_reply.readException();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
packageInfo = _reply.readTypedObject(PackageInfo.CREATOR);
}
_data.recycle();
_reply.recycle();
} catch (Throwable e) {
Log.e("reverccqin", "IPC_TEST_getPackageInfo error "+e);
}
return packageInfo;
}

浙公网安备 33010602011771号