Waydroid

来自 ArchWiki

此文章或章节需要语言、wiki 语法或风格改进。参见 Help:Style 以供参考。

原因: 需要改进风格。(在 Talk:Waydroid 中讨论)

Waydroid 是一种基于容器的方法,用于在常规 Linux 系统上启动完整的 Android 系统。

先决条件

CPU 要求

要求取决于 CPU 架构。您可以查看此表格以获取更多信息。

您可以使用 cat /proc/cpuinfo 检查您是否具有所需的 CPU 指令。

GPU 要求

Waydroid 目前在 Intel GPU 上效果最佳。它们应该可以开箱即用。

所有 AMD GPU 均已支持;如果 Waydroid 无法工作,您可能还想尝试构建新的 Waydroid 镜像(适用于 Radeon 680M),或者尝试下面的 NVIDIA 说明。

NVIDIA GPU 目前无法工作,但有 2 种解决方法。

  1. 如果可能,切换到集成显卡
  2. 使用软件渲染(参见 #软件渲染

Wayland 会话管理器

Waydroid 仅在 Wayland 会话管理器中工作,因此请确保您在 Wayland 会话中。

请注意,即使您在 X11 中,许多 Wayland 会话管理器也支持嵌套会话(因此您可以在 X11 会话中运行它),最简单的例子是 cage

内核模块

您需要运行一个带有 binder 模块的内核。这些模块包含在 linuxlinux-ltslinux-zen 内核中,但如果您使用不同的 内核,您可能需要通过 DKMS 或重新编译来添加这些模块。

DKMS 模块

安装 binder_linux-dkmsAUR 并加载 内核模块 binder_linux,模块选项为 devices=binder,hwbinder,vndbinder(参见 错误报告)。

# modprobe binder-linux devices=binder,hwbinder,vndbinder

或者,您可以在启动时设置加载 binder_linux,方法是在 /etc/modules-load.d//etc/modprobe.d/ 中创建配置文件(有关更多信息,请参阅 内核模块)。

/etc/modules-load.d/binder_linux.conf
# Load binder_linux at boot
binder_linux
/etc/modprobe.d/binder_linux.conf
# Options for binder_linux
options binder_linux devices=binder,hwbinder,vndbinder

您还需要使用 内核参数 ibt=off 来解决内核 5.18+ 上的 oops 问题。请参阅 挂载 /dev/binderfs 时出现段错误

构建内核

或者,您可以重新编译 linux 内核 — 或其他内核包(>=5.7)— 并使用必要的选项。另请参阅 Kernel#Compilation

在构建最小内核时,请记住以下要求

  • IPv6 支持。如果您的内核中没有内置 IPv6 网络支持,Waydroid 中将没有 IPv4 连接。
  • Netlink 套接字 (CONFIG_NF_CT_NETLINK=y)。
  • PSI (CONFIG_PSI=y)。
  • 循环块设备 (CONFIG_BLK_DEV_LOOP=m) - 必须在启动 Waydroid 之前加载 loop 模块。

在设置编译选项时,您有两个选项可用;binderbinderfs。下面提供了两者的说明。

使用 binder

这些模块可以编译到内核中 (y)、编译为模块 (m) 或完全不编译 (n)。此外,并非配置中的所有组合都是可能的,并且某些选项将需要其他选项。

以下配置选项会将 binder 编译为模块,而最后一个选项指定在加载 binder 模块时将在 /dev/ 目录中创建三个设备。

CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=m
CONFIG_ANDROID_BINDERFS=n
CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder"

从 AUR 构建内核时,可以使用以下步骤更新配置

  1. 运行 makepkg --nobuild,这将下载源文件、验证并提取它们并运行 prepare() 函数。
  2. 编辑 .config 文件(文件名中带有句点),该文件位于内核目录的根目录。
  3. prepare() 函数的末尾可能有一个命令,该命令使用来自配置的信息重新生成 makefile,可能是 make olddefconfig。将其移动到 build() 函数,或自行执行。
  4. 运行 makepkg --noextract,这将从 makepkg --nobuild 停止的位置继续。
使用 binderfs

已知 binder 内核模块会给一些用户带来问题。为了解决这些问题,创建了 binderfs。在编译内核时,必须在新旧方式之间做出选择。使用以下选项,将使用 binderfs 代替。

内核源代码还附带一个简单的脚本来设置配置选项。它不会像手动编辑配置那样进行依赖项检查。当在 .config 文件所在的同一目录中时,可以执行以下命令

$ scripts/config --enable  CONFIG_ANDROID
$ scripts/config --enable  CONFIG_ANDROID_BINDER_IPC
$ scripts/config --enable  CONFIG_ANDROID_BINDERFS
$ scripts/config --set-str CONFIG_ANDROID_BINDER_DEVICES ""

从 AUR 构建内核时,只需将这些行插入到 PKGBUILD 中的正确位置即可,通常在 prepare() 中。

设置 binder 设备

确保您拥有最新版本的 Waydroid 软件包,Waydroid 将自动处理此问题。

安装

安装 waydroidAUR 软件包。

可选地,安装 waydroid-imageAURwaydroid-image-gappsAUR 通过 AUR 提供所需的 Android 镜像。但是,建议让 Waydroid 本身处理镜像下载。

之后初始化 Waydroid,如果最新的 Android 镜像尚不可用,这将自动下载。

# waydroid init

要使用 GApps 支持进行初始化

# waydroid init -s GAPPS

接下来 启动/启用 waydroid-container.service

Waydroid 现在应该可以工作了。

用法

确保 waydroid-container.service启动,然后运行

$ waydroid session start

Waydroid 会话现在处于活动状态,以下是与它交互的命令示例

启动 GUI

$ waydroid show-full-ui

启动 shell

# waydroid shell

安装应用程序

$ waydroid app install $path_to_apk

获取应用程序列表

$ waydroid app list

运行应用程序

$ waydroid app launch $package_name

网络

网络应该可以开箱即用,如果不是,您可能需要确保在内核中启用了数据包转发,并在运行Waydroid session start之前,允许以下规则通过您的防火墙。

ufw 为例

  • 需要允许 DNS 流量
    • # ufw allow 67
    • # ufw allow 53
  • 需要允许数据包转发
    • # ufw default allow FORWARD

对于 firewalld,您可以使用这些命令

  • DNS
    • # firewall-cmd --zone=trusted --add-port=67/udp
    • # firewall-cmd --zone=trusted --add-port=53/udp
  • 数据包转发
    • # firewall-cmd --zone=trusted --add-forward
  • 将 waydroid 接口添加到 trusted
    • # firewall-cmd --zone=trusted --add-interface=waydroid0
注意: 我们假设由 waydroid 创建的接口 waydroid0 应该自动位于 firewalld 区域 trusted 中。如果不是这样,请调整上述命令或将接口 waydroid0 移动到 trusted。您可能还需要
# firewall-cmd --runtime-to-permanent
使您的更改在重启后持久存在。

技巧与诀窍

启用与桌面窗口管理器集成

waydroid 默认始终以全屏模式运行。

如果您希望 waydroid 与您的桌面环境窗口管理器集成

使用以下命令启动 waydroid 会话

$ waydroid session start

设置所需的属性

$ waydroid prop set persist.waydroid.multi_windows true

现在应用程序应该在其自己的桌面窗口中启动。

更多信息请参见 官方文档

软件渲染

确保您已运行

# waydroid init

(有关更多信息,请参阅 #安装 部分)

然后,添加以下内容

/var/lib/waydroid/waydroid_base.prop
ro.hardware.gralloc=default
ro.hardware.egl=swiftshader

最后,重启 waydroid-container.service

设置视口尺寸

要设置 waydroid 窗口的尺寸,请使用以下命令,并根据您的喜好调整尺寸

$ waydroid prop set persist.waydroid.width 576
$ waydroid prop set persist.waydroid.height 1024

然后 重启 waydroid-container.service

故障排除

如果您遇到问题,请查看官方问题跟踪器:Waydroid issue tracker

通用技巧

Waydroid 正在快速开发中,因此如果您遇到问题,以下是首先要执行的步骤列表

  1. 确保您的 Waydroid 软件包是最新的。
  2. 通过运行以下命令确保您拥有最新的 Waydroid 镜像
    # waydroid upgrade
  3. 重置 Waydroid:停止 waydroid-container.service,运行
    # waydroid init -f
    启动服务。
  4. 您可能还需要进行少量清理,运行
    # rm -rf /var/lib/waydroid /home/.waydroid
    $ rm -rf ~/waydroid ~/.share/waydroid ~/.local/share/applications/*aydroid* ~/.local/share/waydroid
提示: 如果您在 2021-09 之后安装了它,则无需删除 /home/.waydroid/

ARM 应用不兼容

使用 casualsnek 的 脚本 安装翻译层。

由于翻译层中的优化,建议在 AMD CPU 上使用 libndk,在 Intel CPU 上使用 libhoudini。但是,某些应用在一个翻译层上可以工作,而在另一个翻译层上则不能。因此,如果游戏无法工作或性能不佳,您可能需要尝试两者。

安装 libndk arm 翻译

# python3 main.py install libndk 

安装 libhoudini arm 翻译

# python3 main.py install libhoudini

旋转的应用无法使用

参见 Issue 70

单击 F11 将当前应用切换到窗口模式。

无法启动剪贴板管理器服务

安装 python-pyclipAUR 及其图形会话的依赖项 (xclip 用于 X11 或 wl-clipboard 用于 Wayland)。

有时物理键盘无法工作

按下左侧的 Alt 键。

dnsmasq: failed to open pidfile /run/waydroid-lxc/dnsmasq.pid: Permission denied

很可能未设置 AppArmor 规则。添加以下规则

/etc/apparmor.d/usr.sbin.dnsmasq
@{run}/waydroid-lxc/ r,
@{run}/waydroid-lxc/* rw,

Waydroid shell 内的命令输出无法访问或未找到

在基于 Arch 的发行版中,存在一个 “bug”,在使用 lxc-attach 时可能会出现,这可能会导致 waydroid shell 内的命令(如 adbdsettings)出现此问题。

一个可能的解决方法是用以下命令替换 waydroid shell 命令

# lxc-attach -P /var/lib/waydroid/lxc/ -n waydroid --clear-env

WARNING: Service manager /dev/binder has died

参见 Issue 136

您应该启用 PSI

psi=1 添加到 内核命令行

请注意,Liquorix 内核 永远无法与 Waydroid 一起工作,因为它使用某些与 PSI 不兼容的调度程序。

多 GPU 系统上的图形损坏

目前,Waydroid 需要在主机合成器运行的同一 GPU 上运行。解决此问题的两种方法是编辑 /var/lib/waydroid/lxc/waydroid/config_nodes 以使其成为正确的 GPU,或更改合成器运行的 GPU。

没有互联网连接

此文章或章节需要扩充。

原因: 本节需要解释此冲突发生的更深层原因(在 Talk:Waydroid 中讨论)

根据 waydroid/issue/509,Waydroid 已知与 docker 存在 nftables 冲突。

要解决此问题,请关闭 LXC_USE_NFT 作为一种解决方法

/usr/lib/waydroid/data/scripts/waydroid-net.sh
LXC_USE_NFT="false"

或运行以下命令

# systemctl stop docker
# systemctl restart iptables
# ip link delete docker0
# systemctl restart waydroid-container

This device isn't Play Protect certified

参见: https://docs.waydro.id/faq/google-play-certification

如果您收到此错误,您需要进入 waydroid shell 并检索 android id

# waydroid shell
# ANDROID_RUNTIME_ROOT=/apex/com.android.runtime ANDROID_DATA=/data ANDROID_TZDATA_ROOT=/apex/com.android.tzdata ANDROID_I18N_ROOT=/apex/com.android.i18n sqlite3 /data/data/com.google.android.gsf/databases/gservices.db "select * from main where name = \"android_id\";"

之后,将 id 输入到此网站: https://www.google.com/android/uncertified

等待几分钟并重启 waydroid。

Waydroid 一段时间后挂起

这可能是由于音频服务器崩溃所致,请参阅 Issue 576Issue 829 了解详细信息。

一种解决方法是运行

# sysctl -w kernel.pid_max=65535 

您可以通过在 /etc/sysctl.d/ 中创建一个 .conf 文件并在其中添加 kernel.pid_max=65535 使其永久生效。

/etc/sysctl.d/99-sysctl.conf
kernel.pid_max=65535

另请参阅