插件化(二)插件化Activity的启动

大话插件化系列目录
插件化(一) 插件化思想与类加载
插件化(二) 插件化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点和思路

偷梁换柱.png

Activity------>AMS

查找源码的Hook点

Activity#startActivity 方法查看

Activity-AMS.png

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= 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 IActivityManagerSingleton =
            new Singleton() {
                @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#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 启动

Activity 启动.png

AMS----->ApplicationThread Hook Handler

ActivityThread------>Activity

ActvityThread流程.png

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

AMS.png
 // 获取 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");
            }
  1. hookHandler
截屏2020-11-29 23.30.12.png

API 26 H 类 从100 开始
API 28 H 类 从110 开始 生命周期从100~109 合并成了一个类 159

API28 startActivit.png

ClientTransaction == msg.obj ---- private List mActivityCallbacks;private List mActivityCallbacks; -- -- ClientTransactionItem的子类

private Intent mIntent; -- LaunchActivityItem 对象 -- private List 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();
                            }

你可能感兴趣的:(插件化(二)插件化Activity的启动)