VirtualApp(以下简称VA)是一个开源的Android app虚拟化引擎,它提供了一个虚拟空间,允许其他应用运行在这个虚拟空间中,实现应用多开(可重复安装)。
在VA中,host应用(VA自身)和client应用(通过VA安装的应用)具有相同的uid。
在运行时,一般会包含三个进程:
- io.virtualapp,主进程,负责VA的用户界面及应用管理;
- io.virtualapp:x,服务进程,负责系统服务的代理;
- io.virtual:pXXX,用于运行client应用的进程,应用启动后,进程名更新为应用包名。
用ps命令看一下:
u0_a123 16545 256 1056344 84524 ffffffff 00000000 S io.virtualapp
u0_a123 16607 256 909252 36140 ffffffff 00000000 S io.virtualapp:x
u0_a123 16674 256 914872 40004 ffffffff 00000000 S com.example.test
下面从源码分析一下VA启动与运行的整个过程:
VA的Application为VApp,包路径为io.virtualapp,是一个继承自MultiDexApplication的Application。这个类重写了attachBaseContext()
方法,程序启动后首先运行该方法,再调用oncreate()
方法。先看一下这个attachBaseContext方法做了什么:
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
mPreferences = base.getSharedPreferences("va", Context.MODE_MULTI_PROCESS);
VASettings.ENABLE_IO_REDIRECT = true;
VASettings.ENABLE_INNER_SHORTCUT = false;
try {
VirtualCore.get().startup(base);
} catch (Throwable e) {
e.printStackTrace();
}
}
除了设置一些属性,主要有这么一句:VirtualCore.get().startup(base);
VirtualCore是定义在包com.lody.virtual.client.core中的一个类,get()
首先返回一个重点内容静态的VirtualCore对象,然后调用该对象的startup()
方法进行一些初始化操作,看下这个方法的代码:
public void startup(Context context) throws Throwable {
if (!isStartUp) {
// step 1
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("VirtualCore.startup() must called in main thread.");
}
VASettings.STUB_CP_AUTHORITY = context.getPackageName() + "." + VASettings.STUB_DEF_AUTHORITY;
ServiceManagerNative.SERVICE_CP_AUTH = context.getPackageName() + "." + ServiceManagerNative.SERVICE_DEF_AUTH;
// step 2
this.context = context;
mainThread = ActivityThread.currentActivityThread.call();
unHookPackageManager = context.getPackageManager();
hostPkgInfo = unHookPackageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_PROVIDERS);
IPCBus.initialize(new IServerCache() {
@Override
public void join(String serverName, IBinder binder) {
ServiceCache.addService(serverName, binder);
}
@Override
public IBinder query(String serverName) {