Android 双开沙箱 VirtualApp 源码分析(四)启动插件 Service

VirtualApp源码(完整工程) VirtualApp源码(完整工程),基于android studio (ndk,sdk)开发,实现安卓双开。 立即下载

Android 双开沙箱 VirtualApp 源码分析(四)启动插件 Service

原生 Service 创建过程

首先有必要了解一下原生 framework 对 Service 的创建,因为在 VA 中启动 Service 和 Activity 有很大的区别。

首先入口 ContextWrapper.startService():

@Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

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

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

不出所料,逻辑再一次转移到远程的 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);
    }

这里的 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);
        }

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

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

那么综上所诉,为了启动插件 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);
        }

        @Override
        public boolean isEnable() {
            return isAppProcess() || isServerProcess();
        }
    }

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

 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);
        boolean needCreateService = false;
        if (r == null) {
            r = new ServiceRecord();
            r.name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
            r.startId = 0;
            r.activeSince = SystemClock.elapsedRealtime();
            r.process = targetApp;
            r.serviceInfo = serviceInfo;
            needCreateService = true;
        } else {
            if (r.process == null) {
                r.process = targetApp;
                needCreateService = true;
            }
        }

        // 如果 service 尚未创建
        if (needCreateService) {
            try {
                // 调用 ApplicationThread.scheduleCreateService 直接创建 Service
                IApplicationThreadCompat.scheduleCreateService(appThread, r, r.serviceInfo, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

            // Note: If the service has been called for not AUTO_CREATE binding, the corresponding
            // ServiceRecord is already in mHistory, so we use Set to replace List to avoid add
            // ServiceRecord twice
            // 将 ServiceRecorder 推入 history
            addRecord(r);

            // 等待 bindService,如果是通过 bindService 自动创建的 Service,在创建 Service 完成后会进入 bindService 流程
            requestServiceBindingsLocked(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. 和 Activity 创建的时候一样,调用 startProcessIfNeedLocked 检查 Application 是否初始化,没有则开始初始化 Application 流程。
  2. 准备 ServiceRecord 和 ServiceInfo。
  3. 如果 service 还没有创建,则直接调用 ApplicationThread.scheduleCreateService 创建 Service,可以看出这里直接跳过了 AMS。
  4. 将 ServiceRecord 记录到 Service 列表,等待 bindService,如果是通过 bindService 自动创建的 Service,在创建 Service 完成后会进入 bindService 流程。

同样的 bindService 也是直接调用系统的 ApplicationThread.scheduleBindService

好了,由于 Service 的特点,startService 看上去比 startActivity 简单多了。接下来要分析的是 BroacastReceiver。

转载:https://blog.youkuaiyun.com/ganyao939543405/article/details/76208729

Android-VirtualApp.zip Android-VirtualApp.zip,Android虚拟引擎(商务版支持10.0),安卓系统是谷歌在2008年设计和制造的。操作系统主要写在爪哇,C和C 的核心组件。它是在linux内核之上构建的,具有安全性优势。 立即下载

相关推荐

virtualapp编译好的

大家要是环境没配好,不好编译,就先用我编译的virtualapp吧。

Android 双开沙箱 VirtualApp 源码分析(一)

最近发现了一个非常好的开源项目,基本实现了一个 Android 上的沙箱环境,不过应用场景最多的还是应用双开。 VA github: https://github.com/asLody/VirtualApp VA 的源码注释: https://github.com/ganyao114/VA_Doc 第一章主要是分析一下项目的整体结构。包结构android.content主要是 PackageP

ganyao939543405的博客 4万+

岭回归的MATLAB步骤

MATLAB 实现框架,它涵盖了从数据导入到岭回归的步骤,包括计算共线性、使用 MAE、MSE、R²、MAPE 进行评价,以及绘制相应的可视化图表。

subject625Ruben的博客 1089

Android 双开沙箱 VirtualApp 源码分析(三)App 启动

上一章:Android 双开沙箱 VirtualApp 源码分析(二) 在这之前,我们还是要先了解一下 VA Client Framework 和 VAService 之间的通讯方式VAService 与通讯VAService首先,VAService 是指 VA 仿造 Android 原生 framework 层 Service 实现的一套副本,举例有 VActivityManagerServic

ganyao939543405的博客 1万+

2021 buaa 计组上机P0 logisim 3道课上考试题

每年题目都不一样,但看看往年题可以帮助查缺补漏 第一题:组合逻辑设计 4人(1个组长和3个组员)对议题进行投票表决。组长有一票否决权。如果组长一票否决,则议题被否决。如果组长正常投票(同意、反对或者弃权),则统计同意的人数和反对的人数。当同意人数大于反对人数,则议题通过,否则议题被否决。 请设计组合逻辑电路,实现这样子的一个投票表决器 同意 反对 弃权 一票否决 组长信号 00 01 10 组员信号 00 01与11 10 第2题 时序逻辑电路设计 设计一个Mealy型电路,若序列的

weixin_41892813的博客 3456

【无标题】EXCEL实现刷题

运用Excel开发的刷题工具,具有普遍实用性,可将WORD的试题自动导入并实现刷题。

weixin_44081794的博客 2970

【使用VirtualApp无root对手游进行修改】

使用VirtualApp对手游进行修改

qq_45071266的博客 2929

对比学习(contrastive learning)

什么是自监督学习? 举个通俗的例子:即使不记得物体究竟是什么样子,我们也可以在野外识别物体。 我们通过记住高阶特征并忽略微观层面的细节来做到这一点。那么,现在的问题是,我们能否构建不关注像素级细节,只编码足以区分不同对象的高阶特征的表示学习算法?通过对比学习,研究人员正试图解决这个问题。 什么是对比学习? 对比学习是一种自监督学习方法,用于在没有标签的情况下,通过让模型学习哪些数据点相似或不同来学习数据集的一般特征。 让我们从一个简单的例子开始。想象一下,你是一个试图理解世界的新生婴儿。在家里,假设你有两只

cziun的博客 11万+

Android 双开沙箱 VirtualApp 源码分析(六)ContentProvider

上一章:Android 双开沙箱 VirtualApp 源码分析(五)BroadcastReceiverProvider 注册回顾前面,Activity 启动的时候会检查 Application 是否初始化,会调用 bindApplication,里面执行了安装 Provider 的方法:private void installContentProviders(Context app, List<P

ganyao939543405的博客 7051

利用Dify平台打造大学生专属AI模拟面试助手:从零到精通的完整指南

在这个充满竞争的就业市场中,拥有一个24小时在线的AI面试教练无疑是大学生求职路上的秘密武器。通过本文的指导,你已经掌握了使用Dify平台构建专业级模拟面试助手的全套技能。从环境部署、模型选择,到Prompt设计、知识库集成,再到高级功能开发和效果优化,我们一步步打造了一个能够适应不同岗位、提供专业反馈的智能面试系统。无论是技术岗的算法问答,还是咨询业的案例分析,或是外企的英语面试,你的定制助手都能提供针对性训练。更重要的是,这个方案具有极强的可扩展性。

专注于编程、AI、人工智能等多个领域内容研究和分析 2789

LED灯闪烁实验:代码集成

LED灯闪烁实验已经全部完成,在该实验中使用了较多的工具链,涉及底层软件、建模、软件编译等。首先,通过STM32CubeMX工具进行STM32底层软件配置,可以大大减少手写代码的工作量。另外由于做了可视化,也降低了STM32的上手难度,提升效率。利用Simulink建模,可以在PC环境下验证应用层算法的正确性而不依赖于具体控制器,实现应用层算法和底层软件、控制器硬件的解耦。另外,图形化的建模方式也更加有利于开发者思考与分析,大量的封装库文件也可以降低开发的工作量。

u013288925的博客 368

【Android 插件化】VirtualApp 接入 ( 在 VirtualApp 工程下创建 Module | 添加依赖 | 启动 VirtualApp 插件引擎 )

一、在 VirtualApp 工程下创建 Module、 二、添加依赖、 三、启动 VirtualApp 插件引擎、 四、博客源码、

让 学习 成为一种 习惯 ( 韩曙亮 の 技术博客 ) 2141

Testbench编写:激励生成、响应监控、仿真时间控制

本文介绍了Verilog/VHDL Testbench的核心技术,重点阐述了激励生成、响应监控和仿真时间控制三大关键环节。通过时钟生成、复位信号生成等具体代码示例,展示了如何有效构建测试平台。文章还总结了波形输出、自动检查等验证方法,并提出了模块化设计、自动化检查等最佳实践,帮助开发者提升FPGA仿真效率和验证质量。这些技术要点为数字电路设计的正确性验证提供了系统化的解决方案。

2301_79143213的博客 111

【Android 插件化】VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )

一、目前的 API 现状、 二、安装应用源码分析、 1、安装按钮执行的操作、 2、返回到 HomeActivity 执行的操作、

让 学习 成为一种 习惯 ( 韩曙亮 の 技术博客 ) 1946

PX4实战(四):PX4 uorb模块详解

本节主要讲解PX4中的uorb消息,主要包括uorb的基本概念使用、PX4内重要的uorb消息、如何自定义uorb消息以及使用uorb消息的注意点等,其中讲解重要uorb消息是为了对PX4内重要数据结构有初步的了解,有助于后期算法理解。uORB(micro Object Request Broker)是PX4中用于模块间通信的轻量级发布-订阅(Publish/Subscribe)机制。模块之间可以通过uORB传递消息,无需直接调用对方函数;提高系统模块化与解耦性;

PX4-SLAM-PNC 1928

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VirtualAPP,va,virtualapp源码

zh739115743的专栏 1169

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Android 双开沙箱 VirtualApp 源码分析(二)

上一章:Android 双开沙箱 VirtualApp 源码分析(一)VA 初始化先看一下代码: VirtualCore.startuppublic void startup(Context context) throws Throwable { if (!isStartUp) { // 确保 MainThread if (Loo

ganyao939543405的博客 1万+

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Chromium 沙盒Sandbox源码介绍(1)

if (!////对应如图:其实最核心的就是利用CreateProcessAsUserW函数 指定用户token 桌面 环境变量 job,然后来限制子进程的权限。

杰克东的专栏 2198

终极指南:如何快速掌握VirtualApp安卓沙盒开源项目

VirtualApp是一款革命性的Android沙盒开源项目,它让开发者能够在同一设备上运行多个应用实例,实现应用多开、游戏合集、移动办公安全等多种创新场景。这个强大的安卓沙盒技术通过三个层次的技术实现应用虚拟化,为Android开发者提供了前所未有的灵活性和控制能力。 ## 🚀 VirtualApp的核心价值与应用场景 VirtualApp不仅仅是一个简单的应用多开工具,它是一个完整的An

gitblog_01030的博客 399

VirtualApp沙盒基本原理

转自:http://rk700.github.io/2017/03/15/virtualapp-basic/ VirtualApp是一个开源的Android App虚拟化引擎,允许在其中创建虚拟空间,并在这个虚拟空间中运行其他应用。通过阅读源码及动态调试,基本了解了其运行原理,在此记录。 本质 Android应用隔离是基于Linux系统的多用户机制实现的,即每个应用在安装

云守护的专栏 2万+

装X指南之通过 VirtualApp 实现免 Root 权限 Hook

一、前言 之前写的 「装X指南之Xposed安装与配置」,有人反馈手机 root 风险较大,而且操作成本高,有没有什么方法是不需要 root 就能够实现 hook 的或者不需要 Xposed 也能玩起插件的?于是就有了这篇文章,离开 Xposed ,带你免 root 实现 hook! 二、VirtualApp 1、关于 VirtualApp 的介绍 VA目前被广泛应用于插件化开发、无感知热更新...

behindeye的博客 4092

Android 双开沙箱 VirtualApp 源码分析(五)BroadcastReceiver

Android 双开沙箱 VirtualApp 源码分析(五)BroadcastReceiver 方案猜测 同 Activity 一样,Client App 在 Menifest 中注册的静态广播外部 AMS 是无法知晓的,经过前几章的分析,相信大家已经是老司机了,我们可以先尝试提出自己的观点。 和 Activity 一样使用 Stub 组件占坑?仔细想一想是无法实现的,因为你无法预先确定 Cl...

CoderAldrich的专栏 657

java双开_修改Android源码实现原生应用双开,应用多开

1. 准备把某系统双开的两个app的信息进行对比1.1 目录的对比1.1.1 data目录对比原应用:/data/user/0/com.luoyesiqiu.crackme/files被复制的应用:/data/user/999/com.luoyesiqiu.crackme/files1.1.2 apk所在目录对比原应用:/data/app/com.luoyesiqiu.crackme-H1Dvbk...

weixin_32900811的博客 2288

android 5.0 创建多用户 双开多开应用(2)

上一讲 讲了如何创建一个user android 5.0 创建多用户 双开多开应用(1) 为什么要创建User  例如window 系统创建了一个user 会在当前用户下进行操作,而android 多用户体系就像window系统 创建了一个user之后在当前user下进行操作,就可以再安装或者启动一个应用。 有了一个user 之后在这个user下创建一个工作空间,在工作空间

small_role的专栏 2483
上一篇: Android 双开沙箱 VirtualApp 源码分析(三)App 启动
下一篇: Android 双开沙箱 VirtualApp 源码分析(五)BroadcastReceiver
CoderAldrich
博客等级 码龄12年 431粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值