1.IActivityManager
1启动Activity执行到Instrumentation的execStartActivity方法时,Android 26以下版本的代码为:
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManagerNative.getDefault()
.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;
}
Android 26以上版本的代码为:
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
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;
}
在Hook进行Intent替换时,获取IActivityManager的方式不同,Android 26以下版本如下:
Class mActivityManagerClass = Class.forName("android.app.ActivityManagerNative");
Method getDefaultMethod = mActivityManagerClass.getDeclaredMethod("getDefault");
getDefaultMethod.setAccessible(true);
mIActivityManager = getDefaultMethod.invoke(null);
Android 26以上版本如下:
Class mActivityManagerClass = Class.forName("android.app.ActivityManager");
mIActivityManager = mActivityManagerClass.getMethod("getService").invoke(null);
Field mIActivityManagerSingletonField = mActivityManagerClass.getDeclaredField("IActivityManagerSingleton");
mIActivityManagerSingletonField.setAccessible(true);
mIActivityManagerSingleton = mIActivityManagerSingletonField.get(null);
2. Handler H
在Android 28版本中,ActivityThread的内部类Handler H去掉了以下消息类型:
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
当启动Activity时,会跳转到handleMessage方法的以下代码:
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction)msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
transaction.recycle();
}
break;
在以上代码执行前,需要把真实的Intent注入其中,替换掉绕过AMS检查的代理Intent。以上代码首先获得了ClientTransaction对象,ClientTransaction中有一个成员变量List mActivityCallbacks,ClientTransactionItem的其中一个子类是LaunchActivityItem,LaunchActivityItem中的成员变量Intent就是需要替换的Intent。
新建一个MyHandler继承android.os.Handler,使用MyHandler替换ActivityThread中的H,在handlerMessage中,首先获取mActivityCallbacks。
Object mClientTransaction = msg.obj;
Field mactivityCallbacks = mClientTransaction.getClass().getDeclaredField("mActivityCallbacks");
mactivityCallbacks.setAccessible(true);
List mActivityCallbacks = (List)mactivityCallbacks.get(mClientTransaction);
if (mActivityCallbacks.size() == 0) {
return false;
}
获取LaunchActivityItem:
Class mLaunchActivityItemClass = Class.forName("android.app.servertransaction.LaunchActivityItem");
Object mLaunchActivityItem = mActivityCallbacks.get(0);
if (mLaunchActivityItemClass.isInstance(mLaunchActivityItem) == false) {
return false;
}
Field mIntentField = mLaunchActivityItemClass.getDeclaredField("mIntent");
mIntentField.setAccessible(true);
Intent proxyIntent = (Intent) mIntentField.get(mLaunchActivityItem);
替换Intent:
Intent targetIntent = proxyIntent.getParcelableExtra("targetIntent");
if (targetIntent != null) {
mIntentField.setAccessible(true);
mIntentField.set(mLaunchActivityItem, targetIntent);
}