我是如何在PC电脑上使用Android应用的
我所在的公司是使用内部自己开发的聊天工具来办公的,而这个聊天工具是研发同志开发出来,但是仅支持Windows,Android,IOS,MacOS四个平台(我感觉腾讯非常赞同)。对于使用Archlinux我这边平时办公沟通变得极不方便。
第一次尝试是桌上摆手机,并安装An2Linux来把Android上的app消息转发到linux的An2Linux服务端通知。使用了很久,算是解决了通知不及时纯靠喊的问题。缺点就是要拿着手机操作,而且无法跟操作系统共享文件跟粘贴板(后来自己又开发了个粘贴板跟图片同步工具解决)
之后开始找一些远程连接到Android的解决方案,谷歌帮我找到 scrcpy 这个开源工具,通过adb tool 把android屏幕镜像到linux系统上,原理是android上的屏幕流数据编码,通过adb usb或者wifi发给电脑解码,在电脑上屏幕可以鼠标操作,并且也有android跟linux粘帖板同步。说来他这个scrcpy还支持wayland窗口渲染协议,像我用swaywm以后也可以很好的兼容。倒是android上的app消息通知无法展现给linux dbus协议,不过还好有之前An2Linux可以一起用。算是接近完美的使用方法了,scrcpy利用adb可以保持手机唤醒状态并关闭手机屏幕。
后来,考虑采用仿真的方法,可选有1:选择android x86 emulator,2:anbox 的lxc容器
android 的x86 emulator试过一段时间,我是在编译LineageOS的时候跑过,较为复杂。说实话弄qemu模拟器有很多事要弄,参数也多,不过兼容性倒是非常好。有空再另外整一篇记录。 接下去我主要想谈 Anbox这个利用lxc技术为Android app模拟运行的方案。毕竟这是最终使用的方案,不排除以后又搞别的方法(笑)
需要:
已有Archlinux操作系统
熟悉Archlinux PKGBUILD构建软件包
了解内核参数的配置
了解systemd运行的机制
了解Linux Namespace容器
编译一个可用的内核
Anbox需要一个能支持Android binfmt的Linux内核。根据Anbox的官方文档说明,你还需要打开多个内核参数。就Archlinux自带的core/linux而言,确实仅需要Android binfmt。但如果你是自行编译的针对自己机器使用的内核的话,还是需要知道下几个需要开的参数。主要是Android部分跟Namespace的部分。
这个commit展示了需要支持的一些要开的CONFIG,跟编译用的PKGBUILD,自用内核的话修改的那几个CONFIG很有参考性。注意:你自己的电脑不能直接用他这个config那是设备定制的配置。如果你是使用Archlinux core/linux 包,只需要开启Android那几个就可以,其他配置Arch默认都有开。
安装可用的lxc
lxc支持的话非常简单,你只需要Pacman -S lxc
注意版本需要 4.0.2以后的,我在安装的时候是4.0.4
安装Anbox
Anbox是方案的核心
安装anbox-git
编译Anbox建议用这个 当然可能需要几个额外的补丁,如果你仅需要简单跑起来,那么直接这个anbox-git makepkg并安装就可以了。注意:编译完成后仅需要安装 anbox-git这个包,dkms跟anbox-modules-dkms-git 不用安装。
网络部分,lxc是桥接方式,如果你使用systemd-networkd管理网络的话,那么anbox-git自带配置就很方便的支持,不需要什么额外配置。
安装anbox-image
操作系统需要系统,模拟android也一样,android的system image使用 这个, 同样makepkg安装,他这个image有一些问题,下面疑难解答会提到,可以先用着
启动Anbox
上面几个安装完成之后是show magic的时间了
# mkdir /dev/binderfs
# mount -t binder binder /dev/binderfs
# systemctl start anbox-container-manager.service
以上这分别是暴露binderfs设备接口以及启动anbox daemon
然后
% cat > $HOME/.config/systemd/user/anbox-session-manager.service <<EOF
[Unit]
Description=Anbox Session Manager
[Service]
ExecStart=/usr/bin/anbox session-manager --single-window --window-size=576,1024 --gles-driver=host
[Install]
WantedBy=default.target
EOF
这准备 anbox session-manager 的启动参数,窗口大小自行根据显示器改个合适的值,建议是竖屏16:9,app兼容性好。
% systemctl --user start anbox-session-manager.service
就启动了,第一次会有很长时间的黑屏,毕竟android启动慢嘛
疑难解答
anbox好像有点问题,应该怎么排查
不论如何都应该知道下一些排查的方式
% anbox system-info
如果显示
binder: false
ashmem: true
那基本就是没什么问题了,这两个内核功能是关键,这里binder显示false不要紧,anbox支持binderfs创建设备。如果ashmem false,那么内核编译的还不支持ashmem。
graphics: egl: vendor: Mesa Project version: 1.5 extensions: 也需要显示很长的一些EGL扩展,有了显示才能正常。
我是swaywm或者wayland wm用户
注意目前anbox的sdl驱动还仅支持X11,wayland用户需要把Xwayland开起来
lxc容器无法启动
% /usr/bin/lxc-checkconfig
Cgroup v1 systemd controller: missing
Cgroup v1 freezer controller: missing
Cgroup namespace: required
这个命令显示的一定要除了这几个红色,其他都不能红色,不然lxc工作不正常。
还有如果你内核启动参数添加了 systemd.unified_cgroup_hierarchy=1 这类的仅支持cgroup v2的设置,那么需要注意下 lxc需要很新的版本,并且要在系统刚启动的时候把cgroup根组的 subtree支持开起来
# echo "+cpuset +cpu +io +memory +hugetlb +pids +rdma" > /sys/fs/cgroup//cgroup.subtree_control
lxc是支持cgroup v2 only的,但是如果你在需要动态开启cgroup根组的控制树的时候,会由于一些已经存在的SCHED_RR进程而无法修改,目前linux内核还不支持cgroup subtree递归控制,真要操作的话,要么把 进程kill掉
# ps ax -L -o 'pid tid cls rtprio comm' | grep RR
大概都是pulseaudio跟rtkit在使用,这时候的 SCHED_RR进程可能是你正在听歌看视频
或者要么这些进程使用的systemd scope得放在 cgroup /组,这些SCHED_RR进程服务一般都放在/user.slice。
kill掉这些进程cgroup v2的lxc应该可以正常启动。当然如果没有加systemd.unified_cgroup_hierarchy=1那么lxc在cgroup混合模式下是工作正常的。
也可以打上这个patch解决
anbox 里面 app 声音延迟很大
如果上面的疑难都是特殊情况,那么这个声音延迟问题肯定是存在的,至少在我写的这个时候,还未修复 这个 pr一直未合并,然后patch修复需要同时编译anbox以及image,anbox-git还好说,image本身是android 7.1.1 一直没有更新,维护者也说了,等下次image更新就合并这个提交。如果你想编译image,那么参考这里。编译android image的坑也是很多的,如果你不会编译,那么有空我再写一遍 android aosp编译的。 如果你不想自己编译,可以私信我,我把编译好的android_amd64.img 共享给你。
anbox 里面的chromium 无法正常运行
没错,chromium android 默认是用gl es驱动的,anbox里的egl扩展还是有点问题的,但是平时chromium的gpu都有device list兼容列表来针对不同设备进行兼容配置,anbox应该没有在列表里面,如果设置成 egl software应该就可以了吧。打开about:flags空白无法设置,logcat显示大量egl error,我也不知道android怎么给chromium加启动参数。
我的mesa是amdgpu驱动的,也许别的gpu mesa支持良好不会有这个问题。