attachBaseContext
@Override
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);
public void startup(Context context) throws Throwable {
if (!isStartUp) {
......
detectProcessType();
InvocationStubManager invocationStubManager = InvocationStubManager.getInstance();
invocationStubManager.init();
invocationStubManager.injectAll();
ContextFixer.fixContext(context);
isStartUp = true;
......
}
}
这里最主要的是实例化了invocationStubManager ,并开启注入(injectAll),
public void init() throws Throwable {
if (isInit()) {
throw new IllegalStateException("InvocationStubManager Has been initialized.");
}
injectInternal();
sInit = true;
}
private void injectInternal() throws Throwable {
if (VirtualCore.get().isMainProcess()) {
return;
}
......
}
由于当前我们是主进程,所以这里注入是啥也没干
SplashActivity
) protected void onCreate(Bundle savedInstanceState) {
@SuppressWarnings("unused")
boolean enterGuide = !Once.beenDone(Once.THIS_APP_INSTALL, VCommends.TAG_NEW_VERSION);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
VUiKit.defer().when(() -> {
if (!Once.beenDone("collect_flurry")) {
FlurryROMCollector.startCollect();
Once.markDone("collect_flurry");
}
long time = System.currentTimeMillis();
doActionInThread();
time = System.currentTimeMillis() - time;
long delta = 3000L - time;
if (delta > 0) {
VUiKit.sleep(delta);
}
}).done((res) -> {
HomeActivity.goHome(this);
finish();
});
}
private void doActionInThread() {
if (!VirtualCore.get().isEngineLaunched()) {
VirtualCore.get().waitForEngine();
}
}
在这里异步执行了doActionInThread,也就是执行了waitForEngine
,这一步很重要,在这里会开启另一个进程
public void waitForEngine() {
ServiceManagerNative.ensureServerStarted();
}
ServiceManagerNative.java
public static String SERVICE_CP_AUTH = "virtual.service.BinderProvider";
......
public static void ensureServerStarted() {
new ProviderCall.Builder(VirtualCore.get().getContext(), SERVICE_CP_AUTH).methodName("ensure_created").call();
}
ProviderCall.java
public static Bundle call(String authority, Context context, String method, String arg, Bundle bundle) {
Uri uri = Uri.parse("content://" + authority);
return ContentProviderCompat.call(context, uri, method, arg, bundle);
}
最终会构造出一个uri: virtual.service.BinderProvider
, 并启动这个Provider
ContentProviderCompat.java
public static Bundle call(Context context, Uri uri, String method, String arg, Bundle extras) {
if (VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return context.getContentResolver().call(uri, method, arg, extras);
}
ContentProviderClient client = crazyAcquireContentProvider(context, uri);
Bundle res = null;
try {
res = client.call(method, arg, extras);
} catch (RemoteException e) {
e.printStackTrace();
} finally {
releaseQuietly(client);
}
return res;
}
......
private static ContentProviderClient acquireContentProviderClient(Context context, Uri uri) {
if (VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
return context.getContentResolver().acquireUnstableContentProviderClient(uri);
}
return context.getContentResolver().acquireContentProviderClient(uri);
}
也就是最终使用context.getContentResolver().acquireContentProviderClient
获得一个client引用,并执行他的client.call(method, arg, extras);
,经上面分析method的值为ensure_created
,
这里的目的就是为了唤醒这个BinderProvider
查看它在AndroidManifest.xml
中的配置
<provider
android:name="com.lody.virtual.server.BinderProvider"
android:authorities="${applicationId}.virtual.service.BinderProvider"
android:exported="false"
android:process="@string/engine_process_name" />
<string name="engine_process_name">:x</string>
那么它是存在另一个进程中的,那么根据命名规则,该进程名会是io.virtualapp:x
主进程
io.virtualapp
服务进程
io.virtualapp:x
由于provider的启动,那么流程又会走到VApp中,在这个进程中走attachBaseContext
的VirtualCore.get().startup(base);
然后同样的走
InvocationStubManager invocationStubManager = InvocationStubManager.getInstance();
invocationStubManager.init();
invocationStubManager.injectAll();
InvocationStubManager.java
private void injectInternal() throws Throwable {
....
if (VirtualCore.get().isServerProcess()) {
addInjector(new ActivityManagerStub());
addInjector(new PackageManagerStub());
return;
....
}
void injectAll() throws Throwable {
for (IInjector injector : mInjectors.values()) {
injector.inject();
}
// XXX: Lazy inject the Instrumentation,
addInjector(AppInstrumentation.getDefault());
}
在这里会hook掉ActivityManager 和PackageManager
@Inject(MethodProxies.class)
public final class PackageManagerStub extends MethodInvocationProxy<MethodInvocationStub<IInterface>> {
public PackageManagerStub() {
super(new MethodInvocationStub<>(ActivityThread.sPackageManager.get()));
}
@Override
protected void onBindMethods() {
super.onBindMethods();
addMethodProxy(new ResultStaticMethodProxy("addPermissionAsync", true));
addMethodProxy(new ResultStaticMethodProxy("addPermission", true));
addMethodProxy(new ResultStaticMethodProxy("performDexOpt", true));
addMethodProxy(new ResultStaticMethodProxy("performDexOptIfNeeded", false));
addMethodProxy(new ResultStaticMethodProxy("performDexOptSecondary", true));
addMethodProxy(new ResultStaticMethodProxy("addOnPermissionsChangeListener", 0));
addMethodProxy(new ResultStaticMethodProxy("removeOnPermissionsChangeListener", 0));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
addMethodProxy(new ResultStaticMethodProxy("checkPackageStartable", 0));
}
if (BuildCompat.isOreo()) {
addMethodProxy(new ResultStaticMethodProxy("notifyDexLoad", 0));
addMethodProxy(new ResultStaticMethodProxy("notifyPackageUse", 0));
addMethodProxy(new ResultStaticMethodProxy("setInstantAppCookie", false));
addMethodProxy(new ResultStaticMethodProxy("isInstantApp", false));
}
}
@Override
public void inject() throws Throwable {
final IInterface hookedPM = getInvocationStub().getProxyInterface();
ActivityThread.sPackageManager.set(hookedPM);
BinderInvocationStub pmHookBinder = new BinderInvocationStub(getInvocationStub().getBaseInterface());
pmHookBinder.copyMethodProxies(getInvocationStub());
pmHookBinder.replaceService("package");
}
@Override
public boolean isEnvBad() {
return getInvocationStub().getProxyInterface() != ActivityThread.sPackageManager.get();
}
}
这里就是创建了一个PackageManager 的一个代理, 通过Java动态代理的方式,并通过反射写回到ActivityThread.sPackageManager
中,实现这个对象的代理,走到我们自己对象中
@Override
public boolean onCreate() {
Context context = getContext();
DaemonService.startup(context);
if (!VirtualCore.get().isStartup()) {
return true;
}
VPackageManagerService.systemReady();
IPCBus.register(IPackageManager.class, VPackageManagerService.get());
VActivityManagerService.systemReady(context);
IPCBus.register(IActivityManager.class, VActivityManagerService.get());
IPCBus.register(IUserManager.class, VUserManagerService.get());
VAppManagerService.systemReady();
IPCBus.register(IAppManager.class, VAppManagerService.get());
BroadcastSystem.attach(VActivityManagerService.get(), VAppManagerService.get());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
IPCBus.register(IJobService.class, VJobSchedulerService.get());
}
VNotificationManagerService.systemReady(context);
IPCBus.register(INotificationManager.class, VNotificationManagerService.get());
VAppManagerService.get().scanApps();
VAccountManagerService.systemReady();
IPCBus.register(IAccountManager.class, VAccountManagerService.get());
IPCBus.register(IVirtualStorageService.class, VirtualStorageService.get());
IPCBus.register(IDeviceInfoManager.class, VDeviceManagerService.get());
IPCBus.register(IVirtualLocationManager.class, VirtualLocationService.get());
return true;
}
IServiceFetcher.Stub 的实现在BinderProvider.java 中
private class ServiceFetcher extends IServiceFetcher.Stub {
@Override
public IBinder getService(String name) throws RemoteException {
if (name != null) {
return ServiceCache.getService(name);
}
return null;
}
@Override
public void addService(String name, IBinder service) throws RemoteException {
if (name != null && service != null) {
ServiceCache.addService(name, service);
}
}
@Override
public void removeService(String name) throws RemoteException {
if (name != null) {
ServiceCache.removeService(name);
}
}
}
BinderProvider.java
@Override
public Bundle call(String method, String arg, Bundle extras) {
if ("@".equals(method)) {
Bundle bundle = new Bundle();
BundleCompat.putBinder(bundle, "_VA_|_binder_", mServiceFetcher);
return bundle;
}
if ("register".equals(method)) {
}
return null;
}
sFetcher = IServiceFetcher.Stub.asInterface(binder);
创建客户端的interface,具体可以参考
ServiceManagerNative.java 的以下方法
private static IServiceFetcher getServiceFetcher() {
if (sFetcher == null || !sFetcher.asBinder().isBinderAlive()) {
synchronized (ServiceManagerNative.class) {
Context context = VirtualCore.get().getContext();
Bundle response = new ProviderCall.Builder(context, SERVICE_CP_AUTH).methodName("@").call();
if (response != null) {
IBinder binder = BundleCompat.getBinder(response, "_VA_|_binder_");
linkBinderDied(binder);
sFetcher = IServiceFetcher.Stub.asInterface(binder);
}
}
}
return sFetcher;
}
客户段通过这个Fetcher来访问服务端的各个服务,而各个服务都是封装成了TransformBinder 对象,TransformBinder 继承于Binder, 可通过RPC进行通信
至此virtual app 启动完毕