启动Service:
mRemote.transact(transactCode, mServiceData, null, 1);
在 native 层进行 binder 通信
在Java层做进程复活的工作,这个方式是比较低效的,最好的方式是在 native 层使用纯 C/C++来复活进程。方案有两个。
其一,维术大佬给出的方案是利用libbinder.so, 利用Android提供的C++接口,跟ActivityManagerService通信,以唤醒新进程。
- Java 层创建 Parcel (含 Intent),拿到 Parcel 对象的 mNativePtr(native peer),传到 Native 层。
- native 层直接把 mNativePtr 强转为结构体指针。
- fork 子进程,建立管道,准备传输 parcel 数据。
- 子进程读管道,拿到二进制流,重组为 parcel。
其二,Gityuan大佬则认为使用 ioctl 直接给 binder 驱动发送数据以唤醒进程,才是更高效的做法。然而,这个方法,大佬们并没有提供思路。
那么今天,我们就来实现这两种在 native 层进行 Binder 调用的骚操作。
方式一 利用 libbinder.so 与 ActivityManagerService 通信
上面在Java层复活进程一节中,是向ActivityManagerService发送特定的封装了Intent的Parcel包来实现唤醒进程。而在native层,没有Intent这个类。所以就需要在Java层创建好Intent,然后写到Parcel里,再传到Native层。
Parcel mServiceData = Parcel.obtain();
mServiceData.writeInterfaceToken(“android.app.IActivityManager”);
mServiceData.writeStrongBinder(null);
mServiceData.writeInt(1);
intent.writeToParcel(mServiceData, 0);
mServiceData.writeString(null); // resolvedType
mServiceData.writeInt(0);
mServiceData.writeString(context.getPackageName()); // callingPackage
mServiceData.writeInt(0);
查看[Parcel的源码](()可以看到,Parcel类有一个mNativePtr变量:
private long mNativePtr; // used by native code
// android4.4 mNativePtr是int类型
可以通过反射得到这个变量:
private static long getNativePtr(Parcel parcel) {
try {
Field ptrField = parcel.getClass().getDeclaredField(“mNativePtr”);
ptrField.setAccessible(true);
return (long) ptrField.get(parcel);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
这个变量对应了C++中[Parcel类](()的地址,因此可以强转得到Parcel指针:
Parcel *parcel = (Parcel *) parcel_ptr;
然而,NDK中并没有提供binder这个模块,我们只能从Android源码中扒到binder相关的源码,再编译出libbinder.so。腾讯TIM应该就是魔改了binder相关的源码。
提取libbinder.so
为了避免libbinder的版本兼容问题,这里我们可以采用一个更简单的方式,拿到binder相关的头文件,再从系统中拿到libbinder.so,当然binder模块还依赖了其它的几个so,要一起拿到,不然编译的时候会报链接错误。
adb pull /system/lib/libbinder.so ./
adb pull /system/lib/libcutils.so ./
adb pull /system/lib/libc.so ./
adb pull /system/lib/libutils.so ./
复制代码
如果需要不同SDK版本,不同架构的系统so库,可以在 [Google Factory Images](() 网页里找到适合的版本,下载相应的固件,然后解包system.img(需要在windows或linux中操作),提取出目标so。
binder_libs
├── ar