1、
2、
前面介绍了两个库AndroidPerformanceMonitor和ANR WatchDog,这两个是自动化卡顿和ANR的监测方案。有了自动化方案,为什么还需要对卡顿进行单点问题的监控呢?这是因为自动卡顿监测方案并不能满足所有场景的要求。比如有很多的msg要执行,但是每个msg的执行时间都不到卡顿的阈值,那么自动化卡顿方案不能自动化检测到卡顿,但是对于用户来说,却觉得该应用有些卡顿。
如果要体系化解决方案,那么需要在项目上线之前尽可能早地暴漏问题。
主要需要关注的是主线程IPC和DB操作等。
主线程IPC其实是一个很耗时的操作,但是在实际开发过程中,对IPC没有足够的重视,经常在主线程中做频繁的IPC操作及频繁的调用,这种卡顿其实并不能到卡顿的阈值。
3、
IPC调用类型:比如PackageManager的调用和Telephone Manager的调用,这就属于不同的调用类型。
4、
5、
6、
7、
哪些操作是一个IPC的操作?比如说通过packageManager拿到应用的信息,比如说获取到deviceid这样的一些信息,以及AMS等等,这些其实都是有一个IPC的操作。这些操作其实都有一个固定的调用方式,不管通过哪种调用类型,最终都会通过一个类,也就是anddroid.os.BinderProxy。
每个IPC操作,最终都会调用到BinderProxy里面。
然后它会调用一个方法,transact()
在ARTHook种,第一个参数由于类没有办法直接获取到,所以使用反射的方式进行调用,需要hook的是transact方法,同时还需传入这个具体方法的参数信息,然后传入一个message callback。在beforeHookedMethod()方法里可以打印具体的调用栈信息,就可以知道这次的IPC调用是从哪里调用过来的。
try {
DexposedBridge.findAndHookMethod(Class.forName("android.os.BinderProxy"), "transact",
int.class, Parcel.class, Parcel.class, int.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
LogUtils.i( "BinderProxy beforeHookedMethod " + param.thisObject.getClass().getSimpleName()
+ "\n" + Log.getStackTraceString(new Throwable()));
super.beforeHookedMethod(param);
}
});
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
运行后打印出所有IPC的调用堆栈信息
如在PerformanceApp的153行调用了initStrictMode()这样一个方法,它里面呢会具体调用到ServiceManager.getService()这个方法。这也是一个ipc的操作,这个ipc的操作就被我们捕获到了。
通过这种方式可以很容易得到这个应用中的所有ipc操作。可以获取到ipc调用的类型以及调用类型、耗用次数、调用的堆栈等等一些信息。拿到这些信息后就可以具体地分析。因为有具体的堆栈信息,就可以找到具体的同学进行相应的堆栈信息的确认以及修改。
8、
9、