Android最强进程保活黑科技实现原理解密及方法

启动Service:

mRemote.transact(transactCode, mServiceData, null, 1);

在 native 层进行 binder 通信

在Java层做进程复活的工作,这个方式是比较低效的,最好的方式是在 native 层使用纯 C/C++来复活进程。方案有两个。

其一,维术大佬给出的方案是利用libbinder.so, 利用Android提供的C++接口,跟ActivityManagerService通信,以唤醒新进程。

  1. Java 层创建 Parcel (含 Intent),拿到 Parcel 对象的 mNativePtr(native peer),传到 Native 层。
  2. native 层直接把 mNativePtr 强转为结构体指针。
  3. fork 子进程,建立管道,准备传输 parcel 数据。
  4. 子进程读管道,拿到二进制流,重组为 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
├── arm64

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值