virtualapp-IPCBus跨进程通讯(转载)

转自:https://www.jianshu.com/p/d47fdf3133c4

IPCBus

IPCBus是虚拟app进程和ServerProcess进程通信的核心。

public class IPCBus {

    private static IServerCache sCache;

    public static void initialize(IServerCache cache) {
        sCache = cache;
    }

    private static void checkInitialized() {
        if (sCache == null) {
            throw new IllegalStateException("please call initialize() at first.");
        }
    }

    public static void register(Class<?> interfaceClass, Object server) {
        checkInitialized();
        ServerInterface serverInterface = new ServerInterface(interfaceClass);
        TransformBinder binder = new TransformBinder(serverInterface, server);
        sCache.join(serverInterface.getInterfaceName(), binder);
    }

    public static <T> T get(Class<?> interfaceClass) {
        checkInitialized();
        ServerInterface serverInterface = new ServerInterface(interfaceClass);
        IBinder binder = sCache.query(serverInterface.getInterfaceName());
        if (binder == null) {
            return null;
        }
        //noinspection unchecked
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new IPCInvocationBridge(serverInterface, binder));
    }
}

IPCBus主要有两个方法registergetregister方法根据传入的class对象构造ServerInterface对象。

ServerInterface

 public ServerInterface(Class<?> interfaceClass) {
        this.interfaceClass = interfaceClass;
        Method[] methods = interfaceClass.getMethods();
        codeToInterfaceMethod = new SparseArray<>(methods.length);
        methodToIPCMethodMap = new HashMap<>(methods.length);
        for (int i = 0; i < methods.length; i++) {
            int code = Binder.FIRST_CALL_TRANSACTION + i;
            IPCMethod ipcMethod = new IPCMethod(code, methods[i], interfaceClass.getName());
            codeToInterfaceMethod.put(code, ipcMethod);
            methodToIPCMethodMap.put(methods[i], ipcMethod);
        }
    }

ServerInterface构造函数里面通过反射获取methods然后再根据Binder.FIRST_CALL_TRANSACTION的自增去构造IPCMethod实例(这个类后面会讲到,通过反射进行方法调用并将结果通过Parcel进行回传),
接着通过键值codemethodIPCMethod存储在两个Map中。

TransformBinder

ServerInterface实例构造完成后,再和传入的server实例对象构造TransformBinder

public class TransformBinder extends Binder {

    private ServerInterface serverInterface;
    private Object server;

    public TransformBinder(ServerInterface serverInterface, Object server) {
        this.serverInterface = serverInterface;
        this.server = server;
    }

    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        if (code == INTERFACE_TRANSACTION) {
            reply.writeString(serverInterface.getInterfaceName());
            return true;
        }
        IPCMethod method = serverInterface.getIPCMethod(code);
        if (method != null) {
            try {
                method.handleTransact(server, data, reply);
            } catch (Throwable e) {
                e.printStackTrace();
            }
            return true;
        }
        return super.onTransact(code, data, reply, flags);
    }
}

从代码可以看到TransformBinder主要的方法是重载了Binder的onTransact方法,这个方法通常是在IPC通信中接收消息然后进行回传处理的地方。

在这里我们又看到了IPCMethod,是通过codeServerInterface中获取,跟前面的serverInterface构造就对应起来了,然后调用handleTransact方法。

public void handleTransact(Object server, Parcel data, Parcel reply) {
        data.enforceInterface(interfaceName);
        Object[] parameters = data.readArray(getClass().getClassLoader());
        if (parameters != null && parameters.length > 0) {
            for (int i = 0; i < parameters.length; i++) {
                if (converters[i] != null) {
                    parameters[i] = converters[i].convert(parameters[i]);
                }
            }
        }
        try {
            Object res = method.invoke(server, parameters);
            reply.writeNoException();
            reply.writeValue(res);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            reply.writeException(e);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            reply.writeException(e);
        }
    }

我们跟踪这个方法进去看到,果然就是反射调用在IPCMethodmethod,并且将结果通过reply写回请求进程完成IPC通信。

这样我们再回到IPCBus中的register方法中,在构造完这个TransformBinder后调用sCache.join(serverInterface.getInterfaceName(), binder); 最终调用ServiceCache.addService方法进行存储。

IPCBus.initialize(new IServerCache() {
                @Override
                public void join(String serverName, IBinder binder) {
                    ServiceCache.addService(serverName, binder);
                }

                @Override
                public IBinder query(String serverName) {
                    return ServiceManagerNative.getService(serverName);
                }
            });

我们再回到IPCBus中的get(Class<?> interfaceClass)方法,那其实就是调用ServiceManagerNative.getService()的方法获取IBinder对象,并且返回interfaceClassproxy类(参考上面的代码)。

JAVA的动态proxy可以参考: http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html(官方英文)
http://wiki.jikexueyuan.com/project/java-reflection/java-dynamic.html (官方英文)
https://www.cnblogs.com/LCcnblogs/p/6823982.html (简单易懂小示例)

我们再跟踪进去看下get(Class<?> interfaceClass)方法中IPCInvocationBridge这个类干了什么

public class IPCInvocationBridge implements InvocationHandler {

    private ServerInterface serverInterface;
    private IBinder binder;

    public IPCInvocationBridge(ServerInterface serverInterface, IBinder binder) {
        this.serverInterface = serverInterface;
        this.binder = binder;
    }

    @Override
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
        IPCMethod ipcMethod = serverInterface.getIPCMethod(method);
        if (ipcMethod == null) {
            throw new IllegalStateException("Can not found the ipc method : " + method.getDeclaringClass().getName() + "@" +  method.getName());
        }
        return ipcMethod.callRemote(binder, args);
    }
}

在重载InvocationHandlerinvoke方法中我们又看到了熟悉的serverInterfaceIPCMethod,然后调用IPCMethodcallRmote方法。

public Object callRemote(IBinder server, Object[] args) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        Object result;
        try {
            data.writeInterfaceToken(interfaceName);
            data.writeArray(args);
            server.transact(code, data, reply, 0);
            reply.readException();
            result = readValue(reply);
            if (resultConverter != null) {
                result = resultConverter.convert(result);
            }
        } finally {
            data.recycle();
            reply.recycle();
        }
        return result;
    }

这个方法主要就是发起一次IPC请求,传入需要调用的类名称(data.writeInterfaceToken(interfaceName);),参数( data.writeArray(args);),对应的方法( server.transact(code, data, reply, 0);),然后通过IBindertransact进行IPC调用。

到这里我们其实可以发现这和前面提到的handleTransact方法对应起来,一个是请求,一个是应答处理。

我们再次回到IPCBusget(Class<?> interfaceClass)方法,那其实这里的IBinder应该就是TransformBinder在调用进程的BinderProxy,其他进程通过get方法获取BinderProxy来向TransformBinder所在的进程发送IPC调用。

到了这里大家可能会一头雾水,别急我们去看下sCache.query也就是ServiceManagerNative.getService(serverName)看看是不是返回的是BinderProxy

一次跨进程远程通信的过程是:
1.Client的代码调用BinderProxy.transact(),发起远程调用。参数flags为0时方法阻塞,等待Server端对应方法返回后继续执行。参数flags为FLAG_ONEWAY时立即返回。
2.Client中的transact()调用传递式触发Server端Binder.transact()的调用,进而调用Binder.onTransact()
3.Server端,Binder.onTransact()中,子类的重写方法根据收到的code,执行对应业务逻辑,设置必要的返回数据到参数reply,然后Binder.transact()方法返回。
4.Client端,BinderProxy.transact()从阻塞状态返回,调用者解析得到必要的返回参数,继续执行。

ServiceManagerNative

public static IBinder getService(String name) {
        if (VirtualCore.get().isServerProcess()) {
            return ServiceCache.getService(name);
        }
        IServiceFetcher fetcher = getServiceFetcher();
        if (fetcher != null) {
            try {
                return fetcher.getService(name);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        VLog.e(TAG, "GetService(%s) return null.", name);
        return null;
    }

在这里可以看到如果是ServerProcess进程直接返回保存在ServiceCacheTransformBinder,如果是其他进程,则调用getServiceFetcher,再通过其getService进行返回。

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;
    }

getServiceFetcher方法主要是启动一个virtual.service.BinderProviderContentProvider并且调用"@"方法。

<provider
            android:name="com.lody.virtual.server.BinderProvider"
            android:authorities="${applicationId}.virtual.service.BinderProvider"
            android:exported="false"
            android:process="@string/engine_process_name" />

BinderProvider

我们再来看看BinderProvider这个类主要作用。
https://www.jianshu.com/p/5e893d814a53(ContentProvider 的简单示例)

public final class BinderProvider extends ContentProvider {

    private final ServiceFetcher mServiceFetcher = new ServiceFetcher();

    @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;
    }

    @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;
    }
    ...
    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就启动了ServerProcess进程,在这个进程里面我们看到通过BinderProvideronCreate方法调用了大量的IPCBus.register方法把一系列的VPackageManagerService等对应的TransformBinder保存了在这个ServerProcess进程的ServiceCache中。

我们再来看call方法,返回了一个ServiceFetcher通过键值"VA|binder"进行存储的Bundle

我们再回到ServiceManagerNativegetService中,这个时候我们就明白了,如果是其他进程则先通过getServiceFetcher获取ServiceFetcherBinderProxy,然后再调用getService方法获取对应的TransformBinder在这个进程的BinderProxy,然后通过Proxy去调用ServerProcess进程的对应VxxService服务。这个时候其他VAppProcess进程跟ServerProcess进程的交互就通过这一系列IPCBusIPCMethodBinderTransformer等来完成。

整个流程图如下:
在这里插入图片描述

InvocationStubManager

public final class InvocationStubManager {
    ...
    void injectAll() throws Throwable {
        for (IInjector injector : mInjectors.values()) {
            injector.inject();
        }
        // XXX: Lazy inject the Instrumentation,
        addInjector(AppInstrumentation.getDefault());
    }
    ...
    private void injectInternal() throws Throwable {
        if (VirtualCore.get().isMainProcess()) {
            return;
        }
        if (VirtualCore.get().isServerProcess()) {
            addInjector(new ActivityManagerStub());
            addInjector(new PackageManagerStub());
            return;
        }
        if (VirtualCore.get().isVAppProcess()) {
            addInjector(new LibCoreStub());
            addInjector(new ActivityManagerStub());
            addInjector(new PackageManagerStub());
            addInjector(HCallbackStub.getDefault());
            addInjector(new ISmsStub());
            addInjector(new ISubStub());
            addInjector(new DropBoxManagerStub());
            addInjector(new NotificationManagerStub());
            addInjector(new LocationManagerStub());
            addInjector(new WindowManagerStub());
            addInjector(new ClipBoardStub());
            addInjector(new MountServiceStub());
            addInjector(new BackupManagerStub());
            addInjector(new TelephonyStub());
            addInjector(new TelephonyRegistryStub());
            addInjector(new PhoneSubInfoStub());
            addInjector(new PowerManagerStub());
            addInjector(new AppWidgetManagerStub());
            addInjector(new AccountManagerStub());
            addInjector(new AudioManagerStub());
            addInjector(new SearchManagerStub());
            addInjector(new ContentServiceStub());
            addInjector(new ConnectivityStub());

            if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR2) {
                addInjector(new VibratorStub());
                addInjector(new WifiManagerStub());
                addInjector(new BluetoothStub());
                addInjector(new ContextHubServiceStub());
            }
            if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR1) {
                addInjector(new UserManagerStub());
            }

            if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR1) {
                addInjector(new DisplayStub());
            }
            if (Build.VERSION.SDK_INT >= LOLLIPOP) {
                addInjector(new PersistentDataBlockServiceStub());
                addInjector(new InputMethodManagerStub());
                addInjector(new MmsStub());
                addInjector(new SessionManagerStub());
                addInjector(new JobServiceStub());
                addInjector(new RestrictionStub());
            }
            if (Build.VERSION.SDK_INT >= KITKAT) {
                addInjector(new AlarmManagerStub());
                addInjector(new AppOpsManagerStub());
                addInjector(new MediaRouterServiceStub());
            }
            if (Build.VERSION.SDK_INT >= LOLLIPOP_MR1) {
                addInjector(new GraphicsStatsStub());
                addInjector(new UsageStatsManagerStub());
            }
            if (Build.VERSION.SDK_INT >= M) {
                addInjector(new FingerprintManagerStub());
                addInjector(new NetworkManagementStub());
            }
            if (Build.VERSION.SDK_INT >= N) {
                addInjector(new WifiScannerStub());
                addInjector(new ShortcutServiceStub());
                addInjector(new DevicePolicyManagerStub());
            }
            if (Build.VERSION.SDK_INT >= 26) {
                addInjector(new AutoFillManagerStub());
            }
        }
    }

    ...

    public <T extends IInjector, H extends MethodInvocationStub> H getInvocationStub(Class<T> injectorClass) {
        T injector = findInjector(injectorClass);
        if (injector != null && injector instanceof MethodInvocationProxy) {
            // noinspection unchecked
            return (H) ((MethodInvocationProxy) injector).getInvocationStub();
        }
        return null;
    }
}

里面最主要的方法就是injectInternal,从这里看到主进程(io.virtualapp)没有进行hookServerProcess(io.virtualapp:x)AMS以及PMSBinderProxy进行了hook,而VAppProcess则对大量的系统服务进行了hook

具体的hook是通过MethodInvocationStubMethodInvocationProxyMethodProxy这个基础框架来完成的,具体的原理也是生成需要hook类的proxy对象通过反射进行注入,这里就不在细说了。整个封装的Hook框架是在包名com.lody.virtual.hook下

两个进程一个是va的主进程(io.virtualapp)通过ui处理安装和多开app等功能,一个ServerProcess进程虚拟了VxxService10个服务,来替代androidsystemservice进程里的服务来完成和VAppProcess进程的交互。

参考:https://www.jianshu.com/p/d47fdf3133c4

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Microsoft Virtual Wi-Fi,也称为软AP(软件接入点),是一种由微软开发的技术,旨在为Windows操作系统提供无线网络连接共享的功能。使用Microsoft Virtual Wi-Fi,用户可以将计算机的无线适配器转换为多个虚拟适配器,使得一台计算机可以同时连接多个无线网络。 这项技术的应用场景非常广泛。举例来说,当用户的计算机只能连接一个无线网络,而他们希望将网络共享给其他设备时,Microsoft Virtual Wi-Fi便可派上用场。通过将计算机的一个虚拟接入点与设备连接,其他设备便可以通过这个接入点访问互联网。此外,该技术还可以被用于创建无线网桥,将两个或多个无线网络连接起来。 Microsoft Virtual Wi-Fi的使用非常简便。首先,用户需要在他们的计算机上安装驱动程序,然后将软AP选项启用。一旦启用,用户可以使用命令行或系统图形界面来配置和管理虚拟接入点。 然而,需要注意的是Microsoft Virtual Wi-Fi仅适用于Windows操作系统,并且需要计算机硬件和驱动程序的支持。此外,由于多个网络连接将占用计算机的网络带宽和处理能力,因此可能会对性能产生一定的影响。 总而言之,Microsoft Virtual Wi-Fi是一项实用的技术,可以提供无线网络共享的功能,扩展了Windows操作系统的无线连接功能。它在各种场景下都能发挥作用,但需要注意其对计算机性能的一定影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值