用 RK3588 设备搭建自己的云手机:Redroid 实践指南

最近,我折腾了一把 Orange Pi 5 Max (搭载 RK3588 芯片) ,成功搭建了一套私有的云手机系统。这个过程不仅实现了远程运行 Android 应用的目的,更让我对 ARM 虚拟化容器化技术有了深入的了解。如果你手里也有 RK3588 或类似的高性能 ARM 单板机,不妨跟着这份指南,将你的硬件潜力彻底释放。

redroid-rk3588

🚀 引言:为什么选择 RK3588 和 Redroid-rk3588

什么是云手机?

云手机本质上是一种基于云计算或虚拟化技术的远程 Android 操作系统实例。它可以让你在任何地方通过网络控制一台虚拟的 Android 设备。

RK3588 的独特优势

我们选择 Rockchip RK3588 (如 Orange Pi 5 Max、Rock 5B 等) 作为宿主机,因为它具备关键的技术优势:

  1. 强劲的性能: 采用大小核架构(4x Cortex-A76 + 4x Cortex-A55),提供足够的 CPU 性能支撑多个 Android 容器。

  2. GPU 硬件加速: 内置高性能 Mali-G610 GPU,这是运行 Android 游戏或图形密集型应用的关键。Redroid 可以直接透传宿主机的 GPU 资源,获得接近原生设备的渲染速度。

  3. 大内存支持: RK3588 设备通常配备 8GB、16GB 甚至 32GB 内存,为多个云手机实例提供了充足的资源。

Redroid:容器化 Android 的利器

我选择了 Redroid-rk3588 项目。它是一个高度优化的 Android 容器化解决方案,相比传统的虚拟机(如 Android-x86),它利用 Linux 的 NamespaceCgroups 机制,直接共享宿主机的内核,资源占用极低,启动速度极快


🛠️ 搭建环境与核心步骤

环境准备

  • 硬件: Orange Pi 5 Max (RK3588) 或其他同类设备。

  • 系统: Armbian (推荐) 或其他主流 Linux 发行版。

  • 网络: 稳定的网络连接,并准备好 ADB 调试工具和 scrcpy 软件。

基础系统:使用 Armbian

  1. 烧录 Armbian 镜像到存储介质, 我的设备时Orangepi 5 MAX。

  2. 开机并完成初始设置。建议使用 Armbian CLI (命令行界面) 版本,资源占用更小。

  3. 更新系统:

    1
    2
    sudo apt update
    sudo apt upgrade -y

核心难点:编译支持 Redroid 的内核

armbian的默认内核中没有system-uncached-dma32设备, 这个设备在Linux 6.1中已经被移除,但redroid-rk3588若要使用GPU加速则必须此设备,否则会出现scrcpy无法连接的情况。

  1. 编译环境准备:
    我使用的是Ubuntu 22.04.5 LTS, 不确定WSL是否能够正确编译.

    • 至少8GB内存
    • 至少15GB剩余存储空间
  2. 为了避免一些奇怪的问题,建议以root身份执行操作

  3. 克隆armbian-build源代码

    1
    2
    cd ~
    git clone --depth=1 https://github.com/armbian/build
  4. 关键一步: 使用脚本生成内核补丁

    1
    2
    3
    4
    5
    6
    7
    # 创建补丁生成脚本
    touch generate_redroid_patch.sh
    # 打开脚本
    vim generate_redroid_patch.sh

    # 或者直接从Github仓库下载
    wget https://github.com/HwlloChen/redroid-rk3588-armbian-kernel-patch/raw/refs/heads/main/generate_redroid_patch.sh

    写入以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    #!/bin/bash

    # --- 配置参数 ---
    # 您的 Armbian build 目录路径
    ARMBIAN_BUILD_DIR="$HOME/build"
    # Armbian 目标内核分支 (来自您的日志)
    TARGET_KERNEL_BRANCH="rk35xx-vendor-6.1"
    # Armbian 官方内核 rk-6.1 分支 (Base)
    ARMBIAN_KERNEL_BRANCH="rk-6.1-rkr5.1"
    # CNflysky 带 Redroid 更改的内核分支 (Target)
    CNFLYSKY_KERNEL_BRANCH="rk-6.1-rkr4.1"

    # 补丁文件路径
    PATCH_DIR="${ARMBIAN_BUILD_DIR}/userpatches/kernel/${TARGET_KERNEL_BRANCH}"
    PATCH_FILE="0002-dma-uncached-dma32.patch"

    # 临时目录
    TEMP_DIR_ARMBIAN="armbian-rkr5.1-base"
    TEMP_DIR_CNFLYSKY="cnflysky-rkr4.1-target"

    # 需要提取差异的目录和文件列表
    # 目录差异将递归提取(如 drivers/dma-buf)
    # 文件差异将单独提取(如 include/linux/dma-buf.h)
    TARGET_PATHS=(
    "drivers/dma-buf"
    "include/linux/dma-buf.h"
    "include/linux/dma-heap.h"
    "include/linux/android_kabi.h"
    )
    # ------------------

    echo "--- 1. 清理环境 ---"
    rm -rf ${TEMP_DIR_ARMBIAN} ${TEMP_DIR_CNFLYSKY}
    mkdir -p ${PATCH_DIR}

    echo "--- 2. 克隆 Armbian Base 内核 (${ARMBIAN_KERNEL_BRANCH}) ---"
    git clone --depth 1 -b ${ARMBIAN_KERNEL_BRANCH} https://github.com/armbian/linux-rockchip.git ${TEMP_DIR_ARMBIAN}
    if [ $? -ne 0 ]; then echo "❌ 克隆 Armbian 失败。"; exit 1; fi

    echo "--- 3. 克隆 CNflysky Target 内核 (${CNFLYSKY_KERNEL_BRANCH}) ---"
    git clone --depth 1 -b ${CNFLYSKY_KERNEL_BRANCH} https://github.com/CNflysky/linux-rockchip.git ${TEMP_DIR_CNFLYSKY}
    if [ $? -ne 0 ]; then echo "❌ 克隆 CNflysky 失败。"; exit 1; fi

    echo "--- 4. 生成补丁头信息 ---"
    # 创建补丁文件并写入补丁的描述信息,这是必须的。
    {
    echo "From: Redroid Contributor <cnflysky@users.noreply.github.com>"
    echo "Subject: [PATCH 0002] dma-heap: Add system-uncached-dma32 and necessary files for Redroid GPU"
    echo " "
    echo "---"
    } > "${PATCH_DIR}/${PATCH_FILE}"

    echo "--- 5. 按需提取差异并追加到补丁文件 ---"

    for path in "${TARGET_PATHS[@]}"; do
    echo "-> 提取差异: ${path}"

    # 使用 diff -Nurb 分别比较每个路径
    # 路径必须以 TEMP_DIR_ARMBIAN/path 和 TEMP_DIR_CNFLYSKY/path 形式提供
    diff -Nurb "${TEMP_DIR_ARMBIAN}/${path}" "${TEMP_DIR_CNFLYSKY}/${path}" >> "${PATCH_DIR}/${PATCH_FILE}"

    if [ $? -gt 1 ]; then
    echo "❌ 提取 ${path} 差异时发生错误,请检查文件是否存在。"
    exit 1
    fi
    done

    echo "✅ 新的干净补丁已生成并放置在 ${PATCH_DIR}/${PATCH_FILE}"

    echo "--- 6. 清理临时文件 ---"
    rm -rf ${TEMP_DIR_ARMBIAN} ${TEMP_DIR_CNFLYSKY}

    echo -e "\n--- 7. 后续操作 ---"
    echo "请确认您的 'userpatches/config/kernel/linux-${TARGET_KERNEL_BRANCH}.config' 中已包含以下配置:"
    echo "**CONFIG_ARM64_VA_BITS=39**,以及 **CONFIG_ANDROID_BINDERFS=y**, **CONFIG_PSI=y** 等 Redroid 所需项。"
    echo ""
    echo "现在回到您的 Armbian build 目录并重新运行编译:"
    echo " cd ${ARMBIAN_BUILD_DIR}"
    echo " ./compile.sh"

    运行脚本,生成补丁

    1
    ./generate_redroid_patch.sh
  5. 配置内核menuconfig

    1
    2
    cd build
    ./compile.sh BOARD=orangepi5-max BRANCH=vendor kernel-config # 此处的BOARD应该为你的开发板代号, 以获得合适的defconfig

    进入配置界面后,确保启用以下关键选项:

    必须启用的配置项:

    • CONFIG_ARM64_VA_BITS=39 (Kernel Features → Virtual Address Space Size)
      • 如果不启用, 某些APP(比如重返未来:1999)会在加载资源时崩溃

    需要检查并启用的配置项(一般无需更改, defconfig中默认启用):

    • CONFIG_ANDROID_BINDERFS=y (Device Drivers → Android → Android Binderfs)

      • 启用Android Binder文件系统支持
    • CONFIG_PSI=y (General setup → Pressure stall information tracking)

      • 内存压力监控,Android系统需要
    • CONFIG_ANDROID_BINDER_IPC=y (Device Drivers → Android)

      • Android核心IPC机制
    • DMA-BUF相关配置:

      • CONFIG_DMA_SHARED_BUFFER=y
      • CONFIG_DMABUF_HEAPS=y
      • CONFIG_DMABUF_SYSFS_STATS=y

    保存配置后退出。

  6. 编译内核

    1
    ./compile.sh BOARD=orangepi5-max BRANCH=vendor kernel

    编译过程可能需要1-2小时,取决于你的硬件配置。编译完成后,将生成的.deb包安装到你的Orange Pi设备上。

    踩坑记录:
    在进行完第5步后, 如果按照上面命令编译, 好像又是以默认配置编译的。 所以建议直接 ./compile.sh , 在TUI中手动选择好你的设备, 在界面更改配置后直接编译内核!!

  7. 安装编译好的内核
    将编译好的deb包传输到Orange Pi设备:

    1
    scp output/debs/*.deb root@192.168.1.100:/tmp/ # 改为你的设备地址

    在Orange Pi上安装:

    1
    2
    3
    cd /tmp
    sudo dpkg -i linux-*.deb
    sudo reboot

    重启后验证内核版本和必要设备:

    1
    2
    uname -r
    ls -la /dev/binderfs /dev/dma_heap/
  8. 检查是否支持所有特性
    我们使用CNflysky制作的脚本来快速检查是否成功地编译了支持所有特性的内核

    1
    curl -fsSL https://github.com/CNflysky/redroid-rk3588/raw/refs/heads/main/envcheck.sh | bash

    如果看到输出和下面截图一致, 则恭喜你已经成功了一大半.

    正常截图

安装 Docker 环境

请参考 Docker官方文档 进行安装.

1
2
# 允许非 root 用户使用 Docker
sudo usermod -aG docker $USER

注意: 执行 sudo usermod 后,必须退出终端并重新登录,才能使权限生效。

配置 Redroid 的 docker-compose

为了持久化数据和方便管理,我们使用 docker-compose

docker-compose.yml 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
services:
redroid:
image: cnflysky/redroid-rk3588:lineage-20
container_name: lineageos20
restart: unless-stopped
privileged: true
ports:
- "5555:5555" # 注意配置防火墙或更改端口加强安全性
volumes:
- "~/android_data:/data"
- "/dev/mali0:/dev/mali0"
command:
- "androidboot.redroid_gpu_mode=mali"
- "androidboot.redroid_width=1080"
- "androidboot.redroid_height=1920"
- "androidboot.redroid_fps=60"

# uncomment following line to enable magisk
# - "androidboot.redroid_magisk=1"

# uncomment following line to enable fake wifi
# - "androidboot.redroid_fake_wifi=1"
# - "androidboot.redroid_fake_wifi_ssid=CMCC-YeShouXianBei"
# - "androidboot.redroid_fake_wifi_bssid=11:45:14:19:19:81"
# - "androidboot.redroid_fake_wifi_mac=19:19:81:01:14:51"

运行 Redroid 容器

docker-compose.yml 所在目录下执行:

1
docker-compose up -d

Docker 会自动拉取镜像并启动云手机。

快速开始:使用预构建镜像

如果你不想经历漫长的内核编译过程,CNflysky 提供了预构建的 Armbian 镜像:

  1. 下载专门为 Orange Pi 5 优化的 Armbian 镜像(已包含所需内核)
  2. 直接烧录到存储介质
  3. 启动后安装 Docker 并运行 Redroid

获取方式: 访问 redroid-rk3588 Releases 页面下载。

注意: 预构建镜像可能不是最新版本,如果需要最新内核特性,仍建议自行编译。 而且作者只编译了Orangepi 5的镜像


🖥️ 远程访问与控制

配置 scrcpy

scrcpy (Screen Copy) 是一个轻量级、高性能的 Android 投屏和控制工具,是云手机的最佳搭档。

  1. 安装 scrcpy:
    在你的 PC/Mac/Linux 客户端上安装:

    1
    2
    sudo apt install scrcpy -y
    # 或者通过其他包管理器安装

    在Windows上:

    1
    winget install scrcpy # 仅windows高版本有
  2. 连接云手机: 通过 ADB 协议连接到你的 RK3588 设备 IP 和映射的端口 5555。

    1
    2
    3
    4
    # 假设你的 Orange Pi IP 是 192.168.1.100
    scrcpy -s 192.168.1.100:5555
    # 如果是在 RK3588 本地运行,则使用
    # scrcpy -s 127.0.0.1:5555

一个 Android 屏幕窗口会立刻弹出。你可以像使用真机一样操作它,而且由于 GPU 硬件加速的加持,画面会非常流畅。

成功运行并连接

scrcpy 高级用法

1
2
3
4
5
6
7
8
9
10
11
# 限制码率以适应较慢的网络
scrcpy -s 192.168.1.100:5555 -b 4M

# 降低分辨率以提升性能
scrcpy -s 192.168.1.100:5555 -m 1024

# 横屏显示
scrcpy -s 192.168.1.100:5555 --rotation 1

# 录制屏幕
scrcpy -s 192.168.1.100:5555 --record screen.mp4

❓ 常见问题与故障排除

问题现象 可能原因 解决方案
failed to access /dev/binder 内核未正确编译或未开启 binder 支持。 重新编译内核,确保 CONFIG_ANDROID_BINDER_IPC 被启用。
ADB device not found 容器端口未映射或 ADB 服务未启动。 检查 docker-compose.yml 中的 ports: "5555:5555" 是否正确,并使用 docker logs 确认 Redroid 启动日志。
画面卡顿/无硬件加速 GPU 设备透传失败。 确认 devices 配置是否正确,检查 /dev/dri 等设备文件是否存在且 Docker 用户有权限访问。RK3588 驱动可能需要特殊配置。
容器反复重启 内存分配不足或内核缺少关键驱动。 检查 REDROID_MEMORY 配置,确保分配了足够的内存(建议 ≥ 3GB)。 并检查内核是否配置了CONFIG_PSI=y
scrcpy 无法连接 GPU 加速失败或 system-uncached-dma32 设备缺失。 确认内核补丁已正确应用,检查 ls /dev/dma_heap/ 是否存在 system-uncached-dma32 设备。
应用闪退(比如《重返未来: 1999》) VA_BITS问题 确保内核配置了CONFIG_ARM64_VA_BITS=39

💡 应用场景拓展

搭建自己的云手机不只是一个技术玩具,它在许多场景下都非常实用:

  1. 自动化测试: 利用 ADB 和自动化框架(如 Appium),可以远程对容器内的应用进行批量、高效的自动化测试。

  2. 远程游戏挂机: 凭借 RK3588 强大的性能和低功耗特性,可以运行一些需要长期在线的 Android 游戏或应用。

  3. 隐私沙盒: 将一些可能涉及隐私的应用隔离在云手机内运行,与你的日常手机环境分离。

  4. 多开与多实例: 通过复制 docker-compose.yml 文件并修改端口、数据卷和内存配置,你可以轻松在一台 RK3588 上运行多个独立的云手机实例。

多实例配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
services:
redroid1:
image: cnflysky/redroid-rk3588:lineage-20
container_name: redroid_instance_1
privileged: true
ports:
- "5555:5555"
volumes:
- /opt/redroid/data1:/data
# ... 其他配置 ...

redroid2:
image: cnflysky/redroid-rk3588:lineage-20
container_name: redroid_instance_2
privileged: true
ports:
- "5556:5555" # 注意端口不能冲突
volumes:
- /opt/redroid/data2:/data
# ... 其他配置 ...

🔒 安全与隐私注意事项

在公网暴露云手机服务前,请务必注意以下安全问题:

  1. 启用 ADB 认证: 生产环境中应设置 ro.adb.secure=1,并配置 ADB 密钥认证。

  2. 防火墙配置: 不要直接将 5555 端口暴露到公网,建议使用 VPN 或 SSH 隧道访问:

    1
    2
    3
    4
    # 通过 SSH 隧道访问远程云手机
    ssh -L 5555:localhost:5555 user@your-orangepi-ip
    # 然后在本地连接
    scrcpy -s localhost:5555
  3. 定期更新: 及时更新 Redroid 镜像和系统内核,修复安全漏洞。

  4. 数据隔离: 不同用途的云手机实例应使用独立的数据卷,避免数据泄露。


📚 参考资料与扩展阅读


🎯 总结

通过本指南,我们完成了从零到一搭建基于 RK3588 的私有云手机系统。这个过程涉及了:

  • 内核编译: 为 Redroid 定制支持 system-uncached-dma32 的 Linux 内核
  • 容器化部署: 使用 Docker 快速启动和管理 Android 实例
  • 硬件加速: 充分利用 RK3588 的 GPU 和 VPU 资源
  • 远程控制: 通过 scrcpy 实现低延迟、高帧率的投屏体验
  • 性能优化: 从内存、CPU、GPU、存储等多方面调优

RK3588 凭借其强大的性能和开放的生态,为云手机、边缘计算等场景提供了理想的硬件平台。希望这篇指南能帮助你顺利搭建自己的 RK3588 云手机。如果你在实践中遇到任何问题,或者有更好的优化建议,欢迎在评论区分享交流!

(部分内容由Claude sonnet 4.5辅助完成, 经过人工修改、测试、审核, 可放心食用)