## 零、前言说明 本教程使用[systemd-networkd](https://zhida.zhihu.com/search?content_id=228426250&content_type=Article&match_order=1&q=systemd-networkd&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3NDEyNzgxNzEsInEiOiJzeXN0ZW1kLW5ldHdvcmtkIiwiemhpZGFfc291cmNlIjoiZW50aXR5IiwiY29udGVudF9pZCI6MjI4NDI2MjUwLCJjb250ZW50X3R5cGUiOiJBcnRpY2xlIiwibWF0Y2hfb3JkZXIiOjEsInpkX3Rva2VuIjpudWxsfQ.MuX51TS-DGdgd_khAzFgU2o4epNjqnd-nm-gshNOpy4&zhida_source=entity)、[systemd-resolved](https://zhida.zhihu.com/search?content_id=228426250&content_type=Article&match_order=1&q=systemd-resolved&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3NDEyNzgxNzEsInEiOiJzeXN0ZW1kLXJlc29sdmVkIiwiemhpZGFfc291cmNlIjoiZW50aXR5IiwiY29udGVudF9pZCI6MjI4NDI2MjUwLCJjb250ZW50X3R5cGUiOiJBcnRpY2xlIiwibWF0Y2hfb3JkZXIiOjEsInpkX3Rva2VuIjpudWxsfQ.xLpnWJkVi1abK39e8We03bBLFznCVkP2y06Fzw8mC6A&zhida_source=entity)及nftables配置waydroid的网络,与官方基于iproute2、dnsmasq及iptables的方法不同。原因是我的[qemu-KVM](https://zhida.zhihu.com/search?content_id=228426250&content_type=Article&match_order=1&q=qemu-KVM&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3NDEyNzgxNzEsInEiOiJxZW11LUtWTSIsInpoaWRhX3NvdXJjZSI6ImVudGl0eSIsImNvbnRlbnRfaWQiOjIyODQyNjI1MCwiY29udGVudF90eXBlIjoiQXJ0aWNsZSIsIm1hdGNoX29yZGVyIjoxLCJ6ZF90b2tlbiI6bnVsbH0.yNwEyB-UtEuIhhbjubReR7v13J0IbCztvViW1Q-BXF0&zhida_source=entity)虚拟机网络也是基于systemd、nftables配置的,这种方法更为现代化,且比iproute2、dnsmasq及iptables繁琐的规则简单多了。 waydroid是基于lxc的容器方案,能在X86_64位CPU上运行原生安卓系统(LineageOS X86_64系统),与宿主机器共享同一个linux内核(包括你自己编译优化的内核),能直接调用宿主机显卡硬件,是目前所有安卓兼容方案中性能最高的。但是需要添加ARM转译层(libhoudini或libndk)的支持才能运行绝大多数手机app,这点教程里会教你。 waydroid的图形实现是[wayland](https://zhida.zhihu.com/search?content_id=228426250&content_type=Article&match_order=1&q=wayland&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3NDEyNzgxNzEsInEiOiJ3YXlsYW5kIiwiemhpZGFfc291cmNlIjoiZW50aXR5IiwiY29udGVudF9pZCI6MjI4NDI2MjUwLCJjb250ZW50X3R5cGUiOiJBcnRpY2xlIiwibWF0Y2hfb3JkZXIiOjEsInpkX3Rva2VuIjpudWxsfQ.fC0vV7nX5opGbf1h4Et5F288XD8TE3HA6XGir_SaT2o&zhida_source=entity),所以你的linux桌面必须是以wayland环境启动(KDE、Gnome、sway、Hyprland、Weston等)。不要再想着你的X11了,这种老旧的协议应该早点淘汰。 教程里有一些重复的步骤,尤其是"修改waydroid的网络配置",不要觉得麻烦就跳过,这些步骤都是设计好的,没有多余的步骤。跳过的话你执行"waydroid session start"命令是不会成功的。 ## 一、首先准备编译内核 #写在前头:不会配置编译内核的朋友,请换用Archlinux的linux-zen内核,然后在你们grub内核引导配置的末尾加上一个"psi=1"就ok了。 ``` 选中所有cgroup和namespace的子选项 CONFIG_CGROUP_FAVOR_DYNMODS=n CONFIG_PSI=y CONFIG_PSI_DEFAULT_DISABLED=n CONFIG_BPF_SYSCALL=y CONFIG_BPF_UNPRIV_DEFAULT_OFF=y CONFIG_VETH=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_ANDROID_BINDERFS=y CONFIG_ANDROID_BINDER_DEVICES="" CONFIG_ANDROID_BINDER_IPC_SELFTEST=n CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT2=y #"n"表示取消选择 ``` ![](https://picx.zhimg.com/v2-1e5a5b2ea2d62bcd75342c93468baecf_1440w.jpg) ![](https://picx.zhimg.com/v2-8fba7c72cec95e77c108c1b134a255e3_1440w.jpg) ![](https://pica.zhimg.com/v2-00447a18e2c1d191911d69f5983fd474_1440w.jpg) ![](https://pic3.zhimg.com/v2-185ab9e7b2157479e4b96f57c984bce6_1440w.jpg) ![](https://pic3.zhimg.com/v2-fb097c6966afd4f37a94c9aaac32e280_1440w.jpg) 重新编译并安装内核(参见我的内核编译教程) ## 二、下载waydroid和image ``` 在pacman里添加archlinuxcn源 sudo pacman -Syu sudo pacman -S waydroid waydroid-image paru -S python-pyclip ``` ``` sudo waydroid init -f -i /usr/share/waydroid-extra/images sudo systemctl enable waydroid-container.service sudo systemctl start waydroid-container.service ``` 这里先不启动waydroid,我们先配置网络 ## 四、配置网络(使用systemd-networkd和nftables) 更改以下脚本,删除关于iproute2和dnsmasq的设置 ``` sudo nano /usr/lib/waydroid/data/scripts/waydroid-net.sh : #!/bin/bash echo "mama" #每次waydroid更新后均需要修改此脚本 ``` 修改waydroid的网络配置 ``` sudo nano /var/lib/waydroid/lxc/waydroid/config : 找到网络配置的那一段,改为以下 lxc.net.0.type = veth lxc.net.0.flags = up #lxc.net.0.link = waydroid0 lxc.net.0.name = eth0 lxc.net.0.hwaddr = 00:16:3e:f9:d3:03 lxc.net.0.mtu = 1500 lxc.net.0.veth.pair = waydroid0 #每次waydroid更新后均需要修改此配置文件 ``` 修改systemd-networkd的网络配置 ``` sudo nano /etc/systemd/network/waydroid0.network : [Match] Name=waydroid0 [Network] Address=192.168.24.1/24 DHCPServer=true IPForward=yes ``` 修改nftables的防火墙配置 ``` sudo nano /etc/nftables.conf : table inet filter { chain input { type filter hook input priority filter; policy drop; iifname "lo" accept iifname "waydroid0" accept ct state established,related accept ct state invalid drop } chain output { type filter hook output priority filter; policy accept; } chain forward { type filter hook forward priority filter; policy drop; ct state established,related accept iifname "waydroid0" oifname "wlan0" accept iifname "wlan0" oifname "waydroid0" accept } } table inet nat { chain postrouting { type nat hook postrouting priority srcnat; policy accept; iifname "waydroid0" oifname "wlan0" masquerade } } #其中"wlan0"更改为你自己用于连接外部网络上网的设备,用"ip a"命令查看 ``` 启用ip转发 ``` sudo nano /etc/sysctl.d/90-override.conf : net.ipv4.ip_forward = 1 net.ipv4.conf.default.forwarding = 1 net.ipv4.conf.all.forwarding = 1 net.ipv6.conf.default.forwarding = 1 net.ipv6.conf.all.forwarding = 1 ``` 停用dnamasq、dhcpd、networkmanager网络服务及iptables防火墙,他们会和systemd-networkd、systemd-resolved和nftables冲突 ``` sudo systemctl disable dnsmasq.service sudo systemctl disable dhcpd.service sudo systemctl disable NetworkManager.service sudo systemctl disable iptables.service ``` 启用systemd-networkd、systemd-resolved和nftables ``` sudo rm /etc/resolv.conf sudo ln -rsf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf sudo systemctl enable systemd-networkd.service sudo systemctl enable systemd-resolved.service sudo systemctl enable nftables.service ``` 好了,重启电脑 ## 五、为waydroid安装arm兼容层 终端里执行 完成后退出执行("ctrl+c"终止运行) 安装相关依赖及脚本 ``` sudo pacman -S lzip sqlite paru -S waydroid-script-git ``` AMD的cpu安装libndk Intel的cpu安装libhoudini 修改waydroid的网络配置 ``` sudo nano /var/lib/waydroid/lxc/waydroid/config : 找到网络配置段,改为以下 lxc.net.0.type = veth lxc.net.0.flags = up #lxc.net.0.link = waydroid0 lxc.net.0.name = eth0 lxc.net.0.hwaddr = 00:16:3e:f9:d3:03 lxc.net.0.mtu = 1500 lxc.net.0.veth.pair = waydroid0 ``` ## 六、使用waydroid 终端里执行,不终止退出 为waydroid配置网关 ``` echo "ip route add default via 192.168.24.1" | sudo waydroid shell #这一步很重要,不配置网关无法上网。此命令必须随每一次"waydroid session start"启动而执行一次,否则失效 ``` 接下来即可进入waydroid图形界面开始上网 ## 七、小技巧 列出waydroid系统里安装的包及包名 安装安卓应用 ``` waydroid app install /path/to/apk ``` 不启动安卓界面,只启动一个app ``` waydroid app launch $package-name #Can be retrieved with `waydroid app list` ``` 有的app不识别鼠标点击事件 ``` waydroid prop set persist.waydroid.fake_touch $package-name #此命令必须随每一次"waydroid session start"启动而执行一次,否则失效 ``` 有的app即使联网了也不能上网,浏览器能上网但不能下载东西 ``` waydroid prop set persist.waydroid.fake_wifi $package-name #此命令必须随每一次"waydroid session start"启动而执行一次,否则失效 ``` ## 八、Trouble Shooting 1. 一些ARM应用无法正常启动 ``` 事关libndk和libhoudini本身的兼容性,无解,只能等待google和intel更新 ``` 2. 一些app和游戏无法识别键盘和鼠标,只识别触摸屏事件,极大阻碍waydroid实际使用体验 ``` 1、使用qtscrcpy,但是键盘鼠标映射配置复杂,通过adb投屏的画质差、延迟高 2、下载安卓键鼠映射app,比如panda mouse pro、八爪鱼,相关教程去B站上搜,反正我是没成功过 3、此类问题最有希望的是waydroid官方上游加入类似windows平台上mumu、雷电模拟器的键鼠映射支持,否则基本无解 ``` 目前我只找到了键盘映射触屏事件的app,即Key Mapper+Shizuku。鼠标映射触屏实在是没办法。 ![](https://pic3.zhimg.com/v2-b99e6110c644b87a70f6999c9032ecc4_1440w.jpg) ![](https://pic2.zhimg.com/v2-03b48fb71ac42d1ccc19fdd9132fa261_1440w.jpg) ![](https://pic2.zhimg.com/v2-d8286994a0ba1c7529e5f5bf64ebd37f_1440w.jpg) #不玩游戏时记得把上述键盘映射关了,免得影响日常输入法体验。 关于在映射触屏tap事件时,如何获取屏幕触击坐标? 首先开启开发者模式 ``` 设置-->关于手机-->版本号,连续点击"版本号"7次以上 ``` 然后 ``` 系统-->高级-->开发者选项-->指针位置,开启"指针位置" ``` 此时长按鼠标左键即可在屏幕上方显示当前触击点的x,y坐标。 3. 一些app启动后默认竖屏,导致屏幕翻转,鼠标操控困难 ``` 安装一款名叫Rotation的app,不用破解版也行。上网随便一搜就能找到。 ``` ![](https://pic4.zhimg.com/v2-cd4b4e3b17e2cd365e4f20456d50573f_1440w.jpg) 右下角Rotation ![](https://pic2.zhimg.com/v2-3e4554ea82d2ee700163a3dea55554c5_1440w.jpg) 如红色选中的设置为强制横屏 ![](https://pic4.zhimg.com/v2-deb3b4445367b0a147aff1f68570a305_1440w.jpg) 设置为开机启动 #注意:强制横屏后,原本你在Key Mapper里配置的竖屏app的触屏事件坐标会对应不上,需要重新配置改为横屏后的触屏坐标。 ## 九、挂载宿主机目录到waydroid内部目录里 比如 ``` sudo mount --bind /home/zouzi/ ~/.local/share/waydroid/data/media/0/Download/ ``` 之后你就可以在waydroid系统里的Download目录里看见你宿主机上的内容了 ``` 每一次"waydroid session start"启动后,需要先执行 sudo umount ~/.local/share/waydroid/data/media/0/Download/ 再执行 sudo mount --bind /home/zouzi/ ~/.local/share/waydroid/data/media/0/Download/ 否则挂载失效 ``` 若重复两次及以上挂载,waydroid系统里不会看到宿主机上的内容。这时候需要 ``` 多次重复执行 sudo umount ~/.local/share/waydroid/data/media/0/Download/ ``` 直到出现提示 ``` umount: /home/zouzi/.local/share/waydroid/data/media/0/Download/: not mounted. ``` 再次执行一次 ``` sudo mount --bind /home/zouzi/ ~/.local/share/waydroid/data/media/0/Download/ ``` 就可以了 ## 十、删除所有waydroid配置,重新安装 有的时候遇到难以修改的问题,可以删除所有的waydroid文件及配置,重新安装 ``` sudo systemctl stop waydroid-container.service sudo rm -rf /var/lib/waydroid/ /home/.waydroid/ ~/waydroid/ ~/.share/waydroid/ ~/.local/share/applications/*aydroid*/ ~/.local/share/waydroid/ sudo pacman -S waydroid-image #重新安装waydroid镜像,这一步必不可少 sudo waydroid init -f -i /usr/share/waydroid-extra/images sudo systemctl start waydroid-container.service ``` 修改waydroid的网络配置 ``` sudo nano /var/lib/waydroid/lxc/waydroid/config : 找到网络配置段,改为以下 lxc.net.0.type = veth lxc.net.0.flags = up #lxc.net.0.link = waydroid0 lxc.net.0.name = eth0 lxc.net.0.hwaddr = 00:16:3e:f9:d3:03 lxc.net.0.mtu = 1500 lxc.net.0.veth.pair = waydroid0 ``` 执行 完成后退出 AMD的cpu安装libndk Intel的cpu安装libhoudini 修改waydroid的网络配置 ``` sudo nano /var/lib/waydroid/lxc/waydroid/config : 找到网络配置段,改为以下 lxc.net.0.type = veth lxc.net.0.flags = up #lxc.net.0.link = waydroid0 lxc.net.0.name = eth0 lxc.net.0.hwaddr = 00:16:3e:f9:d3:03 lxc.net.0.mtu = 1500 lxc.net.0.veth.pair = waydroid0 ``` 启动waydroid ``` waydroid session start echo "ip route add default via 192.168.24.1" | sudo waydroid shell waydroid show-full-ui ``` ## 十一、如何执行root操作 waydroid里的LineageOS X86_64安卓系统并没有被预先root。 一些app可能需要通过开启安卓系统ADB调试的方式来获取root权限。如Shizuku,需要连接USB ADB调试或Wifi ADB调试后执行 ``` adb shell sh /storage/emulated/0/Android/data/moe.shizuku.privileged.api/start.sh ``` 才能激活运行。 但是waydroid容器不用那么复杂,只需要在宿主机上执行 即可以最高root权限进入waydroid系统内执行命令 ``` sh /storage/emulated/0/Android/data/moe.shizuku.privileged.api/start.sh #此命令必须随每一次"waydroid session start"启动而执行一次,否则失效 ``` 不用开启USB ADB调试或Wifi ADB调试,即可成功激活Shizuku。 激活命令可以改为 ``` echo "sh /storage/emulated/0/Android/data/moe.shizuku.privileged.api/start.sh" | sudo waydroid shell #此命令必须随每一次"waydroid session start"启动而执行一次,否则失效 ``` 在宿主机终端里执行。 ## 十二、最终实现效果 目前,我通过自己编译配置内核,已经实现了qemu-KVM虚拟机运行win10系统办公微信写论文、waydroid容器运行安卓游戏、steam proton玩游戏、yuzu模拟器玩塞尔达旷野之息和王国之泪、pcsx2模拟器玩老PS2经典游戏、webd服务器自建网盘、mpv+SVP+Anime4k高清60帧看番剧。我的linux桌面系统正在被我调教成一个兼具办公和娱乐的高性能六边形战士,感觉十分有趣。