大话插件化系列目录
插件化(一) 插件化思想与类加载
插件化(二) 插件化Activity的启动
插件化(三) 插件资源加载
启动Activity
我们启动Activity的方式
正常一个进程app
startActivity(new Intent(MainActivity.this,ProxyAcitvity.class));
启动其他进程
Intent intent = new Intent();
intent.setComponent(new ComponentName("top.zcwfeng.plugin",
"top.zcwfeng.plugin.MainActivity"));
但是我们启动的时候都需要进行注册。在AMS(ActivityManagerService)中进行注册。
APP----AMS----APP
所以我们用到的技术局势Hook: 通过 反射 和 动态代理实现。
如何查找Hook点和思路
Activity------>AMS
查找源码的Hook点
Activity#startActivity 方法查看
Activity#startActivityForResult 三个参数方法
instrumentation 这个位置是个hook点,但是我们继续看看有没有更轻松
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
继续进入Instrumentation#execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
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;
}
找到 静态方法,并且有Intent相关的
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
这里让我们容易想到,可以用动态代理去修改Intent。反射对于静态方法比较容易。所以这里是突破口。
接口+实现,比较容易想到
source 26——8.0源码中
/**
* @hide
*/
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
反射拿到IActivityManager 获取 Singleton 对象
ActivityManager.getService()---静态方法,后去返回---IActivityManager
IActivityManger 对象---IActivityManagerSingleton get 获取---Singleton<T>#private T mInstance
我们的proxyInstance 替换系统的 mInstance 对象
mInstance 非静态的 -- Singleton的对象 ---- IActivityManagerSingleton 是静态的
public static void hookAMS() {
try {
// 获取 Singleton 对象
Class<?> clazz = Class.forName("android.app.ActivityManager");
Field singletonField = clazz.getDeclaredField("IActivityManagerSingleton");
singletonField.setAccessible(true);
Object singleton = singletonField.get(null);
// 获取 IActivityManager 对象
Class<?> singletonClass = Class.forName("android.util.Singleton");
Field mInstanceField = singletonClass.getDeclaredField("mInstance");
mInstanceField.setAccessible(true);
Object mInstance = mInstanceField.get(singleton);
Class<?> iActivityManagerClass = Class.forName("android.app.IActivityManager");
Object proxyInstance = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{iActivityManagerClass}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//TODO Intent 的修改
//TODO Intent 的修改---进行过滤
if ("startActivity".equals(method.getName())) {
int index = -1;
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Intent) {
index = i;
break;
}
}
Intent intent = (Intent) args[index];
Intent proxyIntent = new Intent();
proxyIntent.setClassName("top.zcwfeng.zcwplugin",
"top.zcwfeng.zcwplugin.ProxyActivity");
intent.putExtra(TARGET_INTENT, intent);
args[index] = proxyIntent;
}
//iActivityManager 对象
return method.invoke(mInstance,args);
}
});
// TODO: 替换
//proxyInstance.startActivity()
// ActivityManager.getService() 替换成ProxyActity Instance
mInstanceField.set(singleton, proxyInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
Activity 启动
AMS----->ApplicationThread
Hook Handler
ActivityThread------>Activity
ActivityThread#scheduleLaunchActivity----->sendMessage--->H
所以我们要Hook Handler
public static final int LAUNCH_ACTIVITY = 100;
我们的目标还是找Intent 先关方便替换的地方
继续搜索
ActvityThread#handleLaunchActivity-->performLaunchActivity
-----> r.intent.getComponent();
找到 Intent的方便替换的地方 --- 在这个类 ActivityClientRecord 里面 --- Intent 是非静态 -- 获取 ActivityClientRecord 对象(关键点)
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
看到这个,所以 r ---- 相当与msg.obj
源码中Handler 对象H 是 final H mH = new H();
因此我们需要到Handler#handlerMessage-------->
Handler 源码
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
调用handlerMessage 之前,我们会执行mCallback
所以我们可以借助mCallback
mH 创建没有构造赋值过,所以 系统的mCallback == null
思路:
创建 mCallback 替换系统的 -- 从而拿到 msg --- msg.obj -- intent
想要拿到Handler mCallBack 因为不是静态,我们就要拿到Handler,handler就是H类,mH 不是静态,我们就需要ActivityThread 找到
private static volatile ActivityThread sCurrentActivityThread;
静态的反射比较方便拿到。
hookHandler
public static void hookHandler() {
// 拿到handler对象 mh,非静态,拿到ActivityThread是静态的
try {
Class<?> clazz = Class.forName("android.app.ActiityThread");
//获取 ActivityThread 对象
Field activityThreadField = clazz.getDeclaredField("sCurrentActivityThread");
activityThreadField.setAccessible(true);
Object activityThread = activityThreadField.get(null);
//获取 mh 对象
Field mHField = clazz.getDeclaredField("mH");
mHField.setAccessible(true);
Handler mH = (Handler) mHField.get(activityThread);
Field callbackField = Handler.class.getDeclaredField("mCallback");
callbackField.setAccessible(true);
// 创建callback
Handler.Callback callback = new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
// 通过msg 拿到 Intent 换回 插件执行的Intent
switch (msg.what) {
case 100:
try {
Field intentField = msg.obj.getClass().getDeclaredField("intent");
intentField.setAccessible(true);
// 启动代理Intent
Intent proxyIntent = (Intent) intentField.get(msg.obj);
// 启动插件Intent
Intent intent = proxyIntent.getParcelableExtra(TARGET_INTENT);
if (intent != null) {
intentField.set(msg.obj, intent);
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
// 必须 return false 保证向下执行handlerMessage
return false;
}
};
// 替换系统callback
callbackField.set(mH, callback);
} catch (Exception e) {
e.printStackTrace();
}
}
适配(上面用的源代码是8.0 上的源码,所以我们需要适配)
适配点:
1.hookAMS
Instrumentation.java ActivityManager.java
// 获取 Singleton 对象
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // 小于8.0
Class<?> clazz = Class.forName("android.app.ActivityManagerNative");
singletonField = clazz.getDeclaredField("gDefault");
} else {
Class<?> clazz = Class.forName("android.app.ActivityManager");
singletonField = clazz.getDeclaredField("IActivityManagerSingleton");
}
- hookHandler
API 26 H 类 从100 开始
API 28 H 类 从110 开始 生命周期从100~109 合并成了一个类 159
ClientTransaction == msg.obj ---- private List<ClientTransactionItem> mActivityCallbacks;private List<ClientTransactionItem> mActivityCallbacks; -- -- ClientTransactionItem的子类
private Intent mIntent; -- LaunchActivityItem 对象 -- private List<ClientTransactionItem> mActivityCallbacks;
-- ClientTransaction == msg.obj
try {
// 获取 mActivityCallbacks 对象
Field mActivityCallbacksField = msg.obj.getClass()
.getDeclaredField("mActivityCallbacks");
mActivityCallbacksField.setAccessible(true);
List mActivityCallbacks = (List) mActivityCallbacksField.get(msg.obj);
for (int i = 0; i < mActivityCallbacks.size(); i++) {
if (mActivityCallbacks.get(i).getClass().getName()
.equals("android.app.servertransaction.LaunchActivityItem")) {
Object launchActivityItem = mActivityCallbacks.get(i);
// 获取启动代理的 Intent
Field mIntentField = launchActivityItem.getClass()
.getDeclaredField("mIntent");
mIntentField.setAccessible(true);
Intent proxyIntent = (Intent) mIntentField.get(launchActivityItem);
// 目标 intent 替换 proxyIntent
Intent intent = proxyIntent.getParcelableExtra(TARGET_INTENT);
if (intent != null) {
mIntentField.set(launchActivityItem, intent);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}