• 浅谈VirtualApp


    VA初始化操作

    Vapp.Java

    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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    attachBaseContext的时候进行startup()加载hook等

    public void startup(Context context) throws Throwable {
        if (!isStartUp) {
            //判断是否为主线程
            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;
            this.context = context;
            //获取ActivityThread实例
            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) {
                    return ServiceManagerNative.getService(serverName);
                }
            });
            detectProcessType();
            //hook系统类
            InvocationStubManager invocationStubManager = InvocationStubManager.getInstance();
            invocationStubManager.init();
            invocationStubManager.injectAll();
            //修复权限管理
            ContextFixer.fixContext(context);
            isStartUp = true;
            if (initLock != null) {
                initLock.open();
                initLock = null;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    invocationStubManager.init();

    public void init() throws Throwable {
       if (isInit()) {
          throw new IllegalStateException("InvocationStubManager Has been initialized.");
       }
       injectInternal();
       sInit = true;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    对 Java 层 framework 的 Hook,将其定位到 VA 伪造 VA framework 上去

    private void injectInternal() throws Throwable {
     	//VA自身的app的进程不需要Hook
        if (VirtualCore.get().isMainProcess()) {
          return;
       }
        //VAService 需要 Hook AMS 和 PMS
       if (VirtualCore.get().isServerProcess()) {
          addInjector(new ActivityManagerStub());
          addInjector(new PackageManagerStub());
          return;
       }
        //Client APP 需要 Hook 整个 framework,来使其调用到 VA framework
       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());
          }
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    Vapp.java

    public void onCreate() {
        gApp = this;
        super.onCreate();
        VirtualCore virtualCore = VirtualCore.get();
        virtualCore.initialize(new VirtualCore.VirtualInitializer() {
    
            @Override
            public void onMainProcess() {
                Once.initialise(VApp.this);
                new FlurryAgent.Builder()
                        .withLogEnabled(true)
                        .withListener(() -> {
                            // nothing
                        })
                        .build(VApp.this, "48RJJP7ZCZZBB6KMMWW5");
            }
    
            @Override
            public void onVirtualProcess() {
                //listener components
                virtualCore.setComponentDelegate(new MyComponentDelegate());
                //fake phone imei,macAddress,BluetoothAddress
                virtualCore.setPhoneInfoDelegate(new MyPhoneInfoDelegate());
                //fake task description's icon and title
                virtualCore.setTaskDescriptionDelegate(new MyTaskDescriptionDelegate());
            }
    
            @Override
            public void onServerProcess() {
                virtualCore.setAppRequestListener(new MyAppRequestListener(VApp.this));
                virtualCore.addVisibleOutsidePackage("com.tencent.mobileqq");
                virtualCore.addVisibleOutsidePackage("com.tencent.mobileqqi");
                virtualCore.addVisibleOutsidePackage("com.tencent.minihd.qq");
                virtualCore.addVisibleOutsidePackage("com.tencent.qqlite");
                virtualCore.addVisibleOutsidePackage("com.facebook.katana");
                virtualCore.addVisibleOutsidePackage("com.whatsapp");
                virtualCore.addVisibleOutsidePackage("com.tencent.mm");
                virtualCore.addVisibleOutsidePackage("com.immomo.momo");
            }
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在onCrete方法中加载了安装app的方法在onServerProcess()内的 virtualCore.setAppRequestListener(new MyAppRequestListener(VApp.this));

    public void setAppRequestListener(final AppRequestListener listener) {
        IAppRequestListener inner = new IAppRequestListener.Stub() {
            @Override
            public void onRequestInstall(final String path) {
                VirtualRuntime.getUIHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        listener.onRequestInstall(path);
                    }
                });
            }
    
            @Override
            public void onRequestUninstall(final String pkg) {
                VirtualRuntime.getUIHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        listener.onRequestUninstall(pkg);
                    }
                });
            }
        };
        try {
            getService().setAppRequestListener(inner);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    其中listener.onRequestInstall(path);执行的是MyAppRequestListener.onRequestInstall

    public void onRequestInstall(String path) {
        Toast.makeText(context, "Installing: " + path, Toast.LENGTH_SHORT).show();
        InstallResult res = VirtualCore.get().installPackage(path, InstallStrategy.UPDATE_IF_EXIST);
        if (res.isSuccess) {
            try {
                VirtualCore.get().preOpt(res.packageName);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (res.isUpdate) {
                Toast.makeText(context, "Update: " + res.packageName + " success!", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(context, "Install: " + res.packageName + " success!", Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(context, "Install failed: " + res.error, Toast.LENGTH_SHORT).show();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    InstallResult res = VirtualCore.get().installPackage(path, InstallStrategy.UPDATE_IF_EXIST);调用到了VirtualCore.installPackage就开始执行安装

    Client App 的安装

    VirtualCore.java

    public InstallResult installPackage(String apkPath, int flags) {
        try {
            // 调用远程 VAService
            return getService().installPackage(apkPath, flags);
        } catch (RemoteException e) {
            return VirtualRuntime.crash(e);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    getService()返回的是IAppManager下边是调用过程

    private IAppManager getService() {
        return singleton.get();
    }
    
    • 1
    • 2
    • 3
    private IPCSingleton<IAppManager> singleton = new IPCSingleton<>(IAppManager.class);
    
    • 1
    public class IPCSingleton<T> 
        private Class<?> ipcClass;
        private T instance;
        public IPCSingleton(Class<?> ipcClass) {
            this.ipcClass = ipcClass;
        }
        public T get() {
            if (instance == null) {
                synchronized (this) {
                    if (instance == null) {
                        instance = IPCBus.get(ipcClass);
                    }
                }
            }
            return instance;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    IAppManager.java

    InstallResult installPackage(String path, int flags) throws RemoteException;
    
    • 1

    在VAppManagerService类中实现

    //先于installPackageAsUser安装apk,生成VPackage结构
    public synchronized InstallResult installPackage(String path, int flags, boolean notify) {
            long installTime = System.currentTimeMillis();
            if (path == null) {
                return InstallResult.makeFailure("path = NULL");
            }
        	//apk path
            File packageFile = new File(path);
            if (!packageFile.exists() || !packageFile.isFile()) {
                return InstallResult.makeFailure("Package File is not exist.");
            }
            VPackage pkg = null;
            try {
                 // 进入解析包结构,该结构是可序列化的,为了持久化在磁盘上
                pkg = PackageParserEx.parsePackage(packageFile);
            } catch (Throwable e) {
                e.printStackTrace();
            }
            if (pkg == null || pkg.packageName == null) {
                return InstallResult.makeFailure("Unable to parse the package.");
            }
            InstallResult res = new InstallResult();
            res.packageName = pkg.packageName;
            // PackageCache保存了所有的包,试着检查我们是否需要更新。
            VPackage existOne = PackageCacheManager.get(pkg.packageName);
            PackageSetting existSetting = existOne != null ? (PackageSetting) existOne.mExtras : null;
            if (existOne != null) {
                if ((flags & InstallStrategy.IGNORE_NEW_VERSION) != 0) {
                    res.isUpdate = true;
                    return res;
                }
                if (!canUpdate(existOne, pkg, flags)) {
                    return InstallResult.makeFailure("Not allowed to update the package.");
                }
                res.isUpdate = true;
            }
        	//获得apk安装文件夹
            File appDir = VEnvironment.getDataAppPackageDirectory(pkg.packageName);
           //so文件夹
        	File libDir = new File(appDir, "lib");
            if (res.isUpdate) {
                FileUtils.deleteDir(libDir);
                VEnvironment.getOdexFile(pkg.packageName).delete();
                VActivityManagerService.get().killAppByPkg(pkg.packageName, VUserHandle.USER_ALL);
            }
            if (!libDir.exists() && !libDir.mkdirs()) {
                return InstallResult.makeFailure("Unable to create lib dir.");
            }
       	    // 是否基于系统的 apk 加载,前提是安装过的 apk 并且 dependSystem 开关打开
            boolean dependSystem = (flags & InstallStrategy.DEPEND_SYSTEM_IF_EXIST) != 0
                    && VirtualCore.get().isOutsideInstalled(pkg.packageName);
    
            if (existSetting != null && existSetting.dependSystem) {
                dependSystem = false;
            }
    		//复制so 到 sandbox lib
            NativeLibraryHelperCompat.copyNativeBinaries(new File(path), libDir);
          	//如果不基于系统,一些必要的拷贝工作
        	if (!dependSystem) {
                File privatePackageFile = new File(appDir, "base.apk");
                File parentFolder = privatePackageFile.getParentFile();
                if (!parentFolder.exists() && !parentFolder.mkdirs()) {
                    VLog.w(TAG, "Warning: unable to create folder : " + privatePackageFile.getPath());
                } else if (privatePackageFile.exists() && !privatePackageFile.delete()) {
                    VLog.w(TAG, "Warning: unable to delete file : " + privatePackageFile.getPath());
                }
                try {
                    FileUtils.copyFile(packageFile, privatePackageFile);
                } catch (IOException e) {
                    privatePackageFile.delete();
                    return InstallResult.makeFailure("Unable to copy the package file.");
                }
                packageFile = privatePackageFile;
            }
            if (existOne != null) {
                PackageCacheManager.remove(pkg.packageName);
            }
           // 给上可执行权限,5.0 之后在 SD 卡上执行 bin 需要可执行权限
        	chmodPackageDictionary(packageFile);
          // PackageSetting 的一些配置,后面会序列化在磁盘上
        	PackageSetting ps;
            if (existSetting != null) {
                ps = existSetting;
            } else {
                ps = new PackageSetting();
            }
            ps.dependSystem = dependSystem;
            ps.apkPath = packageFile.getPath();
            ps.libPath = libDir.getPath();
            ps.packageName = pkg.packageName;
            ps.appId = VUserHandle.getAppId(mUidSystem.getOrCreateUid(pkg));
            if (res.isUpdate) {
                ps.lastUpdateTime = installTime;
            } else {
                ps.firstInstallTime = installTime;
                ps.lastUpdateTime = installTime;
                for (int userId : VUserManagerService.get().getUserIds()) {
                    boolean installed = userId == 0;
                    ps.setUserState(userId, false/*launched*/, false/*hidden*/, installed);
                }
            }
            //保存 VPackage Cache 到 Disk
            PackageParserEx.savePackageCache(pkg);
            //保存到 RamCache
            PackageCacheManager.put(pkg, ps);
            mPersistenceLayer.save();
            if (!dependSystem) {
                boolean runDexOpt = false;
                if (VirtualRuntime.isArt()) {
                    try {
                        ArtDexOptimizer.interpretDex2Oat(ps.apkPath, VEnvironment.getOdexFile(ps.packageName).getPath());
                    } catch (IOException e) {
                        e.printStackTrace();
                        runDexOpt = true;
                    }
                } else {
                    runDexOpt = true;
                }
                if (runDexOpt) {
                    try {
                        DexFile.loadDex(ps.apkPath, VEnvironment.getOdexFile(ps.packageName).getPath(), 0).close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            BroadcastSystem.get().startApp(pkg);
          //发送通知 安装完成
            if (notify) {
                notifyAppInstalled(ps, -1);
            }
            res.isSuccess = true;
            return res;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134

    APk 的安装主要完成以下几件事情:

    1. 解析 manifest 拿到 apk 内部信息,包括组件信息,权限信息等。并将这些信息序列化到磁盘和内存中,以备打开时调用。
    2. 准备 App 在 VA 沙箱环境中的私有空间,并且复制一些必要的 apk 和 so libs。
    3. 最后通知前台安装完成。

    解析manifest PackageParserEx.parsePackage()

    //解析包结构
    public static VPackage parsePackage(File packageFile) throws Throwable {
        PackageParser parser = PackageParserCompat.createParser(packageFile);
        //调用系统版本的 parsePackage 方法
        PackageParser.Package p = PackageParserCompat.parsePackage(parser, packageFile, 0);
        
        if (p.requestedPermissions.contains("android.permission.FAKE_PACKAGE_SIGNATURE")
                && p.mAppMetaData != null
                && p.mAppMetaData.containsKey("fake-signature")) {
            String sig = p.mAppMetaData.getString("fake-signature");
            p.mSignatures = new Signature[]{new Signature(sig)};
            VLog.d(TAG, "Using fake-signature feature on : " + p.packageName);
        } else {
          	//验证签名
            PackageParserCompat.collectCertificates(parser, p, PackageParser.PARSE_IS_SYSTEM);
        }
        //转换成可以序列化在磁盘上的Cache
        return buildPackageCache(p);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这里解析 Menifest 的方法其实是调用了 framework 隐藏方法 android.content.pm.PackageParser.parsePackage 来实现的,这个方法返回 android.content.pm.Package 结构,这个类型也是隐藏的,怎么办?可以从 sdk 中复制这个类到自己的项目中欺骗编译器。
    以 RefObject 为例

    类型 RefObject 代表映射 framework 层同名的泛型类型成员变量

    // Field 映射
    public class RefObject<T> {
       // framework 层对应的 Field
        private Field field;
    
        public RefObject(Class<?> cls, Field field) throws NoSuchFieldException {
            // 获取 framework 中同名字段的 field
            this.field = cls.getDeclaredField(field.getName());
            this.field.setAccessible(true);
        }
    	
        //获取变量值
        public T get(Object object) {
            try {
                return (T) this.field.get(object);
            } catch (Exception e) {
                return null;
            }
        }
    
        //赋值
        public void set(Object obj, T value) {
            try {
                this.field.set(obj, value);
            } catch (Exception e) {
                //Ignore
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    以 framework 层中隐藏类 LoadedApk 来说:

    public class LoadedApk {
        public static Class Class = RefClass.load(LoadedApk.class, "android.app.LoadedApk");
        public static RefObject<ApplicationInfo> mApplicationInfo;
        @MethodParams({boolean.class, Instrumentation.class})
        public static RefMethod<Application> makeApplication;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    mApplicationInfo 就是 LoadedApk 中私有 ApplicationInfo 类型字段的同名映射。

    当你引用 LoadedApk Mirror 类时,类加载器加载该类,执行静态成员的初始化表达式 RefClass.load(LoadedApk.class, “android.app.LoadedApk”); Mirror 类中的同名字段将被反射赋值。

    RefClass.load()

    public static Class load(Class mappingClass, Class realClass) {
            // 获取 Mirror 类的所有字段
            Field[] fields = mappingClass.getDeclaredFields();
            for (Field field : fields) {
                try {
                    // 必须是 static 变量
                    if (Modifier.isStatic(field.getModifiers())) {
                        // 从预设的 Map 中找到 RefXXXX 的构造器
                        Constructor constructor = REF_TYPES.get(field.getType());
                        if (constructor != null) {
                            // 赋值
                            field.set(null, constructor.newInstance(realClass, field));
                        }
                    }
                }
                catch (Exception e) {
                    // Ignore
                }
            }
            return realClass;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    最后调用的话 MirrorClass.mirrorField.get(instance),MirrorClass.mirrorField.set(instance),就相当于直接调用 framework 层的隐藏字段了。

    Package 类是不可序列化的,换句话说就是不能直接保存在磁盘上,我们需要将其转换成可以序列化的 VPackage 类型,这就是 buildPackageCache() 的作用。

    public class VPackage implements Parcelable {
    
        public static final Creator<VPackage> CREATOR = new Creator<VPackage>() {
            @Override
            public VPackage createFromParcel(Parcel source) {
                return new VPackage(source);
            }
    
            @Override
            public VPackage[] newArray(int size) {
                return new VPackage[size];
            }
        };
        public ArrayList<ActivityComponent> activities;
        public ArrayList<ActivityComponent> receivers;
        public ArrayList<ProviderComponent> providers;
        public ArrayList<ServiceComponent> services;
        public ArrayList<InstrumentationComponent> instrumentation;
        public ArrayList<PermissionComponent> permissions;
        public ArrayList<PermissionGroupComponent> permissionGroups;
        public ArrayList<String> requestedPermissions;
        public ArrayList<String> protectedBroadcasts;
        public ApplicationInfo applicationInfo;
        public Signature[] mSignatures;
        public Bundle mAppMetaData;
        public String packageName;
        public int mPreferredOrder;
        public String mVersionName;
        public String mSharedUserId;
        public ArrayList<String> usesLibraries;
        public int mVersionCode;
        public int mSharedUserLabel;
        // Applications hardware preferences
        public ArrayList<ConfigurationInfo> configPreferences = null;
        // Applications requested features
        public ArrayList<FeatureInfo> reqFeatures = null;
        public Object mExtras;
        ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    VPackage几乎保存的apk中所有的关键信息,尤其是组件的数据结构会在app在VA中运行的时候给VAMS,VPMS这些VAService提供apk的组件信息。

    关于是否 dependSystem 和 isInstallOutside,这个有关 apk 的动态加载,如果 dependSysytem 并且 apk 已经在外部环境安装了,那么 VA 会调用系统提供的 API 就可以动态加载 APK。反之 VA 需要做一些必要的复制工作然后再费劲的去加载 APK。

    APP启动

    VAService与通讯

    VAservice

    VirtualApp\lib\src\main\java\com\lody\virtual\server\am\*

    首先,VAService 是指 VA 仿造 Android 原生 framework 层 Service 实现的一套副本,举例有 VActivityManagerService,它和系统 AMS 一样,只不过他管理的是 VA 内部 Client App 的组件会话。

    VAService 统一管理

    首先所有 VAService 直接继承与 XXX.Stub,也就是 Binder,并且直接使用了一个 Map 储存在 VAService 进程空间中,并没有注册到系统 AMS 中,事实上在 VAService 进程中,每个 Service 都被当作一个普通对象 new 和 初始化。
    最终,他们被添加到了 ServiceCache 中:

    一个简单的map

    public class ServiceCache {
    
       private static final Map<String, IBinder> sCache = new ArrayMap<>(5);
    
       public static void addService(String name, IBinder service) {
          sCache.put(name, service);
       }
    
       public static IBinder removeService(String name) {
          return sCache.remove(name);
       }
    
       public static IBinder getService(String name) {
          return sCache.get(name);
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    而被添加的时机则在 BinderProvider 的 onCreate() 回掉中:

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    这里使用了IPC通信

    IPCBus.register()

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    checkInitialized()检验IServerCache是否为空

    private static void checkInitialized() {
        if (sCache == null) {
            throw new IllegalStateException("please call initialize() at first.");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    IServerCache.java

    public interface IServerCache {
        void join(String serverName, IBinder binder);
        IBinder query(String serverName);
    }
    
    • 1
    • 2
    • 3
    • 4

    join方法在

    VirtualCore.startup()中

    public void startup(Context context) throws Throwable {
        if (!isStartUp) {
            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;
            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) {
                    return ServiceManagerNative.getService(serverName);
                }
            });
            detectProcessType();
            InvocationStubManager invocationStubManager = InvocationStubManager.getInstance();
            invocationStubManager.init();
            invocationStubManager.injectAll();
            ContextFixer.fixContext(context);
            isStartUp = true;
            if (initLock != null) {
                initLock.open();
                initLock = null;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    回调了ServiceCache.addService(serverName, binder)方法,在BinderProvider 的 onCreate()中已经调用了

    DaemonService.startup(context)

    需要注意的是 DeamonService 是一个空前台服务,目的是为了保活 VAService 进程,即 :x 进程,因为现在后台服务很容易被杀,在 Android 8.0 以后后台服务只能在后台存活5S,而前台服务则不受影响。

    ServiceFetcher

    VA 设计了一个单独的 ServiceFetcher 服务用于向外部暴露 VAService 中的所有服务的 IBinder 句柄,而 ServiceFetcher 本身也是 Binder 服务,也就是说,ServiceFetcher 的 Ibinder 句柄是拿到其他 VAServic IBinder 的钥匙。

    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);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    ServicecFetcher 自身的 IBnder 则通过 BinderProvicer 这个ContentProvider 暴露给其他进程:

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    那么,在 Client App 中 VA Client 就可以通过 IServiceFetcher 这个 IBinder 拿到其他服务的 IBinder 了:

    com.lody.virtual.client.ipc.ServiceManagerNative

    private static IServiceFetcher sFetcher;
    
    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;
    }
    
    //返回服务的IBinder句柄
      public static IBinder getService(String name) {
    	  //如果是本地服务,直接本地返回
          if (VirtualCore.get().isServerProcess()) {
                return ServiceCache.getService(name);
            }
            //如果是ServiceFetcher的句柄找到远程Service 的句柄
            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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    启动App

    首先要了解的是 Android App 是组件化的,Apk 其实是 N 多个组件的集合,以及一些资源文件和 Assert,App 的启动有多种情况,只要在一个新的进程中调起了 apk 中任何一个组件,App 将被初始化,Application 将被初始化。

    启动Activity

    Hook startActivity(重定位 Intent 到 StubActivity)

    首先在 Client App 中,startActivity 方法必须被 Hook 掉,不然 Client App 调用 startActivity 就直指外部 Activity 去了。

    这部分的原理其实与 DroidPlugin 大同小异,由于插件(Client App)中的 Activity 是没有在 AMS 中注册的,AMS 自然无法找到我们的插件 Activity。

    Hook 的目的是我们拿到用户的 Intent,把他替换成指向 VA 在 Menifest 中站好坑的 StubActivity 的 Intent,然后将原 Intent 当作 data 打包进新 Intent 以便日后流程再次进入 VA 时恢复。

    Hook 的方法就是用我们动态代理生成的代理类对象替换系统原来的 ActiityManagerNative.geDefault 对象。

    com.lody.virtual.client.hook.proxies.am.ActivityManagerStub

    public void inject() throws Throwable {
        if (BuildCompat.isOreo()) {
            //Android Oreo(8.X)
            Object singleton = ActivityManagerOreo.IActivityManagerSingleton.get();
            Singleton.mInstance.set(singleton, getInvocationStub().getProxyInterface());
        } else {
            if (ActivityManagerNative.gDefault.type() == IActivityManager.TYPE) {
                ActivityManagerNative.gDefault.set(getInvocationStub().getProxyInterface());
            } else if (ActivityManagerNative.gDefault.type() == Singleton.TYPE) {
                Object gDefault = ActivityManagerNative.gDefault.get();
                Singleton.mInstance.set(gDefault, getInvocationStub().getProxyInterface());
            }
        }
        BinderInvocationStub hookAMBinder = new BinderInvocationStub(getInvocationStub().getBaseInterface());
        hookAMBinder.copyMethodProxies(getInvocationStub());
        ServiceManager.sCache.get().put(Context.ACTIVITY_SERVICE, hookAMBinder);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    好了,下面只要调用到 startActivity 就会被 Hook 到 call。
    这个函数需要注意以下几点:

    1. VA 有意将安装和卸载 APP 的请求重定向到了卸载 VA 内部 APK 的逻辑。
    2. resolveActivityInfo 调用到了 VPM 的 resolveIntent,最终会远程调用到 VPMS 的 resolveIntent,然后 VPMS 就会去查询 VPackage 找到目标 Activity 并将信息附加在 ResolveInfo 中返回 VPM。
    3. 最后也是最重要的一点,startActivity 会调用到 VAM.startActivity,同样最终会远程调用到 VAMS 的 startActivity。
    static class StartActivity extends MethodProxy {
    
        private static final String SCHEME_FILE = "file";
        private static final String SCHEME_PACKAGE = "package";
        private static final String SCHEME_CONTENT = "content";
    
        @Override
        public String getMethodName() {
            return "startActivity";
        }
    
        @Override
        public Object call(Object who, Method method, Object... args) throws Throwable {
    
            Log.d("Q_M", "---->StartActivity 类");
    
            int intentIndex = ArrayUtils.indexOfObject(args, Intent.class, 1);
            if (intentIndex < 0) {
                return ActivityManagerCompat.START_INTENT_NOT_RESOLVED;
            }
            int resultToIndex = ArrayUtils.indexOfObject(args, IBinder.class, 2);
            String resolvedType = (String) args[intentIndex + 1];
            Intent intent = (Intent) args[intentIndex];
            intent.setDataAndType(intent.getData(), resolvedType);
            IBinder resultTo = resultToIndex >= 0 ? (IBinder) args[resultToIndex] : null;
            int userId = VUserHandle.myUserId();
    
            if (ComponentUtils.isStubComponent(intent)) {
                return method.invoke(who, args);
            }
    
            // 请求安装和卸载界面
            if (Intent.ACTION_INSTALL_PACKAGE.equals(intent.getAction())
                    || (Intent.ACTION_VIEW.equals(intent.getAction())
                    && "application/vnd.android.package-archive".equals(intent.getType()))) {
                if (handleInstallRequest(intent)) {
                    return 0;
                }
            } else if ((Intent.ACTION_UNINSTALL_PACKAGE.equals(intent.getAction())
                    || Intent.ACTION_DELETE.equals(intent.getAction()))
                    && "package".equals(intent.getScheme())) {
    
                if (handleUninstallRequest(intent)) {
                    return 0;
                }
            }
    
            String resultWho = null;
            int requestCode = 0;
            Bundle options = ArrayUtils.getFirst(args, Bundle.class);
            if (resultTo != null) {
                resultWho = (String) args[resultToIndex + 1];
                requestCode = (int) args[resultToIndex + 2];
            }
            // chooser 调用选择界面
            if (ChooserActivity.check(intent)) {
                intent.setComponent(new ComponentName(getHostContext(), ChooserActivity.class));
                intent.putExtra(Constants.EXTRA_USER_HANDLE, userId);
                intent.putExtra(ChooserActivity.EXTRA_DATA, options);
                intent.putExtra(ChooserActivity.EXTRA_WHO, resultWho);
                intent.putExtra(ChooserActivity.EXTRA_REQUEST_CODE, requestCode);
                return method.invoke(who, args);
            }
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                args[intentIndex - 1] = getHostPkg();
            }
            if (intent.getScheme() != null && intent.getScheme().equals(SCHEME_PACKAGE) && intent.getData() != null) {
                if (intent.getAction() != null && intent.getAction().startsWith("android.settings.")) {
                    intent.setData(Uri.parse("package:" + getHostPkg()));
                }
            }
    		//解析 ActivityInfo
            ActivityInfo activityInfo = VirtualCore.get().resolveActivityInfo(intent, userId);
            if (activityInfo == null) {
                VLog.e("VActivityManager", "Unable to resolve activityInfo : " + intent);
    
                Log.d("Q_M", "---->StartActivity who=" + who);
                Log.d("Q_M", "---->StartActivity intent=" + intent);
                Log.d("Q_M", "---->StartActivity resultTo=" + resultTo);
    
                if (intent.getPackage() != null && isAppPkg(intent.getPackage())) {
                    return ActivityManagerCompat.START_INTENT_NOT_RESOLVED;
                }
    
                if (INTERCEPT_BACK_HOME && Intent.ACTION_MAIN.equals(intent.getAction())
                        && intent.getCategories().contains("android.intent.category.HOME")
                        && resultTo != null) {
                    VActivityManager.get().finishActivity(resultTo);
                    return 0;
                }
    
                return method.invoke(who, args);
            }
            // 调用远程 VAMS.startActivity
            int res = VActivityManager.get().startActivity(intent, activityInfo, resultTo, options, resultWho, requestCode, VUserHandle.myUserId());
            if (res != 0 && resultTo != null && requestCode > 0) {
                VActivityManager.get().sendActivityResult(resultTo, resultWho, requestCode);
            }
             // 处理 Activity 切换动画,因为此时动画还是 Host 的 Stub Activity 默认动画,需要覆盖成子程序包的动画
            if (resultTo != null) {
                ActivityClientRecord r = VActivityManager.get().getActivityRecord(resultTo);
                if (r != null && r.activity != null) {
                    try {
                        TypedValue out = new TypedValue();
                        Resources.Theme theme = r.activity.getResources().newTheme();
                        theme.applyStyle(activityInfo.getThemeResource(), true);
                        if (theme.resolveAttribute(android.R.attr.windowAnimationStyle, out, true)) {
    
                            TypedArray array = theme.obtainStyledAttributes(out.data,
                                    new int[]{
                                            android.R.attr.activityOpenEnterAnimation,
                                            android.R.attr.activityOpenExitAnimation
                                    });
    
                            r.activity.overridePendingTransition(array.getResourceId(0, 0), array.getResourceId(1, 0));
                            array.recycle();
                        }
                    } catch (Throwable e) {
                        // Ignore
                    }
                }
            }
            return res;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125

    逻辑最终走到 VAMS 后,VAMS 调用 ActivityStack.startActivityLocked

    public int startActivity(Intent intent, ActivityInfo info, IBinder resultTo, Bundle options, String resultWho, int requestCode, int userId) {
        synchronized (this) {
            return mMainStack.startActivityLocked(userId, intent, info, resultTo, options, resultWho, requestCode);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    startActivityLocked()

    //和framework的实现一致
    int startActivityLocked(int userId, Intent intent, ActivityInfo info, IBinder resultTo, Bundle options,
                            String resultWho, int requestCode) {
        optimizeTasksLocked();
    
        Intent destIntent;
        ActivityRecord sourceRecord = findActivityByToken(userId, resultTo);
        TaskRecord sourceTask = sourceRecord != null ? sourceRecord.task : null;
        
        ReuseTarget reuseTarget = ReuseTarget.CURRENT;
        ClearTarget clearTarget = ClearTarget.NOTHING;
        boolean clearTop = containFlags(intent, Intent.FLAG_ACTIVITY_CLEAR_TOP);
        boolean clearTask = containFlags(intent, Intent.FLAG_ACTIVITY_CLEAR_TASK);
    
    //对Flag的处理
    ......
        String affinity = ComponentUtils.getTaskAffinity(info);
    //根据Flag 寻找合适的 Task
        TaskRecord reuseTask = null;
        switch (reuseTarget) {
            case AFFINITY:
                reuseTask = findTaskByAffinityLocked(userId, affinity);
                break;
            case DOCUMENT:
                reuseTask = findTaskByIntentLocked(userId, intent);
                break;
            case CURRENT:
                reuseTask = sourceTask;
                break;
            default:
                break;
        }
    
        boolean taskMarked = false;
        if (reuseTask == null) {
            startActivityInNewTaskLocked(userId, intent, info, options);
        } else {
            boolean delivered = false;
            mAM.moveTaskToFront(reuseTask.taskId, 0);
            boolean startTaskToFront = !clearTask && !clearTop && ComponentUtils.isSameIntent(intent, reuseTask.taskRoot);
    
            if (clearTarget.deliverIntent || singleTop) {
                taskMarked = markTaskByClearTarget(reuseTask, clearTarget, intent.getComponent());
                ActivityRecord topRecord = topActivityInTask(reuseTask);
                if (clearTop && !singleTop && topRecord != null && taskMarked) {
                    topRecord.marked = true;
                }
                // Target activity is on top
                if (topRecord != null && !topRecord.marked && topRecord.component.equals(intent.getComponent())) {
                    deliverNewIntentLocked(sourceRecord, topRecord, intent);
                    delivered = true;
                }
            }
            if (taskMarked) {
                synchronized (mHistory) {
                    scheduleFinishMarkedActivityLocked();
                }
            }
            if (!startTaskToFront) {
                if (!delivered) {
                    destIntent = startActivityProcess(userId, sourceRecord, intent, info);
                    if (destIntent != null) {
                        startActivityFromSourceTask(reuseTask, destIntent, info, resultWho, requestCode, options);
                    }
                }
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    然后 call 到了 startActivityProcess ,这就是真正替换 Intent 的地方:

    // 使用 Host Stub Activity 的 Intent 包装原 Intent 
    private Intent startActivityProcess(int userId, ActivityRecord sourceRecord, Intent intent, ActivityInfo info) {
        intent = new Intent(intent);
        // 获得 Activity 对应的 ProcessRecorder,如果没有则表示这是 Process 第一个打开的组件,需要初始化 Application
        ProcessRecord targetApp = mService.startProcessIfNeedLocked(info.processName, userId, info.packageName);
        if (targetApp == null) {
            return null;
        }
        Intent targetIntent = new Intent();
         // 根据 Client App 的 PID 获取 StubActivity
        targetIntent.setClassName(VirtualCore.get().getHostPkg(), fetchStubActivity(targetApp.vpid, info));
        ComponentName component = intent.getComponent();
        if (component == null) {
            component = ComponentUtils.toComponentName(info);
        }
        targetIntent.setType(component.flattenToString());
        StubActivityRecord saveInstance = new StubActivityRecord(intent, info,
                sourceRecord != null ? sourceRecord.component : null, userId);
        saveInstance.saveToIntent(targetIntent);
        return targetIntent;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    fetchStubActivity 会根据相同的进程 id 在 VA 的 Menifest 中找到那个提前占坑的 StubActivity:

    // 获取合适的 StubActivity,返回 StubActivity 全限定名
    private String fetchStubActivity(int vpid, ActivityInfo targetInfo) {
    
        boolean isFloating = false;
        boolean isTranslucent = false;
        boolean showWallpaper = false;
        try {
            int[] R_Styleable_Window = R_Hide.styleable.Window.get();
            int R_Styleable_Window_windowIsTranslucent = R_Hide.styleable.Window_windowIsTranslucent.get();
            int R_Styleable_Window_windowIsFloating = R_Hide.styleable.Window_windowIsFloating.get();
            int R_Styleable_Window_windowShowWallpaper = R_Hide.styleable.Window_windowShowWallpaper.get();
    
            AttributeCache.Entry ent = AttributeCache.instance().get(targetInfo.packageName, targetInfo.theme,
                    R_Styleable_Window);
            if (ent != null && ent.array != null) {
                showWallpaper = ent.array.getBoolean(R_Styleable_Window_windowShowWallpaper, false);
                isTranslucent = ent.array.getBoolean(R_Styleable_Window_windowIsTranslucent, false);
                isFloating = ent.array.getBoolean(R_Styleable_Window_windowIsFloating, false);
            }else{
                Resources resources=VirtualCore.get().getResources(targetInfo.packageName);
                if(resources!=null) {
                    TypedArray typedArray = resources.newTheme().obtainStyledAttributes(targetInfo.theme, R_Styleable_Window);
                    if(typedArray!=null){
                        showWallpaper = typedArray.getBoolean(R_Styleable_Window_windowShowWallpaper, false);
                        isTranslucent = typedArray.getBoolean(R_Styleable_Window_windowIsTranslucent, false);
                        isFloating = typedArray.getBoolean(R_Styleable_Window_windowIsFloating, false);
                    }
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    // 根据在 Menifest 中注册的 pid
        boolean isDialogStyle = isFloating || isTranslucent || showWallpaper;
        if (isDialogStyle) {
            return VASettings.getStubDialogName(vpid);
        } else {
            return VASettings.getStubActivityName(vpid);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    VA 没有为每个 Process 注册多个 Activity,也没有为不同的启动方式注册多个 Activity,这里确实是有改进的。
    这里根本原因是因为 VA 对 VAMS 实现的更为完整,实现了原版 AMS 的基本功能,包括完整的 Recorder 管理,Task Stack 管理等,这样的话 StubActivity 的唯一作用便是携带 Client App 真正的 Intent 交给 VAMS 处理。这套机制衍生到其他的组件也是一样的。
    ActivityStack, TaskRecord ,ActivityRecord

    /* package */ class ActivityStack {
    
        private final ActivityManager mAM;
        private final VActivityManagerService mService;
    
        /**
         * [Key] = TaskId [Value] = TaskRecord
         */
        private final SparseArray<TaskRecord> mHistory = new SparseArray<>();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    class TaskRecord {
        public final List<ActivityRecord> activities = Collections.synchronizedList(new ArrayList<ActivityRecord>());
        public int taskId;
        public int userId;
        public String affinity;
        public Intent taskRoot;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    /* package */ class ActivityRecord {
       public TaskRecord task;
       public ComponentName component;
       public ComponentName caller;
        // Client App 中 Activity 的句柄
       public IBinder token;
       public int userId;
       public ProcessRecord process;
       public int launchMode;
       public int flags;
       public boolean marked;
       public String affinity;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    StubActivityRecorder:

    public class StubActivityRecord  {
            public Intent intent;
            public ActivityInfo info;
            public ComponentName caller;
            public int userId;
    
            public StubActivityRecord(Intent intent, ActivityInfo info, ComponentName caller, int userId) {
                this.intent = intent;
                this.info = info;
                this.caller = caller;
                this.userId = userId;
            }
    		//获得原版Intent和一些其他信息
            public StubActivityRecord(Intent stub) {
                this.intent = stub.getParcelableExtra("_VA_|_intent_");
                this.info = stub.getParcelableExtra("_VA_|_info_");
                this.caller = stub.getParcelableExtra("_VA_|_caller_");
                this.userId = stub.getIntExtra("_VA_|_user_id_", 0);
            }
    
        //将原版的Intent塞到Stub Intent
        public void saveToIntent(Intent stub) {
            stub.putExtra("_VA_|_intent_", intent);
            stub.putExtra("_VA_|_info_", info);
            stub.putExtra("_VA_|_caller_", caller);
            stub.putExtra("_VA_|_user_id_", userId);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    初始化 Application

    VActivityManagerService.java

    private ComponentName startServiceCommon(Intent service,
                                             boolean scheduleServiceArgs, int userId) {
        ServiceInfo serviceInfo = resolveServiceInfo(service, userId);
        if (serviceInfo == null) {
            return null;
        }
        ProcessRecord targetApp = startProcessIfNeedLocked(ComponentUtils.getProcessName(serviceInfo),
                userId,
                serviceInfo.packageName);
    
        if (targetApp == null) {
            VLog.e(TAG, "Unable to start new Process for : " + ComponentUtils.toComponentName(serviceInfo));
            return null;
        }
        IInterface appThread = targetApp.appThread;
        ServiceRecord r = findRecordLocked(userId, serviceInfo);
        if (r == null) {
            r = new ServiceRecord();
            r.startId = 0;
            r.activeSince = SystemClock.elapsedRealtime();
            r.process = targetApp;
            r.serviceInfo = serviceInfo;
            try {
                IApplicationThreadCompat.scheduleCreateService(appThread, r, r.serviceInfo, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            addRecord(r);
        }
        r.lastActivityTime = SystemClock.uptimeMillis();
        if (scheduleServiceArgs) {
            r.startId++;
            boolean taskRemoved = serviceInfo.applicationInfo != null
                    && serviceInfo.applicationInfo.targetSdkVersion < Build.VERSION_CODES.ECLAIR;
            try {
                IApplicationThreadCompat.scheduleServiceArgs(appThread, r, taskRemoved, r.startId, 0, service);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return ComponentUtils.toComponentName(serviceInfo);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    // 获得 Activity 对应的 ProcessRecorder,如果没有则表示这是 Process 第一个打开的组件,需要初始化 Application
    ProcessRecord targetApp = startProcessIfNeedLocked(ComponentUtils.getProcessName(serviceInfo),
                userId,
                serviceInfo.packageName);
    
    • 1
    • 2
    • 3
    • 4

    startProcessIfNeedLocked()

    ProcessRecord startProcessIfNeedLocked(String processName, int userId, String packageName) {
        if (VActivityManagerService.get().getFreeStubCount() < 3) {
            // run GC
            killAllApps();
        }
        PackageSetting ps = PackageCacheManager.getSetting(packageName);
        ApplicationInfo info = VPackageManagerService.get().getApplicationInfo(packageName, 0, userId);
        if (ps == null || info == null) {
            return null;
        }
        if (!ps.isLaunched(userId)) {
            sendFirstLaunchBroadcast(ps, userId);
            ps.setLaunched(userId, true);
            VAppManagerService.get().savePersistenceData();
        }
        int uid = VUserHandle.getUid(userId, ps.appId);
        ProcessRecord app = mProcessNames.get(processName, uid);
        if (app != null && app.client.asBinder().isBinderAlive()) {
            return app;
        }
        int vpid = queryFreeStubProcessLocked();
        if (vpid == -1) {
            return null;
        }
        app = performStartProcessLocked(uid, vpid, info, processName);
        if (app != null) {
            app.pkgList.add(info.packageName);
        }
        return app;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    performStartProcessLocked()

    这里会先去找对应 Client App 进程的 ProcessRecorder,找不到代表 Application 刚启动尚未初始化:

    private ProcessRecord performStartProcessLocked(int vuid, int vpid, ApplicationInfo info, String processName) {
        ProcessRecord app = new ProcessRecord(info, processName, vuid, vpid);
        Bundle extras = new Bundle();
        BundleCompat.putBinder(extras, "_VA_|_binder_", app);
        extras.putInt("_VA_|_vuid_", vuid);
        extras.putString("_VA_|_process_", processName);
        extras.putString("_VA_|_pkg_", info.packageName);
      
         // 调用子程序包的 init_process 方法,并且得到子程序包 IBinder 句柄
        Bundle res = ProviderCall.call(VASettings.getStubAuthority(vpid), "_VA_|_init_process_", null, extras);
        if (res == null) {
            return null;
        }
        int pid = res.getInt("_VA_|_pid_");
        IBinder clientBinder = BundleCompat.getBinder(res, "_VA_|_client_");
        // attach 到 Client 的 VAM , 将子程序句柄推入服务端 VAMS
        attachClient(pid, clientBinder);
        return app;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    ProviderCall.call 向 Client App 的 StubContentProvider 发起远程调用:

    StubContentProvider.java

    public Bundle call(String method, String arg, Bundle extras) {
       if ("_VA_|_init_process_".equals(method)) {
          return initProcess(extras);
       }
       return null;
    }
    
    private Bundle initProcess(Bundle extras) {
       ConditionVariable lock = VirtualCore.get().getInitLock();
       if (lock != null) {
          lock.block();
       }
       IBinder token = BundleCompat.getBinder(extras,"_VA_|_binder_");
       int vuid = extras.getInt("_VA_|_vuid_");
       VClientImpl client = VClientImpl.get();
       client.initProcess(token, vuid);
       Bundle res = new Bundle();
       BundleCompat.putBinder(res, "_VA_|_client_", client.asBinder());
       res.putInt("_VA_|_pid_", Process.myPid());
       return res;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Client App 的 IBinder 句柄(VClientImpl.asBinder) 被打包在了 Bundle 中返回给 VAMS。

    最终, VAMS 调用原生 AM 的 startActivity 向真正的 AMS 发送替换成 StubActivity 的伪造 Intent。

       private void realStartActivitiesLocked(IBinder resultTo, Intent[] intents, String[] resolvedTypes, Bundle options) {
            Class<?>[] types = IActivityManager.startActivities.paramList();
            Object[] args = new Object[types.length];
            if (types[0] == IApplicationThread.TYPE) {
                args[0] = ActivityThread.getApplicationThread.call(VirtualCore.mainThread());
            }
            int pkgIndex = ArrayUtils.protoIndexOf(types, String.class);
            int intentsIndex = ArrayUtils.protoIndexOf(types, Intent[].class);
            int resultToIndex = ArrayUtils.protoIndexOf(types, IBinder.class, 2);
            int optionsIndex = ArrayUtils.protoIndexOf(types, Bundle.class);
            int resolvedTypesIndex = intentsIndex + 1;
            if (pkgIndex != -1) {
                args[pkgIndex] = VirtualCore.get().getHostPkg();
            }
            args[intentsIndex] = intents;
            args[resultToIndex] = resultTo;
            args[resolvedTypesIndex] = resolvedTypes;
            args[optionsIndex] = options;
            ClassUtils.fixArgs(types, args);
           //在这里进行伪造
            IActivityManager.startActivities.call(ActivityManagerNative.getDefault.call(),
                    (Object[]) args);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    恢复原 Intent 重定向到原 Activity

    当 AMS 收到伪装的 Intent 后,就会找到 StubActivity,这时流程回到 VA 里的主线程中的消息队列中。

    Hook 过程就是用我们自己的 Handler 替换 android.os.Handler.mCallback 因为主线程在这里分发一些操作:

    HCallbackStub.java

    @Override
    public void inject() throws Throwable {
        otherCallback = getHCallback();
        mirror.android.os.Handler.mCallback.set(getH(), this);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    handlerMessage 判断是 LAUNCH_ACTIVITY Action 后直接调用了 handlerLaunchActivity 方法,和原版其实很像。

    private boolean handleLaunchActivity(Message msg) {
        Object r = msg.obj;
        Intent stubIntent = ActivityThread.ActivityClientRecord.intent.get(r);
        //获取原版Intent信息
        StubActivityRecord saveInstance = new StubActivityRecord(stubIntent);
        if (saveInstance.intent == null) {
            return true;
        }
        //原版Intent
        Intent intent = saveInstance.intent;
        ComponentName caller = saveInstance.caller;
        IBinder token = ActivityThread.ActivityClientRecord.token.get(r);
        ActivityInfo info = saveInstance.info;
        //如果token还没初始化,代表App刚刚启动第一个组件
        if (VClientImpl.get().getToken() == null) {
            InstalledAppInfo installedAppInfo = VirtualCore.get().getInstalledAppInfo(info.packageName, 0);
            if(installedAppInfo == null){
                return true;
            }
            VActivityManager.get().processRestarted(info.packageName, info.processName, saveInstance.userId);
            getH().sendMessageAtFrontOfQueue(Message.obtain(msg));
            return false;
        }
        //如果AooBindData为空,则App信息不明
        if (!VClientImpl.get().isBound()) {
            VClientImpl.get().bindApplication(info.packageName, info.processName);
            getH().sendMessageAtFrontOfQueue(Message.obtain(msg));
            return false;
        }
        //获取TaskId
        int taskId = IActivityManager.getTaskForActivity.call(
                ActivityManagerNative.getDefault.call(),
                token,
                false
        );
         // 1.将 ActivityRecorder 加入 mActivities 2.通知服务端 VAMS Activity 创建完成
        VActivityManager.get().onActivityCreate(ComponentUtils.toComponentName(info), caller, token, info, intent, ComponentUtils.getTaskAffinity(info), taskId, info.launchMode, info.flags);
        ClassLoader appClassLoader = VClientImpl.get().getClassLoader(info.applicationInfo);
        intent.setExtrasClassLoader(appClassLoader);
       // 将 Host Stub Activity Intent 替换为原版 Intent
        ActivityThread.ActivityClientRecord.intent.set(r, intent);
       // 将 Host Stub Activity Intent 替换为原版 Intent
        ActivityThread.ActivityClientRecord.activityInfo.set(r, info);
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    如果这个 Activity 是这个 Apk 启动的第一个组件,则需要 bindApplication 初始化 Application 操作:

    private void bindApplicationNoCheck(String packageName, String processName, ConditionVariable lock) {
        VDeviceInfo deviceInfo = getDeviceInfo();
        if (processName == null) {
            processName = packageName;
        }
        mTempLock = lock;
        try {
            //设置未捕获异常的Callback
            setupUncaughtHandler();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        try {
            //修复Provider信息
            fixInstalledProviders();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        mirror.android.os.Build.SERIAL.set(deviceInfo.serial);
        mirror.android.os.Build.DEVICE.set(Build.DEVICE.replace(" ", "_"));
        ActivityThread.mInitialApplication.set(
                VirtualCore.mainThread(),
                null
        );
        //从VPMS获取aps信息
        AppBindData data = new AppBindData();
        InstalledAppInfo info = VirtualCore.get().getInstalledAppInfo(packageName, 0);
        if (info == null) {
            new Exception("App not exist!").printStackTrace();
            Process.killProcess(0);
            System.exit(0);
        }
       
        data.appInfo = VPackageManager.get().getApplicationInfo(packageName, 0, getUserId(vuid));
        data.processName = processName;
        data.providers = VPackageManager.get().queryContentProviders(processName, getVUid(), PackageManager.GET_META_DATA);
        Log.i(TAG, "Binding application " + data.appInfo.packageName + " (" + data.processName + ")");
        mBoundApplication = data;
      	//主要设置进程的名字
        VirtualRuntime.setupRuntime(data.processName, data.appInfo);
        int targetSdkVersion = data.appInfo.targetSdkVersion;
        if (targetSdkVersion < Build.VERSION_CODES.GINGERBREAD) {
            StrictMode.ThreadPolicy newPolicy = new StrictMode.ThreadPolicy.Builder(StrictMode.getThreadPolicy()).permitNetwork().build();
            StrictMode.setThreadPolicy(newPolicy);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
            mirror.android.os.Message.updateCheckRecycle.call(targetSdkVersion);
        }
        if (VASettings.ENABLE_IO_REDIRECT) {
          //IO重定向
            startIOUniformer();
        }
        //hook native函数
        NativeEngine.launchEngine();
        Object mainThread = VirtualCore.mainThread();
       //准备dex列表
        NativeEngine.startDexOverride();
    	//获得子pkg的Context前提是必须在系统中安装的
        Context context = createPackageContext(data.appInfo.packageName);
    	//设置虚拟机系统环境,临时文件夹codeCacheDir
        System.setProperty("java.io.tmpdir", context.getCacheDir().getAbsolutePath());
        //oat的cache目录
        File codeCacheDir;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            codeCacheDir = context.getCodeCacheDir();
        } else {
            codeCacheDir = context.getCacheDir();
        }
    	//硬件加速的cache目录
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            if (HardwareRenderer.setupDiskCache != null) {
                HardwareRenderer.setupDiskCache.call(codeCacheDir);
            }
        } else {
            if (ThreadedRenderer.setupDiskCache != null) {
                ThreadedRenderer.setupDiskCache.call(codeCacheDir);
            }
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (RenderScriptCacheDir.setupDiskCache != null) {
                RenderScriptCacheDir.setupDiskCache.call(codeCacheDir);
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            if (RenderScript.setupDiskCache != null) {
                RenderScript.setupDiskCache.call(codeCacheDir);
            }
        }
        //修复子App中ActivityThread.AppBinderData的参数,因为之前用的是在host程序中注册的Stub的信息
        Object boundApp = fixBoundApp(mBoundApplication);
        mBoundApplication.info = ContextImpl.mPackageInfo.get(context);
        mirror.android.app.ActivityThread.AppBindData.info.set(boundApp, data.info);
        //同样修复targetSdkVersion原来也是和Host程序一样的
        VMRuntime.setTargetSdkVersion.call(VMRuntime.getRuntime.call(), data.appInfo.targetSdkVersion);
    
        Configuration configuration = context.getResources().getConfiguration();
        Object compatInfo = CompatibilityInfo.ctor.newInstance(data.appInfo, configuration.screenLayout, configuration.smallestScreenWidthDp, false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                DisplayAdjustments.setCompatibilityInfo.call(ContextImplKitkat.mDisplayAdjustments.get(context), compatInfo);
            }
            DisplayAdjustments.setCompatibilityInfo.call(LoadedApkKitkat.mDisplayAdjustments.get(mBoundApplication.info), compatInfo);
        } else {
            CompatibilityInfoHolder.set.call(LoadedApkICS.mCompatibilityInfo.get(mBoundApplication.info), compatInfo);
        }
    
        boolean conflict = SpecialComponentList.isConflictingInstrumentation(packageName);
        if (!conflict) {
            InvocationStubManager.getInstance().checkEnv(AppInstrumentation.class);
        }
        //开始构建子程序包的Application对象,并且替换原来通过Host Stub生成的mInitialApplication
        mInitialApplication = LoadedApk.makeApplication.call(data.info, false, null);
        mirror.android.app.ActivityThread.mInitialApplication.set(mainThread, mInitialApplication);
        ContextFixer.fixContext(mInitialApplication);
        if (Build.VERSION.SDK_INT >= 24 && "com.tencent.mm:recovery".equals(processName)) {
            fixWeChatRecovery(mInitialApplication);
        }
        if (data.providers != null) {
            //注册Providers
            installContentProviders(mInitialApplication, data.providers);
        }
        // 初始化锁开,异步调用的初始化函数可以返回了
        if (lock != null) {
            lock.open();
            mTempLock = null;
        }
        VirtualCore.get().getComponentDelegate().beforeApplicationCreate(mInitialApplication);
        try {
             // 调用 Application.onCreate
            mInstrumentation.callApplicationOnCreate(mInitialApplication);
            InvocationStubManager.getInstance().checkEnv(HCallbackStub.class);
            if (conflict) {
                InvocationStubManager.getInstance().checkEnv(AppInstrumentation.class);
            }
            Application createdApp = ActivityThread.mInitialApplication.get(mainThread);
            if (createdApp != null) {
                mInitialApplication = createdApp;
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(mInitialApplication, e)) {
                throw new RuntimeException(
                        "Unable to create application " + mInitialApplication.getClass().getName()
                                + ": " + e.toString(), e);
            }
        }
        VActivityManager.get().appDoneExecuting();
        VirtualCore.get().getComponentDelegate().afterApplicationCreate(mInitialApplication);
    }
    
     private void setupUncaughtHandler() {
            ThreadGroup root = Thread.currentThread().getThreadGroup();
            while (root.getParent() != null) {
                root = root.getParent();
            }
            ThreadGroup newRoot = new RootThreadGroup(root);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                final List<ThreadGroup> groups = mirror.java.lang.ThreadGroup.groups.get(root);
                //noinspection SynchronizationOnLocalVariableOrMethodParameter
                synchronized (groups) {
                    List<ThreadGroup> newGroups = new ArrayList<>(groups);
                    newGroups.remove(newRoot);
                    mirror.java.lang.ThreadGroup.groups.set(newRoot, newGroups);
                    groups.clear();
                    groups.add(newRoot);
                    mirror.java.lang.ThreadGroup.groups.set(root, groups);
                    for (ThreadGroup group : newGroups) {
                        if (group == newRoot) continue;
                        mirror.java.lang.ThreadGroup.parent.set(group, newRoot);
                    }
                }
            } else {
                final ThreadGroup[] groups = ThreadGroupN.groups.get(root);
                //noinspection SynchronizationOnLocalVariableOrMethodParameter
                synchronized (groups) {
                    ThreadGroup[] newGroups = groups.clone();
                    ThreadGroupN.groups.set(newRoot, newGroups);
                    ThreadGroupN.groups.set(root, new ThreadGroup[]{newRoot});
                    for (Object group : newGroups) {
                        if (group == newRoot) continue;
                        ThreadGroupN.parent.set(group, newRoot);
                    }
                    ThreadGroupN.ngroups.set(root, 1);
                }
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185

    bindApplication 主要做了以下几个事情:

    1. 从 VPMS 获取 APK 的信息,根据设置控制 Dex 优化的开关。
    2. 调用 mirror.android.os.Process.setArgV0.call(processName); 设置进程的名称,如果不设置则还是 p0 p1 这样。
    3. 做 nativeHook 主要 Hook 一些 native 的函数,主要是一些 IO 函数,包括文件访问重定向等等。
    4. 准备一些 cache 临时文件夹。
    5. 设置 AppBinderData,AppBinderData 内部包含了 ApplicationInfo 和 provider 信息等重要的 apk 信息。可以理解为 framework 所需要的关键数据结构。
    6. 安装 ContentProvider
    7. 初始化用户的 Application 对象,并通过 Instrumentation 调用其 onCreate,代表着 Client App 的生命周期正式开始。

    最后成功从 StubActivity Intent 还原出来的原版 Intent 被继续交给原生的 AM:

        ActivityThread.ActivityClientRecord.intent.set(r, intent);
       // 将 Host Stub Activity Intent 替换为原版 Intent
        ActivityThread.ActivityClientRecord.activityInfo.set(r, info);
    
    • 1
    • 2
    • 3

    最后一个 Hook 点在 Instrumentation.callActivityOnCreate:

    因为 AMS 实际上启动的是 StubActivity 的关系,真正的 Activity 的一些信息还不是其真正的信息,比如主题之类的,所以需要在这个时机修复一下,选择这个时间修复的原因也是因为 Activity 已经被 new 出来了,而且资源已经准备完毕。
    AppInstrumentation.java

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        if (icicle != null) {
            BundleCompat.clearParcelledData(icicle);
        }
        VirtualCore.get().getComponentDelegate().beforeActivityCreate(activity);
        IBinder token = mirror.android.app.Activity.mToken.get(activity);
        ActivityClientRecord r = VActivityManager.get().getActivityRecord(token);
       	//替换Activity对象
        if (r != null) {
            r.activity = activity;
        }
        ContextFixer.fixContext(activity);
        ActivityFixer.fixActivity(activity);
        ActivityInfo info = null;
        if (r != null) {
            info = r.info;
        }
    	//设置主题和屏幕纵横控制
        if (info != null) {
            if (info.theme != 0) {
                activity.setTheme(info.theme);
            }
            if (activity.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
                    && info.screenOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
                activity.setRequestedOrientation(info.screenOrientation);
            }
        }
        super.callActivityOnCreate(activity, icicle);
        VirtualCore.get().getComponentDelegate().afterActivityCreate(activity);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    启动插件 Service

    原生Activity
    public void startActivity(Intent intent) {
        mBase.startActivity(intent);
    }
    
    • 1
    • 2
    • 3

    mBase 是 ContextImpl,所以调用到 ContextImpl.startService():

     @Override
        public ComponentName startService(Intent service) {
            warnIfCallingFromSystemProcess();
            return startServiceCommon(service, mUser);
        }
        private ComponentName startServiceCommon(Intent service, UserHandle user) {
            try {
                validateServiceIntent(service);
                service.prepareToLeaveProcess(this);
                ComponentName cn = ActivityManagerNative.getDefault().startService(
                    mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                                getContentResolver()), getOpPackageName(), user.getIdentifier());
                if (cn != null) {
                    if (cn.getPackageName().equals("!")) {
                        throw new SecurityException(
                                "Not allowed to start service " + service
                                + " without permission " + cn.getClassName());
                    } else if (cn.getPackageName().equals("!!")) {
                        throw new SecurityException(
                                "Unable to start service " + service
                                + ": " + cn.getClassName());
                    }
                }
                return cn;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    Client 的流程最后到 ActivityManagerNative.startService():

    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
                String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IActivityManager.descriptor);
            data.writeStrongBinder(caller != null ? caller.asBinder() : null);
            data.writeString(callingPackage);
            intent.writeToParcel(data, 0);
            data.writeString(resolvedType);
            data.writeStrongBinder(resultTo);
            data.writeString(resultWho);
            data.writeInt(requestCode);
            data.writeInt(startFlags);
            if (profilerInfo != null) {
                data.writeInt(1);
                profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
            } else {
                data.writeInt(0);
            }
            if (options != null) {
                data.writeInt(1);
                options.writeToParcel(data, 0);
            } else {
                data.writeInt(0);
            }
            // 远程调用 AMS
            mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
            reply.readException();
            int result = reply.readInt();
            reply.recycle();
            data.recycle();
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    逻辑再一次转移到远程的 AMS 中,然后我们先忽略 AMS 中的一堆逻辑,最后 AMS 调用到这:

    private final void realStartServiceLocked(ServiceRecord r,
                                              ProcessRecord app, boolean execInFg) throws RemoteException {
        app.thread.scheduleCreateService(r, r.serviceInfo,
                                         mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                                         app.repProcState);
        sendServiceArgsLocked(r, execInFg, true);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里的 ProcessRecoder.thread 是 AMS 持有的 Client App 的 IBinder 句柄,通过他可以远程调用到 Client App 的 ApplicationThread 中的 scheduleCreateService 方法:

    public final void scheduleCreateService(IBinder token,
                    ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
                updateProcessState(processState, false);
                CreateServiceData s = new CreateServiceData();
                s.token = token;
                s.info = info;
                s.compatInfo = compatInfo;
    
                sendMessage(H.CREATE_SERVICE, s);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这里大家可能发现了,Intent 在 AMS 绕了一圈又回来了,事实上 AMS 在其中好像没有发挥什么作用,其实在外部环境 AMS 还是很重要的,但是在 VA 中,AMS 在 Service 调度中其实没有发挥什么作用。原因有以下几点:

    1. 首先 VA 内部的插件 Service 没有比较暴露给外部 App 调用,所以让 AMS 知晓 Service 的意义不大。
      其次和 Activity 必须有个 StubActivity 让 AMS 持有不一样,Service 生命周期和功能都极其简单,并且没有界面,没有交互,换句话说 Service 和其他 Framework Service(例如 WMS) 没有任何关系,所以其实并不需要 AMS 这一步存在。

    2. 那么综上所诉,为了启动插件 Service 我们其实可以绕过 AMS,直接调用 ApplicationThread 中的 scheduleCreateService 方法,Service 的会话储存交给 VAMS 就行。

    startService 的实现

    和startActivity一样,首先是Hook

    static class StartService extends MethodProxy {
    
        @Override
        public String getMethodName() {
            return "startService";
        }
    
        @Override
        public Object call(Object who, Method method, Object... args) throws Throwable {
            IInterface appThread = (IInterface) args[0];
            Intent service = (Intent) args[1];
            String resolvedType = (String) args[2];
            if (service.getComponent() != null
                    && getHostPkg().equals(service.getComponent().getPackageName())) {
                // for server process
                return method.invoke(who, args);
            }
            int userId = VUserHandle.myUserId();
            //如果是内部请求,获取原理的Service
            if (service.getBooleanExtra("_VA_|_from_inner_", false)) {
                userId = service.getIntExtra("_VA_|_user_id_", userId);
                service = service.getParcelableExtra("_VA_|_intent_");
            } else {
                if (isServerProcess()) {
                    userId = service.getIntExtra("_VA_|_user_id_", VUserHandle.USER_NULL);
                }
            }
            service.setDataAndType(service.getData(), resolvedType);
            ServiceInfo serviceInfo = VirtualCore.get().resolveServiceInfo(service, VUserHandle.myUserId());
            if (serviceInfo != null) {
               	//远程调用VAMS.startService
                return VActivityManager.get().startService(appThread, service, resolvedType, userId);
            }
            return method.invoke(who, args);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    和 startActivity 一样将真正业务交给 VAMS.startService():

    public ComponentName startService(IBinder caller, Intent service, String resolvedType, int userId) {
        synchronized (this) {
            return startServiceCommon(service, true, userId);
        }
    }
    
    private ComponentName startServiceCommon(Intent service,
                                             boolean scheduleServiceArgs, int userId) {
        ServiceInfo serviceInfo = resolveServiceInfo(service, userId);
        if (serviceInfo == null) {
            return null;
        }
        ProcessRecord targetApp = startProcessIfNeedLocked(ComponentUtils.getProcessName(serviceInfo),
                userId,
                serviceInfo.packageName);
    
        if (targetApp == null) {
            VLog.e(TAG, "Unable to start new Process for : " + ComponentUtils.toComponentName(serviceInfo));
            return null;
        }
        IInterface appThread = targetApp.appThread;
        ServiceRecord r = findRecordLocked(userId, serviceInfo);
        if (r == null) {
            r = new ServiceRecord();
            r.startId = 0;
            r.activeSince = SystemClock.elapsedRealtime();
            r.process = targetApp;
            r.serviceInfo = serviceInfo;
            try {
                  // 调用 ApplicationThread.scheduleCreateService 直接创建 Service
                IApplicationThreadCompat.scheduleCreateService(appThread, r, r.serviceInfo, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            // 将 ServiceRecorder 推入 history
            addRecord(r);
        }
        
        r.lastActivityTime = SystemClock.uptimeMillis();
        if (scheduleServiceArgs) {
            r.startId++;
            boolean taskRemoved = serviceInfo.applicationInfo != null
                    && serviceInfo.applicationInfo.targetSdkVersion < Build.VERSION_CODES.ECLAIR;
            try {
                IApplicationThreadCompat.scheduleServiceArgs(appThread, r, taskRemoved, r.startId, 0, service);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return ComponentUtils.toComponentName(serviceInfo);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    这里主要做了以下几个工作:

    • 和 Activity 创建的时候一样,调用 startProcessIfNeedLocked 检查 Application 是否初始化,没有则开始初始化 Application 流程。
    • 准备 ServiceRecord 和 ServiceInfo。
    • 如果 service 还没有创建,则直接调用 ApplicationThread.scheduleCreateService 创建 Service,可以看出这里直接跳过了 AMS。
    • 将 ServiceRecord 记录到 Service 列表,等待 bindService,如果是通过 bindService 自动创建的 Service,在创建 Service 完成后会进入 bindService 流程。
    • 同样的 bindService 也是直接调用系统的 ApplicationThread.scheduleBindService

    BroadcastReceiver

    VA 静态广播注册

    VAService 的启动时机实在 BinderProvider.onCreate():

    public boolean onCreate() {
    ...
        VAppManagerService.get().scanApps();
    ...
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    @Override
    public void scanApps() {
        if (mBooting) {
            return;
        }
        synchronized (this) {
            mBooting = true;
            mPersistenceLayer.read();
            PrivilegeAppOptimizer.get().performOptimizeAllApps();
            mBooting = false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    PersistenceLayer.read()

    public void read() {
        File file = mPersistenceFile;
        Parcel p = Parcel.obtain();
        try {
            FileInputStream fis = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()];
            int len = fis.read(bytes);
            fis.close();
            if (len != bytes.length) {
                throw new IOException("Unable to read Persistence file.");
            }
            p.unmarshall(bytes, 0, bytes.length);
            p.setDataPosition(0);
            if (!verifyMagic(p)) {
                onPersistenceFileDamage();
                throw new IOException("Invalid persistence file.");
            }
            int fileVersion = p.readInt();
            int currentVersion = getCurrentVersion();
            if (fileVersion != getCurrentVersion()) {
                if (!onVersionConflict(fileVersion, currentVersion)) {
                    throw new IOException("Unable to process the bad version persistence file.");
                }
            }
            readPersistenceData(p);
        } catch (Exception e) {
            if (!(e instanceof FileNotFoundException)) {
                e.printStackTrace();
            }
        } finally {
            p.recycle();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    PackagePersistenceLayer.readPersistenceData()

    public void readPersistenceData(Parcel p) {
        int count = p.readInt();
        while (count-- > 0) {
            PackageSetting setting = new PackageSetting(p);
            mService.loadPackage(setting);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    VAppManagerService.java

    synchronized void loadPackage(PackageSetting setting) {
        if (!loadPackageInnerLocked(setting)) {
            cleanUpResidualFiles(setting);
        }
    }
    
    private boolean loadPackageInnerLocked(PackageSetting ps) {
        if (ps.dependSystem) {
            if (!VirtualCore.get().isOutsideInstalled(ps.packageName)) {
                return false;
            }
        }
        File cacheFile = VEnvironment.getPackageCacheFile(ps.packageName);
        VPackage pkg = null;
        try {
            pkg = PackageParserEx.readPackageCache(ps.packageName);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        if (pkg == null || pkg.packageName == null) {
            return false;
        }
        chmodPackageDictionary(cacheFile);
        PackageCacheManager.put(pkg, ps);
        BroadcastSystem.get().startApp(pkg);
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    BroadcastSystem.startApp(pkg)

    //静态 Receiver的注册
    public void startApp(VPackage p) {
        PackageSetting setting = (PackageSetting) p.mExtras;
        // 遍历 Client App的Receiver
        for (VPackage.ActivityComponent receiver : p.receivers) {
            ActivityInfo info = receiver.info;
           //得到对应Client App在VAService中的
            List<BroadcastReceiver> receivers = mReceivers.get(p.packageName);
            if (receivers == null) {
                receivers = new ArrayList<>();
                mReceivers.put(p.packageName, receivers);
            }
            //注册显示意图
            String componentAction = String.format("_VA_%s_%s", info.packageName, info.name);
            IntentFilter componentFilter = new IntentFilter(componentAction);
            BroadcastReceiver r = new StaticBroadcastReceiver(setting.appId, info, componentFilter);
            mContext.registerReceiver(r, componentFilter, null, mScheduler);
          	//推入记录
            receivers.add(r);
    		//遍历注册隐式意图
            for (VPackage.ActivityIntentInfo ci : receiver.intents) {
                IntentFilter cloneFilter = new IntentFilter(ci.filter);
                SpecialComponentList.protectIntentFilter(cloneFilter);
                r = new StaticBroadcastReceiver(setting.appId, info, cloneFilter);
                mContext.registerReceiver(r, cloneFilter, null, mScheduler);
                //推入记录
                receivers.add(r);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    这里对每个 Client App 静态 Receiver 的信息使用统一的代理 StaticBroadcastReceiver 注册。

    1. 首先注册 Receiver 的显式意图,每个显式意图被重定向成格式为 “VA_PKGNAME_CLASSNAME”的 componentAction 这么做的理由实际是真正注册是 VAService 进程空间的 StaticBroadcastReceiver 代理 Receiver,而不是 VA Client App 进程空间,所以直接注册 VA Client App 中的真实类名是没有意义的,这样通过 VAService 代理然后再从 Intent 中取出的 “VA_PKGNAME_CLASSNAME”到 VA Client 中找到真正的 Receiver,这个逻辑和 Activity 的处理有些相似。
    2. 然后就是遍历 Intent-Filter,每个 Intent-Filter 注册一个 StaticBroadcastReceiver 代理。

    这样我们的代理 Receiver 注册完毕了。

    下面当代理 Receiver 收到广播时:

    public void onReceive(Context context, Intent intent) {
        if (mApp.isBooting()) {
            return;
        }
        if ((intent.getFlags() & FLAG_RECEIVER_REGISTERED_ONLY) != 0 || isInitialStickyBroadcast()) {
            return;
        }
        String privilegePkg = intent.getStringExtra("_VA_|_privilege_pkg_");
        if (privilegePkg != null && !info.packageName.equals(privilegePkg)) {
            return;
        }
        PendingResult result = goAsync();
        if (!mAMS.handleStaticBroadcast(appId, info, intent, new PendingResultData(result))) {
            result.finish();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    boolean handleStaticBroadcast(int appId, ActivityInfo info, Intent intent,
                                  PendingResultData result) {
        // 取出真正的目标Intent
        Intent realIntent = intent.getParcelableExtra("_VA_|_intent_");
    	//取出真正的目标 component
        ComponentName component = intent.getParcelableExtra("_VA_|_component_");
    	//用户id
        int userId = intent.getIntExtra("_VA_|_user_id_", VUserHandle.USER_NULL);
        if (realIntent == null) {
            return false;
        }
        if (userId < 0) {
            VLog.w(TAG, "Sent a broadcast without userId " + realIntent);
            return false;
        }
        int vuid = VUserHandle.getUid(userId, appId);
        return handleUserBroadcast(vuid, info, component, realIntent, result);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这里取出了真正的 Intent,和 Activity 类似,但是和 Activity 处理不同的是现在的逻辑还在 VAService 中:

    handleUserBroadcast()

    private boolean handleUserBroadcast(int vuid, ActivityInfo info, ComponentName component, Intent realIntent, PendingResultData result) {
        if (component != null && !ComponentUtils.toComponentName(info).equals(component)) {
            // Verify the component.
            return false;
        }
        String originAction = SpecialComponentList.unprotectAction(realIntent.getAction());
        if (originAction != null) {
            // restore to origin action.
            realIntent.setAction(originAction);
        }
        handleStaticBroadcastAsUser(vuid, info, realIntent, result);
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    handleStaticBroadcastAsUser()

    private void handleStaticBroadcastAsUser(int vuid, ActivityInfo info, Intent intent,
                                             PendingResultData result) {
        synchronized (this) {
            ProcessRecord r = findProcessLocked(info.processName, vuid);
            if (BROADCAST_NOT_STARTED_PKG && r == null) {
                r = startProcessIfNeedLocked(info.processName, getUserId(vuid), info.packageName);
            }
            if (r != null && r.appThread != null) {
                performScheduleReceiver(r.client, vuid, info, intent,
                        result);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    performScheduleReceiver()

    private void performScheduleReceiver(IVClient client, int vuid, ActivityInfo info, Intent intent,
                                         PendingResultData result) {
    
        ComponentName componentName = ComponentUtils.toComponentName(info);
        BroadcastSystem.get().broadcastSent(vuid, info, result);
        try {
            // 远程调用 client app 的 scheduleReceiver
            client.scheduleReceiver(info.processName, componentName, intent, result);
        } catch (Throwable e) {
            if (result != null) {
                result.finish();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    public final class VClientImpl extends IVClient.Stub
    
    • 1

    client.scheduleReceiver() 这时候远程调用了 Client App 的 scheduleReceiver。这样我们回到了 Client App 进程空间:

    public void scheduleReceiver(String processName, ComponentName component, Intent intent, PendingResultData resultData) {
        ReceiverData receiverData = new ReceiverData();
        receiverData.resultData = resultData;
        receiverData.intent = intent;
        receiverData.component = component;
        receiverData.processName = processName;
        sendMessage(RECEIVER, receiverData);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    跟到消息队列中

    private class H extends Handler {
    
        private H() {
            super(Looper.getMainLooper());
        }
    
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case NEW_INTENT: {
                    handleNewIntent((NewIntentData) msg.obj);
                }
                break;
                case RECEIVER: {
                    handleReceiver((ReceiverData) msg.obj);
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    handleReceiver()

    private void handleReceiver(ReceiverData data) {
        BroadcastReceiver.PendingResult result = data.resultData.build();
        try {
            //检测Application是否初始化,没有则初始化
            if (!isBound()) {
                bindApplication(data.component.getPackageName(), data.processName);
            }
            //获取Receiver的Context,这个context是一个ReceiverRestrictedContext实例,它有两个主要函数被禁掉:registerReceiver()和 bindService()。这两个函数在BroadcastReceiver.onReceive()不允许调用。每次Receiver处理一个广播,传递进来的context都是一个新的实例。
            Context context = mInitialApplication.getBaseContext();
            Context receiverContext = ContextImpl.getReceiverRestrictedContext.call(context);
            String className = data.component.getClassName();
           // 实例化目标 Receiver
            BroadcastReceiver receiver = (BroadcastReceiver) context.getClassLoader().loadClass(className).newInstance();
            mirror.android.content.BroadcastReceiver.setPendingResult.call(receiver, result);
            data.intent.setExtrasClassLoader(context.getClassLoader());
            if (data.intent.getComponent() == null) {
                data.intent.setComponent(data.component);
            }
            //手动调用onCreate
            receiver.onReceive(receiverContext, data.intent);
          	//通知Pending结束
            if (mirror.android.content.BroadcastReceiver.getPendingResult.call(receiver) != null) {
                result.finish();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(
                    "Unable to start receiver " + data.component
                            + ": " + e.toString(), e);
        }
        //远程通知Vaservice广播已经收到
        VActivityManager.get().broadcastFinish(data.resultData);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    new 了真正的 Receiver 然后调用 onCreate 而已

    BroadcastSystem.broadcastFinish()

    broadCast 发送有个超时机制

    void broadcastFinish(PendingResultData res) {
        synchronized (mBroadcastRecords) {
            BroadcastRecord record = mBroadcastRecords.remove(res.mToken);
            if (record == null) {
                VLog.e(TAG, "Unable to find the BroadcastRecord by token: " + res.mToken);
            }
        }
        mTimeoutHandler.removeMessages(0, res.mToken);
        res.finish();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    private final class TimeoutHandler extends Handler {
    
        TimeoutHandler(Looper looper) {
            super(looper);
        }
    
        @Override
        public void handleMessage(Message msg) {
            IBinder token = (IBinder) msg.obj;
            BroadcastRecord r = mBroadcastRecords.remove(token);
            if (r != null) {
                VLog.w(TAG, "Broadcast timeout, cancel to dispatch it.");
                r.pendingResult.finish();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这里如果广播超时则会通知 PendingResult 结束,告诉发送方广播结束了。

    发送广播的处理
    static class BroadcastIntent extends MethodProxy {
    
        @Override
        public String getMethodName() {
            return "broadcastIntent";
        }
    
        @Override
        public Object call(Object who, Method method, Object... args) throws Throwable {
            Intent intent = (Intent) args[1];
            String type = (String) args[2];
            intent.setDataAndType(intent.getData(), type);
            if (VirtualCore.get().getComponentDelegate() != null) {
                VirtualCore.get().getComponentDelegate().onSendBroadcast(intent);
            }
            Intent newIntent = handleIntent(intent);
            if (newIntent != null) {
                args[1] = newIntent;
            } else {
                return 0;
            }
    
            if (args[7] instanceof String || args[7] instanceof String[]) {
                // clear the permission
                args[7] = null;
            }
            return method.invoke(who, args);
        }
    
    
        private Intent handleIntent(final Intent intent) {
            final String action = intent.getAction();
            if ("android.intent.action.CREATE_SHORTCUT".equals(action)
                    || "com.android.launcher.action.INSTALL_SHORTCUT".equals(action)) {
    
                return VASettings.ENABLE_INNER_SHORTCUT ? handleInstallShortcutIntent(intent) : null;
    
            } else if ("com.android.launcher.action.UNINSTALL_SHORTCUT".equals(action)) {
    
                handleUninstallShortcutIntent(intent);
    
            } else if (BadgerManager.handleBadger(intent)) {
                return null;
            } else {
                return ComponentUtils.redirectBroadcastIntent(intent, VUserHandle.myUserId());
            }
            return intent;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 这里拦截了创建快捷图标的 Intent,这是一个发给 Launcher 的隐式广播,VA 把这个请求拦截下来因为如果不拦截这个快捷方式就会指向外部的 App,并且如果外部 App 没有安装,此广播也不会发生作用。VA 把这个广播换成了自己的逻辑。
    • 注意 ComponentUtils.redirectBroadcastIntent(), 类似 Activity 用代理 Intent 包裹真正的 Intent:

    ComponentUtils.redirectBroadcastIntent()

    public static Intent redirectBroadcastIntent(Intent intent, int userId) {
        Intent newIntent = intent.cloneFilter();
        newIntent.setComponent(null);
        newIntent.setPackage(null);
        ComponentName component = intent.getComponent();
        String pkg = intent.getPackage();
        if (component != null) {
            newIntent.putExtra("_VA_|_user_id_", userId);
         	//显示意图被重定向成_VA_PKGNAME_CLASSNAME 的格式,与前面注册的时候对应
            newIntent.setAction(String.format("_VA_%s_%s", component.getPackageName(), component.getClassName()));
            newIntent.putExtra("_VA_|_component_", component);
            newIntent.putExtra("_VA_|_intent_", new Intent(intent));
        } else if (pkg != null) {
            newIntent.putExtra("_VA_|_user_id_", userId);
            newIntent.putExtra("_VA_|_creator_", pkg);
            newIntent.putExtra("_VA_|_intent_", new Intent(intent));
            String protectedAction = SpecialComponentList.protectAction(intent.getAction());
            if (protectedAction != null) {
                newIntent.setAction(protectedAction);
            }
        } else {
            newIntent.putExtra("_VA_|_user_id_", userId);
            newIntent.putExtra("_VA_|_intent_", new Intent(intent));
            String protectedAction = SpecialComponentList.protectAction(intent.getAction());
            if (protectedAction != null) {
                newIntent.setAction(protectedAction);
            }
        }
        return newIntent;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    ContentProvider

    Provider 注册

    Activity 启动的时候会检查 Application 是否初始化,会调用 bindApplication,里面执行了安装 Provider 的方法:

    private void installContentProviders(Context app, List<ProviderInfo> providers) {
        long origId = Binder.clearCallingIdentity();
        Object mainThread = VirtualCore.mainThread();
        try {
            for (ProviderInfo cpi : providers) {
                try {
                    ActivityThread.installProvider(mainThread, app, cpi, null);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里很简单,调用 ActivityThread.installProvider() 注册就这么完成了。

    但是,仔细一想事情没那么简单,按照这个逻辑 ContentProvider 是在 Application 启动的时候注册的,那么如果 Application 没有启动,那么自然就没有注册了,这样的话其他 App 怎么找到 Provider 呢?

    Activity 是因为有在 VA 的 Menifest 里注册的 StubActivity,这样启动 StubActivity 自然就启动了在“:p(n)”进程。那么对应的,VA 用了 StubContentProvider 么?确实是有的。

    但是请不要误会了,这个注册在 “p(n)”进程的 StubContentProvider(继承自 StubContentProvider 的 C1,C2,Cn……) 并不是 StubActivity 那样的为了给插件 Provider 占坑的 Stub 组件。

    StubContentProvider 的真正目的是为了让 AMS 通过 system_process 带起 “p(n)”进程,然后 VAMS 用过远程调用 StubProvider.call() 回插件 IClient 的 IBinder 句柄给 VAMS 持有。这样 VAMS 就可以远程调用插件进程 “p(n)”中的方法了。

    事实上在前面第二张 App 启动时就有说过相关内容,但是为了避免大家误解还是有必要重复一下。

    public class StubContentProvider extends ContentProvider {
    
       @Override
       public boolean onCreate() {
          return true;
       }
    
       @Override
       public Bundle call(String method, String arg, Bundle extras) {
          if ("_VA_|_init_process_".equals(method)) {
             return initProcess(extras);
          }
          return null;
       }
    
       private Bundle initProcess(Bundle extras) {
          ConditionVariable lock = VirtualCore.get().getInitLock();
          if (lock != null) {
             lock.block();
          }
          IBinder token = BundleCompat.getBinder(extras,"_VA_|_binder_");
          int vuid = extras.getInt("_VA_|_vuid_");
          VClientImpl client = VClientImpl.get();
          client.initProcess(token, vuid);
          Bundle res = new Bundle();
          BundleCompat.putBinder(res, "_VA_|_client_", client.asBinder());
          res.putInt("_VA_|_pid_", Process.myPid());
          return res;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    getContentProvider

    依旧Hook了GetContentProvider方法

    static class GetContentProvider extends MethodProxy {
    
        @Override
        public String getMethodName() {
            return "getContentProvider";
        }
    
        @Override
        public Object call(Object who, Method method, Object... args) throws Throwable {
            int nameIdx = getProviderNameIndex();
            String name = (String) args[nameIdx];
            int userId = VUserHandle.myUserId();
            // 远程调用VPMS从VPackage拿到ProviderInfo
            ProviderInfo info = VPackageManager.get().resolveContentProvider(name, 0, userId);
            //如果为空则说明目标App未启动
            if (info != null && info.enabled && isAppPkg(info.packageName)) {
             	//远程调用VAMS,然后VAMS再通过AMS远程调用注册在插件进程的 StubContentProvider.call 初始化插件进程
                int targetVPid = VActivityManager.get().initProcess(info.packageName, info.processName, userId);
                if (targetVPid == -1) {
                    return null;
                }
                args[nameIdx] = VASettings.getStubAuthority(targetVPid);
                Object holder = method.invoke(who, args);
                if (holder == null) {
                    return null;
                }
                // ContentProviderHolder 有两个成员变量provider、connection,provider 是目标 Provider 的 IBinder 句柄。
                // connection 则是 callback
                if (BuildCompat.isOreo()) {
                    IInterface provider = ContentProviderHolderOreo.provider.get(holder);
                    if (provider != null) {
                         // 这里是重点,远程调用了 VAMS 的 acquireProviderClient
                        provider = VActivityManager.get().acquireProviderClient(userId, info);
                    }
                    ContentProviderHolderOreo.provider.set(holder, provider);
                    ContentProviderHolderOreo.info.set(holder, info);
                } else {
                    IInterface provider = IActivityManager.ContentProviderHolder.provider.get(holder);
                    if (provider != null) {
                        provider = VActivityManager.get().acquireProviderClient(userId, info);
                    }
                    IActivityManager.ContentProviderHolder.provider.set(holder, provider);
                    IActivityManager.ContentProviderHolder.info.set(holder, info);
                }
                return holder;
            }
            Object holder = method.invoke(who, args);
            if (holder != null) {
                if (BuildCompat.isOreo()) {
                    IInterface provider = ContentProviderHolderOreo.provider.get(holder);
                    info = ContentProviderHolderOreo.info.get(holder);
                    if (provider != null) {
                        provider = ProviderHook.createProxy(true, info.authority, provider);
                    }
                    ContentProviderHolderOreo.provider.set(holder, provider);
                } else {
                    IInterface provider = IActivityManager.ContentProviderHolder.provider.get(holder);
                    info = IActivityManager.ContentProviderHolder.info.get(holder);
                    if (provider != null) {
                        provider = ProviderHook.createProxy(true, info.authority, provider);
                    }
                    IActivityManager.ContentProviderHolder.provider.set(holder, provider);
                }
                return holder;
            }
            return null;
        }
    
    
        public int getProviderNameIndex() {
            return 1;
        }
    
        @Override
        public boolean isEnable() {
            return isAppProcess();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    这里主要做了几件事情:

    1. 通过 VPMS 拿到解析好的目标 ProviderInfo,启动目标 Provider 所在的进程,怎么启动?远程调用 VAMS,然后 VAMS 再通过 AMS 远程调用注册在插件进程的 StubContentProvider.call 初始化插件进程。这时候 VAMS 就会持有目标插件进程的 IClient 句柄,以备后续调用。
    2. 准备 ContentProviderHolder 相关的事情,ContentProviderHolder 有两个成员变量provider、connection,provider 是目标 Provider 的 IBinder 句柄。
    3. 远程调用了 VAMS 的 acquireProviderClient(), 将任务抛给了远端的 VAMS。

    VActivityManagerService.acquireProviderClient()

    public IBinder acquireProviderClient(int userId, ProviderInfo info) {
        ProcessRecord callerApp;
        synchronized (mPidsSelfLocked) {
            callerApp = findProcessLocked(getCallingPid());
        }
        if (callerApp == null) {
            throw new SecurityException("Who are you?");
        }
        String processName = info.processName;
        ProcessRecord r;
        synchronized (this) {
            r = startProcessIfNeedLocked(processName, userId, info.packageName);
        }
        if (r != null && r.client.asBinder().isBinderAlive()) {
            try {
                return r.client.acquireProviderClient(info);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    调用了 r.client.acquireProviderClient(info);
    r.client 就是前面 initProcess 的时候保存下来的插件进程的 IClient 句柄,那么等于远程调用到了插件的 VClientImpl.acquireProviderClient():

    public IBinder acquireProviderClient(ProviderInfo info) {
        if (mTempLock != null) {
            mTempLock.block();
        }
         // 这里检查 Application 是否启动,注册 Provider 的逻辑也在里面
        if (!isBound()) {
            VClientImpl.get().bindApplication(info.packageName, info.processName);
        }
        //准备ContentProviderClient
        IInterface provider = null;
        String[] authorities = info.authority.split(";");
        String authority = authorities.length == 0 ? info.authority : authorities[0];
        ContentResolver resolver = VirtualCore.get().getContext().getContentResolver();
        ContentProviderClient client = null;
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                client = resolver.acquireUnstableContentProviderClient(authority);
            } else {
                client = resolver.acquireContentProviderClient(authority);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        if (client != null) {
            //反射获取provider
            provider = mirror.android.content.ContentProviderClient.mContentProvider.get(client);
            client.release();
        }
        return provider != null ? provider.asBinder() : null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    调用 bindApplication 的地方,如果 provider 尚未注册,那么这里将会注册 provider。

    最终通过反射 android.content.ContentProviderClient.mContentProvider 获取到了目标 provider 的句柄,然后 provider 沿着目标 Client App 进程——> VAMS 进程 ———-> 回到了调用 Client App 进程中,整个获取 provider 的过程正式完成。

    借鉴于:https://blog.csdn.net/ganyao939543405/article/details/76146760

  • 相关阅读:
    MATLAB中polyvalm函数用法
    网络基础详解
    有监督学习神经网络的回归拟合——基于红外光谱的汽油辛烷值预测(Matlab代码实现)
    CentOS 定期清理日志
    【DSP程序升级】程序升级/OTA/BootLoader开发
    神经网络训练不起来,怎么办?
    字符串:比较、拼接、切割、转义字符;相关切割、替换、查找、去除空白、转大小写函数的方法
    Spring Cloud---服务熔断Hystrix
    【Python】第九课 类和对象
    2022金九银十 —— 招聘有感,给各位测试同学的一些建议
  • 原文地址:https://blog.csdn.net/liuwushuang233/article/details/126761105