anbox 是一个基于容器技术的android虚拟化系统,主页位于GitHub - anbox/anbox: Anbox is a container-based approach to boot a full Android system on a regular GNU/Linux system
有些团队做了些许改进 GitHub - DockDroid/openvmi: 鹏城实验室与北弓联合开发的VMI开源版本
xdroid做了更多优化: 主页 | 北京麟卓信息科技有限公司
华为基于anbox做的robox: 简介_鲲鹏BoostKit ARM原生使能套件_Robox容器方案_Robox安卓容器 安全说明书_华为云
华为的改进版monbox: https://hdcwebinars.huaweicloud.com/watch/bmb084d7
anbox本身是运行在linux x86平台上,运行时每个App是一个单独的窗口。不支持arm架构的APP,必须是x86的APP才可以跑,这就意味着市面上大多数app都无法运行。
xdroid是在anbox基础上修改的,但从它的介绍来看,是可以运行arm APP的。
华为只提供云服务, 服务器基于鲲鹏CPU,原生支持arm64, arm32需要一个特别的gear 进行转码。
关于此方面,已经有一篇文章介绍这个 Anbox源码分析(二)——Anbox渲染原理_天空中的野鸟的博客-CSDN博客_anbox 原理
讲的非常详细了。不重复
基于anbox改进的云手机系统架构图
黄色方块意思是运行在容器内。
蓝色广场示意此进程运行在容器外。
anbox是目前许多云手机,云游戏平台的基础。anbox本身代码质量是非常好的。其中一部分代码直接借鉴自android的模拟器,在原理上与模拟器非常相似。
区别在于,anbox没有采用模拟硬件的方式运行android,而是以docker容器的方式运行,这对于提高性能有非常重要的作用。众所周知,开发android的人没有几个用模拟器进行测试的,大多直接在真机上运行和测试,因为android的模拟器实在是太卡了。
anbox将App的渲染指令通过 qemu_pipe(unix socket) 传输到容器外面的进程进行渲染, 实现OpenGL绘制。
anbox本身只支持远程用VNC进行连接。VNC的编码压缩是非常差的。 像华为robox已经实现了将android容器中的桌面,作为视频用x264编码压缩后传输给远端。
远程传输就比较考验对弱网络的适应能力了,用户的操作是在客户端,用户的操作要传输到服务器上,服务器上响应后,视频流产生变化,再传输到用户端。这个过程如果时间太长,就会让用户感觉到明显的延时。
1.culltefish (需要梯子)
https://source.android.com/setup/create/cuttlefish
2.android 模拟器
https://source.android.com/setup/create/avd
3.国产各型模拟器
雷电安卓模拟器-手游模拟器安卓版_android手机模拟器电脑版_雷电模拟器官网 雷电模拟器 (性能还不错)
VMI系统是腾讯开发的一款云Android手机系统。VMI系统类似于远程桌面系统,由服务端和客户端组成。在服务端上运行虚拟的Android系统,客户端远程通过网络连接到服务器上,实时显示虚拟Android系统屏幕内容,客户端通过屏幕点击与服务端的虚拟Android系统进行实时互动。从用户使用的角度看,虚拟的Android系统与真机并无太大区别,但VMI系统在应用托管、云游戏、移动办公等场景有广阔的使用。
VMI系统的服务端实现主要由Android容器和dockdroid进程两部分组成,系统架构图如图2.1所示,黄色部分运行在Android容器内,蓝色部分运行在宿主机上。Android容器与dockdroid进程是一对一的关系,每一套VMI系统都有一个Android容器和对应的dockdroid进程在运行。
图2.1 VMI系统架构图
Android容器运行在docker中,通过LXC(Linux Containers)技术实现虚拟化。Android容器用于运行Android系统内的各项基础服务进程和各类用户APP。
Android中的渲染都是通过OpenGL ES API实现的。OpenGL ES是OpenGL的一个子集,是为嵌入式设备专门裁剪过的OpenGL。OpenGL ES只是API,或者说是一个规范,任何人或任何机构都可以根据该规范去实现OpenGL ES的内容。Android允许硬件厂商实现自己的OpenGL ES,并通过一定的方式加载对应的OpenGL ES库。VMI系统/system/lib64/egl目录下有三个动态库,分别为libEGL_emulation.so、libGLESv1_CM_emulation.so和libGLESv2_emulation.so,是腾讯作为虚拟的硬件厂商为Android提供的OpenGL ES渲染库。
每一个APP在运行时,都会将对应的.so加载到进程中,在这些.so的内部实现中,所有的OpenGL ES指令都将被编码(encode)和发送到运行在宿主机上的dockdroid进程,由dockdroid进程调用GPU实现最终的渲染并返回渲染的结果。对于需要返回值的函数,像glGetError()、glFenceSyncAEMU()此时会等待函数执行完成并收到返回值后才往下继续执行。
容器内部到dockdroid进程的连接是通过unix domain socket实现的。Android容器运行时,会通过docker的文件映射机制,将名为qemu_pipe的文件映射到容器内,只要connect此文件即可与外部dockdroid进程建立连接。
dockdroid进程运行在宿主机上,主要作用是接收容器内APP进程发送的OpenGL ES指令,将OpenGL ES指令转成相应的OpenGL指令,调用宿主机上的Radeon Pro WX 5100显卡进行渲染,并返回渲染结果。
dockdroid进程内对于任意一个APP的连接,dockdroid会创建一个渲染线程和一个发送线程,实现OpenGL ES指令的处理和返回。整个OpenGL ES指令的处理流程分三个步骤,如图2.2所示:
第一步,从线程池中随机挑选一个线程负责接收APP发送过来的数据,放入in_queue缓存队列。
第二步,渲染线程从in_queue缓存队列中取出数据,进行OpenGL ES指令的解码、翻译、执行并将需要返回的结果编码后放入out_queue缓存队列。
第三步,发送线程检测到out_queue上有数据就尽全力把数据全部发送出去。
图2.2 dockdroid进程内部处理流程图
普通手机的GPU直接连接显示器,APP渲染的结果可以直接输出到屏幕。与普通真实手机相比,云手机的屏幕显示在客户端呈现,但APP的渲染是在服务器上实现,APP的渲染结果需要从服务端截取再传输到客户端。
VMI系统服务端的Android容器中运行串流服务,服务的名称是com.gray.boxstream,实现的功能是接受客户端的连接,以30帧/s的速度截取Android系统的屏幕,然后进行x264编码,再以视频流的形式发送给客户端。
串流服务获取Android系统屏幕内容的过程被称作“取流”,取流的实现与APP渲染的实现过程是一样的,同样要依赖dockdroid和GPU。
具体的过程是: 串流服务调用底层libgl_XX.so中的rcReadColorBuffer函数,rcReadColorBuffer函数最终在dockdroid中通过glReadPixels函数实现屏幕截取并返回一帧画面的数据。数据的格式是RGBA,一个像素点占4个字节,宽720像素,高1280像素,一张屏幕截图的数据量是720×1280×4=3,686,400,大约是3.5MB。
串流服务取到图像后对进行x264视频编码,目前使用的是CPU软编码,导致串流进程的CPU的使用率达到100%-120%。编码完成后,串流服务将编码后的x264码流通过UDP协议发送给客户端,客户端收到数据后进行解码并播放。