droidvm软件开发手册v1.0


    名词约定:
    =================================================================
    宿主系统——安卓
    虚拟系统——由运行于安卓中的droidvm虚拟出来的ubuntu系统
    
    
    虚拟电脑(droidvm) 简介
    =================================================================
    droidvm 由 闭源的 droidvm apk 和 开源的linux-installer-for-droidvm 两个项目组成
    
    droidvm 的这两个项目分别使用不同的许可协议,具体如下:
    
    1. 闭源的 droidvm apk 项目:
    安卓包名为: com.zzvm
    由柳州正卓软件有限公司开发,柳州正卓软件有限公司对这个项目的全部内容保留所有权利
    发布为一个apk安装包
    
    2. 开源的 linux-installer-for-droidvm 项目:
    由柳州正卓软件有限公司开发,这个项目使用MIT许可协议
    项目托管地址:https://gitee.com/yelam2022/linux-installer-for-droidvm
    发布为一个zip压缩包
    
    
    
    proot简介
    =================================================================
    不需要root权限的chroot工具。
    用proot启动其它程序时,可以指定一个文件夹,来做为被启动程序的根目录(/)
    
    其它基于namespaces原理的类似工具:unshare, lxc, lxd
    需要root权限的类似工具:chroot
    
    
    虚拟系统的限制:
    =================================================================
    受安卓权限系统的限制,虚拟系统也有如下限制:
    1). 单个apk应用的进程数不能超过30个(可在开发者模式下解除此限制)
    2). netstat 之类的需要高权限的、跟内核有关的指令无法运行
    3). 如果需要在模拟器中访问SD卡内的文件,则apk的存储权限要在安卓系统中授予
    4). 无法使用<1024的端口号, lsmod之类的指令没权限使用
    5). 无法使用shmem,安卓认为shmem不安全,但可以使用mmap映射文件
    6). 没有systemd
    7). 无法查看cpu使用率,但可以通过手机的开发者选项查看(adb shell "top")
    8). 虚拟机内文件系统的权限无法隔离
    9). 无法运行.netcore
    
    
    
    用户系统:
    =================================================================
    虚拟系统中的所有用户 都 对应于app在安卓系统中的uid
    
        app在安卓系统中的uid:
        $APP_ANDROID_UID
        $APP_ANDROID_USERNAME
    
    不论在虚拟系统中如何su, uid 如何变, 进程都始终对于 $APP_ANDROID_UID
    也就是文件系统的权限无法按虚拟系统中的用户进行隔离,
    不能真正做到切换用户,毕竟不是qemu,bochs之类的真正的虚拟机.
    好在这些都可以接受,而且效率比纯虚拟机要快多了.
    
    综上,文件系统无法基于用户进行权限隔离,虚拟系统中的sandbox不可用。
    
    
    
    模拟器的图形显示环境:
    =================================================================
    Xvfb	做 x11-server
    jwm		做 窗口管理器
    pcmanfm	做 虚拟桌面和文件管理器
    
    若需安装xfce4,请先卸载jwm,不然xfce4可能会起不来, 指令如下:
    sudo apt remove  -y jwm
    sudo apt install -y --no-install-recommends xfce4
    
    然后运行指令:
    echo "1" > ${app_home}/app_boot_config/cfg_use_xfce4.txt
    
    最后重启APP.
    
    附:
    echo "0" > ${app_home}/app_boot_config/cfg_use_xfce4.txt    # 不启动xfce4
    
    测试对比发现,同样是在桌面上拖动窗口,xfce4 比 JWM 更顺畅。
    但进程也多了几个。
    
    
    
    
    
    
    
    通过adb shell解除安卓对应用最大可用进程数的限制(手机重启后得重新解除)
    =================================================================
    adb.exe shell dumpsys activity settings | grep max_phantom_processes
    adb.exe shell device_config set_sync_disabled_for_tests persistent
    adb.exe shell device_config put activity_manager max_phantom_processes 512
    adb.exe shell dumpsys activity settings | grep max_phantom_processes
    
    
    
    
    shell入口文件:
    =================================================================
    ${app_home}/droidvm_main.sh
    此脚本由安卓端应用中的C代码调用,
    关联的pty可以查看${APP_STDIO_NAME}环境变量
    
    
    
    安卓端应用通过生成三个sh文件, 对虚拟系统提供环境变量:
    =================================================================
    ${app_home}/droidvm_vars_setup.sh   用户选择的安装选项[0,1,2]
    ${app_home}/droidvm_vars.sh         最关键的数据
    ${app_home}/droidvm_fbwh.sh         当前显示器的分辨率
                                        (支持手机原屏显示、外接显示、webcontrol显示)
    
    查看其它环境变量
    set|grep APP
    
    查看屏幕分辨率
    set|grep SCREEN
    
    
    
    安装脚本文件:
    =================================================================
    所在目录: ${app_home}/default_setup_scripts/
    1). setup_droid_console_only.sh
    2). setup_linux_console_only.sh
    3). setup_linux_fullx11.sh
    
    三个文件分别处理三个安装选项[0,1,2]
    0 => 仅安卓控制台
    1 => ubuntu,不带图形界面
    2 => ubuntu,以及图形界面
    
    
    自启动文件:
    =================================================================
    所在目录: ${tools_dir}/
    1). vm_onstarted.sh     不建议改动
    2). vm_onXstarted.sh    不建议改动
    3). vm_onZerogo.sh      可以改动
    
    vm_onstarted.sh     是刚进入系统时由root用户的.bashrc调用的
    vm_onXstarted.sh    是x11环境启动完了以后,由startvm.sh调用的
    vm_onZerogo.sh      是最后被调用的自启动脚本,用来告诉app系统已经启动完成了,并且调用用户设置的启动代码
    
    
    
    完整的启动流程:
    =================================================================
    安卓端应用
    ->
    ${app_home}/droidvm_main.sh
    ->
    ${app_home}/droidvm_bootup.sh
    ->
    ${tools_dir}/setup_linux.sh
    ->
    ${tools_dir}/startvm.sh
    ${tools_dir}/vm_onstarted.sh
    ->
        #客选启动项
        ${tools_dir}/vm_startx.sh
        ${tools_dir}/vm_onXstarted.sh
    ->
    ${tools_dir}/vm_onZerogo.sh
    
    
    
    
    宿主系统和虚拟系统之间的目录共享:
    =================================================================
    通过使用proot软件的-b参数,安卓系统可以与虚拟系统共享指定的文件目录
    默认已将宿主端的:
    ${app_home}         映射为虚拟系统中的 ${app_home}
    /system/fonts/      映射为虚拟系统中的 /usr/share/fonts/truetype/droid
    
    
    
    ${app_home}/ipc目录
    =================================================================
    control         安卓端应用通过这个管道文件,把触屏事件传给虚拟系统
    notify          虚拟端系统通过这个管道文件,向应用告知自己的运行状态
    screenupdated   虚拟端系统通过这个管道文件,向应用通知桌面已重绘
    Xvfb_screen0    虚拟端系统通过这个mmapfile,向应用提供只读的framebuffer
    
    
    
    ${vmCpuArchId} ${vmGraphicsx} 两个环境变量代表安装时用户所选择的项目
    =================================================================
    vmCpuArchId 代表用户选装的CPU架构:
    0: arm64
    1: amd64
    
    vmGraphicsx 代表用户选装的CPU架构:
    0: 不装图形显示界面
    1: 安装图形显示界面
    
    
    
    
    ubuntu 22.10 rootfs 中的3D支持:
    =================================================================
    apt仓库默认选用mesa 22.2.5(opengl)
    mesa22.2.5已支持这两种 GALLIUM_DRIVER
    llvmpipe - cpu指令实现的gl绘图
    virpipe  - virgl
    
    其中 virgl 架构走socket, 分srv和client,效率非常低.
    在安卓上安装 glmark2.apk
    在此模拟器中安装 glmark2
    对这两种方式的跑分结果进行对比
    发现virgl仅能发挥出原生gl库约10%的性能,
    但仍比 llvmpipe 要快一点点, 而且 adb shell top发现CPU使用率也低很多
    
    virgl c/s 通信用的socket文件:
    =================================================================
    /tmp/.virgl_test
    这个socket文件由运行于安卓端的 virglrenderer 创建,
    经查阅源码,发现监听端口号为1
    模拟器中的mesa gl 库,加载时会检查GALLIUM_DRIVER环境变量
    若为virpipe,则通过 /tmp/.virgl_test 这个socket文件所绑定的信息,
    去连接 virgl 的 server 端。
    
    
    
    
    
    
    ubuntu 22.10 rootfs 中对wine的支持:
    =================================================================
    wine能够在多种兼容POSIX接口的操作系统上运行同CPU架构的windows程序。
    
    通过 sudo apt install wine 指令
    ubuntu-arm64 能安装 wine-arm64, 然后能运行windows-arm64的程序
    ubuntu-amd64 能安装 wine-amd64, 然后能运行windows-amd64的程序
    
    若想在 ubuntu-arm64 里面安装 wine-amd64,则需要安装box64
    若想在 ubuntu-arm64 里面安装 wine-x86,  则需要安装box86, 以及启用multi-arch
    虚拟电脑已内置box和wine的安装脚本
    
    box86/64是个只能运行于linux-arm64中的程序, 
    不过,借助box86/64,可以在linux-arm64系统中,
    运行linux-i386/amd64架构的linux程序 -- 比如wine-amd64
    
    我们编译了box86/64,并按照他们建议的方法安装跨CPU架构的wine,但发现都有问题。
    经多次测试,我们仍不能解决跨CPU架构运行wine的问题。
    所以我们建议不要直接使用wine,而是使用其它基于wine开发的更易安装的wine前端工具。
    比如: playonlinux, Bottles, wine助手
    
    
    与box类似的软件有:
    qemu-user
    exagear
    FEX     的FEXInterpreter https://github.com/FEX-Emu/FEX     FEX和qemu-user以及box86类似  FEX原生支持rootfs, 无需使用chroot
    
    
    
    # 启动wine文件浏览器
    wine explorer
    
    # 启动wine虚拟桌面
    wine explorer /desktop=shell,${RECOMMEND_SCREEN_WIDTH}x${RECOMMEND_SCREEN_HEIGHT}