VirtualApp原理解析(1)–初始化及注入流程
VirtualApp是一款可以达到应用双开效果的开源项目。
源码地址:https://github.com/asLody/VirtualApp
这一系列简要分析其原理。
先来看下VirtualApp整体流程,包含启动双开应用Activity的过程。如下图:
VirtualApp的运行存在如下进程:
MainProcess即io.virtualapp:这是VirtualApp的宿主界面存在的进程。负责显示已安装目标应用,选择及启动需要双开的目标应用等。
ServiceProcess即io.virtualapp:x:后台服务进程,运行VirtualApp的后台重要服务。如:BinderProvider、DaemonService等。
ClientProcess即io.virtualapp:p*:目标应用运行进程,这个进程提供StubActivity/StubDialog/StubContentProvider子类负责启动目标应用对应的组件。
初始化及注入流程如下图所示:
1.VApp继承Application是应用程序入口,因为存在多进程所以VApp会调用多次,所以在VApp代码中存在对当前进程的判断逻辑。
- 在覆写函数attachBase()中直接调用VirtualCore.startUp()做初始化操作。
2.VirtualCore.startUp()中主要有以下几个步骤:
首先反射获取当前进程的ActivityThread对象保存,接着获取所在进程的unHookPackageManager。因为后面会对该PackageManager做hook所以这里先做备份。
获取InvocationStubManager单例引用,调用到InvocationStubManager.init()。
完成初始化之后调用InvocationStubManager.injectAll()执行对系统manager注入。
3.InvocationStubManager.init()函数的逻辑:
init函数内部又会调用到InvocationStubManager.injectInternal()该函数会根据当前进程类型执行不同初始化操作。这里假设是一个ServiceProcess或者ClientProcess去初始化ActivityManagerStub操作。
InvocationStubManager.injectInternal()只有两个操作,首先新建一个ActivityManagerStub对象,接着调用addInjector()将这个对象加入到map的mInjectors对象中。
那么在新建ActivityManagerStub对象时发生了什么?
在ActivityManagerStub构造函数中,首先新建了一个MethodInvocationStub对象,参数传入通过反射获取的AMN中IActivityManager的getDefault对象。接着调用MethodInvocationStub两个参数的构造函数,在这里重点来了,首先保存一个传入的getDefault对象,接着获取这个getDefault对应的Class对象所有的接口。这里的一切都是为了使用Proxy.newProxyInstance()构建一个IActivityManager动态代理对象mProxyInterface。
接着将上述步骤构建的MethodInvocationStub对象传入ActivityManagerStub父类MethodInvocationProxy的构造函数中。这里首先需要保存传入MethodInvocationStub对象,接着调用子类的ActivityManagerStub.onBindMethods(),在该函数中先去调用父类对应实现。在父类的onBindMethods()中获取自身的class对象,判断是否存在@Inject注解,读取其注解内部class对象构建对象后使用mInvocationStub.addMethodProxy()添加到MethodInvocationProxy中的一个map的Map