virtualapp启动流程源码分析

virtualapp,启动,流程,源码,分析 · 浏览次数 : 97

小编点评

## ContentResolver.acquireContentProviderClient 获取 BinderProvider的代理服务 这段代码展示了如何通过 ContentResolver.acquireContentProviderClient 获取 BinderProvider 的代理服务,并执行其 `onCreate` 方法。 **主要步骤:** 1. **获取 BinderProvider 的 client:** - `context` 获取应用程序上下文。 - `serviceResolver` 获取 ContentResolver 对象。 - `client = serviceResolver.acquireContentProviderClient(context, null)` 获取 BinderProvider 的代理服务。 2. **调用 `onCreate` 方法:** - `onCreate` 方法是一个特殊的 `onCreate` 方法,在 BinderProvider 创建之前调用。 - 在 `onCreate` 中,首先创建了 `DaemonService`,这是一个后台服务,负责保持 BinderProvider 的活动。 - 然后,初始化了各个模拟的系统服务,并注册到 ServiceCache 中。 - 最后,通过 `ServiceFetcher` 创建了客户端的接口,并通过 `sFetcher = IServiceFetcher.Stub.asInterface(binder)` 将 BinderProvider 的接口绑定到服务端接口上。 **具体代码分析:** ```java private ServiceFetcher mServiceFetcher; @Override public IBinder getService(String name) throws RemoteException { if ("@".equals(method)) { Bundle bundle = new Bundle(); bundle.putBinder(bundle, "._VA_|_binder_", mServiceFetcher); return bundle; } // 其他方法省略... } ``` 这段代码展示了 BinderProvider 的代理服务如何通过 `ServiceFetcher` 与服务端进行通信。具体来说,当客户段通过 BinderProvider 并调用方法名为 "@"时,会返回 `mServiceFetcher`。然后,通过 `sFetcher = IServiceFetcher.Stub.asInterface(binder)` 创建了一个客户端接口,并通过 `mServiceFetcher` 的 `invoke()` 方法执行方法。 **其他注释:** * `BinderProvider` 是一个远程服务接口,使用 RPC 进行通信。 * `ServiceFetcher` 是一个实现 RPC 通用的服务,负责与服务端进行通信。 * `Binder` 是一个远程对象接口,表示一个远程服务的接口。 * `Stub` 是一个动态代理,可以根据实际运行环境的条件创建不同的远程对象实现。

正文

virtualapp启动流程分析

1. 首先是启动本身,执行Vpp 的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;
		}
		......
	}

由于当前我们是主进程,所以这里注入是啥也没干

2. 然后进入APP 的主Activity(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

2. 服务进程启动流程

由于provider的启动,那么流程又会走到VApp中,在这个进程中走attachBaseContextVirtualCore.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

先查看PackageManager 的hooker PackageManagerStub
@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中,实现这个对象的代理,走到我们自己对象中

然后走到BinderProvider的onCreate中
    @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;
    }

BinderProvideronCreate方法,在其中启动后台的DaemonService,保持:x进程不被系统杀死。然后初始化各个模拟的系统服务,如VPackageManagerService、VUserManagerService、VActivityManagerService、VAppManagerService、VNotificationManagerService、VAccountManagerService等,并注册到ServiceCache中
最终通过 IServiceFetcher.aidl 实现rpc通信,实现客户端进程来服务端访问数据

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);
            }
        }
    }
从这里可以看出, 当调用getService 时,实际时从ServiceCache中访问之前注册的service
那么客户端如何获得Fetcher呢

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;
    }
当客户段通过BinderProvider 并调用方法名为"@"时,会返回mServiceFetcher,并通过

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 启动完毕

与virtualapp启动流程源码分析相似的内容: