目录
前言
对于泛型类型,Android源码中是很常见的。偶尔需要对泛型进行反射,因此,记录一下,方便自己查阅。
Android P,不同版本可能不同
正文
本文以hook一下ActivityManager.startActivity(),在startActivity()启动新的Activity时打印Intent中带的参数。
回顾
之前《》中介绍过startActivity()的分析。
Instrumentation.java
execStartActivity()
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { //略 //mActivityMonitors为null if (mActivityMonitors != null) { //略 } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); //调用的ActivityManagerService.startActivity() int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
上面有个比较重要的
int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
虽然最终是调用了ActivityManagerService.startActivity(),这部分之前我们是略过的。
我们看看ActivityManager。
ActivityManager.java
public static IActivityManager getService() { return IActivityManagerSingleton.get(); } private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { //通过ServiceManager获取了ActivityManagerService的IBinder final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };
也就是这里,通过Singleton创建了IActivityManagerSingleton。
Singleton.java
public abstract class Singleton<T> { private T mInstance; protected abstract T create(); public final T get() { synchronized (this) { if (mInstance == null) { mInstance = create(); } return mInstance; } } }
Singleton是个泛型。
这里是个泛型,也是唯一一个初始的地方,算是比较好hook的地方,也就是只需要替换mInstance即可。
HookAMS
本文主要以参考文中HookAMS例子基础上修改
IActivityManagerSingleton
先获取到IActivityManagerSingleton变量,这个是私有的静态变量。(若有疑惑,可看《》)
//加载ActivityManager类的Class Class activityManagerClass = Class.forName("android.app.ActivityManager"); //获取IActivityManagerSingleton的Field Field iActivityManagerSingletonField = activityManagerClass.getDeclaredField("IActivityManagerSingleton"); //private修饰的变量 iActivityManagerSingletonField.setAccessible(true); //获取IActivityManagerSingleton变量 //静态变量,针对类反射,参数传入null Object IActivityManagerSingleton = iActivityManagerSingletonField.get(null);
通过上面,就可以获取到IActivityManagerSingleton变量。
mInstance
从上面知道,Singleton是一个泛型。如果要获取的mInstance其实就是Singleton<IActivityManager>的变量。
//加载Singleton类型 Class singletonClass = Class.forName("android.util.Singleton"); //获取mInstance的Field Field mInstanceField = singletonClass.getDeclaredField("mInstance"); //mInstance是非静态私有变量 mInstanceField.setAccessible(true); //获取mInstance变量,传入IActivityManagerSingleton是要获取此对象的mInstance变量 Object mInstance = mInstanceField.get(IActivityManagerSingleton);
HookAMS完整代码
HookHandler
class HookHandler implements InvocationHandler { private final String TAG = "BiuA_" + getClass().getName(); private final Object mObject; public HookHandler(Object object) { mObject = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //拦截startActivity,并打印Intent中的参数 //IActivityManager中有很多方法 if (method.getName().equals("startActivity")) { for (Object obj : args) { Log.d(TAG, "invoke obj : " + obj); } } return method.invoke(mObject, args); } }
hook主要代码
try { //加载ActivityManager类的Class Class activityManagerClass = Class.forName("android.app.ActivityManager"); //获取IActivityManagerSingleton的Field Field iActivityManagerSingletonField = activityManagerClass.getDeclaredField("IActivityManagerSingleton"); //private修饰 iActivityManagerSingletonField.setAccessible(true); //获取IActivityManagerSingleton变量 //静态变量,针对类反射,参数传入null Object IActivityManagerSingleton = iActivityManagerSingletonField.get(null); //加载Singleton Class singletonClass = Class.forName("android.util.Singleton"); //获取mInstance的field Field mInstanceField = singletonClass.getDeclaredField("mInstance"); //private修饰 mInstanceField.setAccessible(true); //获取mInstance变量 //传入IActivityManagerSingleton,是要获取此对象的mInstance变量 Object mInstance = mInstanceField.get(IActivityManagerSingleton); //加载IActivityManager接口类(IActivityManager.aidl) //需要动态代理其的接口中的方法 Class mIActivityManagerClass = Class.forName("android.app.IActivityManager"); //动态代理 Object proxy = Proxy.newProxyInstance( //使用当前线程的类加载器 Thread.currentThread().getContextClassLoader(), //需要代理的接口 new Class[]{mIActivityManagerClass}, //创建InvocationHandler对象,这里HookHandler实现了 new HookHandler(mInstance)); //把Singleton的mInstance替换为proxy mInstanceField.set(IActivityManagerSingleton, proxy); } catch (Exception e) { throw new RuntimeException("Hook Failed", e); }
打印一下日志
invoke obj : android.app.ActivityThread$ApplicationThread@991d261 invoke obj : com.biumall.biutextview invoke obj : Intent { cmp=com.biumall.biutextview/.SecondActivity (has extras) } invoke obj : null invoke obj : android.os.BinderProxy@c598330 invoke obj : null invoke obj : -1 invoke obj : 0 invoke obj : null invoke obj : null
部分关于Proxy.newProxyInstance()可以看《
参考文章
《Android插件化开发指南-包建强》
《》
《
© 版权声明
看看