Skip to main content

ReDroid. Playing Android games in containers on Linux PC, with GPU Acclelration

Linux Virtual Machine and Container Android Docker Linux
Table of Contents

中文版

ReDroid (Remote anDroid) is an open source and self-hosting “cloud phone” solution. By running Android in containers on Linux PC, we could access Android desktop by using Scrcpy. And the container could be accessed remotely.

Here is my demonstration of what “self-hosting cloud phone” looks like. In this video, I install Scrcpy client on iPhone and connect to Linux PC using Zerotier to play Android games remotely. (sorry my video is in Chinese)

ReDroid is also one of the few solutions to run Android APP on Linux with open source software. Many Android simulators, not to mention cloud phones, are closed source. In contrast, ReDroid is an open source solution except for the ARM translator. Even better, ReDroid supports GPU acceleration plus ARM translations, so you can play more mobile 3D games!

ReDroid is much light-weight and easy to deploy than Android-x86 VM.

If you ask me, there is already a similar, container-based solution, which is known as Waydroid for playing Android games. Why do I choose ReDroid over Waydroid? Well freak Nvidia. Waydroid does not work on Nvidia GPU.

In this article, I will discuss how to use ReDroid to play mobile games on Linux PC. We will setup a container, and add ARM translator + Google Service Framework to the ReDroid image for the best experience.

1. Prerequisites
#

If you want to use ReDroid to play mobile games, it is recommended that you have at least 8GB of RAM on your PC, because sometimes ARM translator will take up a lot of RAM when translating ARM to x86 instructions.

There are installation instructions for all Linux distributions of ReDroid on Github, include WSL.

  1. Since I am using Arch Linux, I have to change the kernel to linux-zen. After installing the linux-zen kernel, update the GRUB options. Reboot and select linux-zen kernel in Advanced Options of GRUB menu.
# If you have an Nvidia driver, remember to replace it with the DKMS version
sudo pacman -R nvidia
sudo pacman -S nvidia-dkms
# Make sure binder_linux-dkms is not installed.
yay -R binder_linux-dkms

# Install linux-zen kernel
sudo pacman -S linux-zen linux-zen-headers
sudo mkinitcpio -p linux-zen
sudo grub-mkconfig -o /boot/grub/grub.cfg
  1. Install Docker to run the container.

  2. Install ADB and Scrcpy. Scrcpy now includes sndcpy.

sudo pacman -S android-tools
sudo pacman -S scrcpy

* If you want a graphical Scrcpy frontend with key mapping, you can install QtScrcpy instead.

2. Create a Redroid virtual machine
#

This step is only required for Nvidia graphics card users, because the Nvidia propertiary driver cannot let Redroid to use GPU acceleration. You need to run a QEMU virtual machine, and then install Redroid in it to achieve hardware acceleration through Virtio-GPU. Otherwise, Redroid will use software rendering.

Reference 在使用 NVIDIA 显卡时为 redroid 开启3d加速 redroid nVidia GPU support #282

  1. Download Ubuntu 22.04 ISO, install QEMU + Virt Manager, and create a 64GB Ubuuntu virtual machine
qemu-img create -f qcow2 ubuntu.qcow2 64GB
qemu-system-x86_64 -boot d -cdrom "ubuntu-22.04.1-desktop-amd64.iso" -enable-kvm -smp 4 -device intel-hda -device hda-duplex -device virtio-vga-gl -net nic -net user,hostfwd=tcp::5555-:5555 -cpu host -m 4096 -display sdl,gl=on -hda ubuntu.qcow2
  1. Boot into the virtual machine, and then install Docker in it.
qemu-system-x86_64 c -enable-kvm -smp 4 -device intel-hda -device hda-duplex -device virtio-vga-gl -net nic -net user,hostfwd=tcp::5555-:5555 -cpu host - m 4096 -display sdl,gl=on -hda ubuntu.qcow2

3. Launch ReDroid
#

Most computers are x86 architecture, and can only run x86 version of Android APP. However, many mobile games only have ARM version, so ReDroid needs a ARM translator.

The redroid:11.0.0-latest and redroid:12.0.0-latest images released by the author of ReDroid have built-in libndk, an ARM translator developed by Google. From what I test, Android 11 image is the stable version, and the Gapps can be isntalled, so we will take Android 11 as an example.

  1. Create a directory for storing your data. Create docker-compose.
mkdir ~/redroid
cd redroid
vim docker-compose.yml
  1. Fill in the following
version: "3"
services.
  redroid.
    image: redroid/redroid:11.0.0-latest
    stdin_open: true
    tty: true
    privileged: true
    ports: "5555:5555
      - "5555:5555"
    volumes.
    # Data is stored in the current directory
      - . /redroid-11-data:/data
    command.
    # Enable GPU hardware acceleration.
      - androidboot.redroid_gpu_mode=auto
    # libndk related parameters
      - ro.product.cpu.abilist0=x86_64,arm64-v8a,x86,armeabi-v7a,armeabi
      - ro.product.cpu.abilist64=x86_64,arm64-v8a
      - ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi
      - ro.dalvik.vm.isa.arm=x86
      - ro.dalvik.vm.isa.arm64=x86_64
      - ro.enable.native.bridge.exec=1
      - ro.dalvik.vm.native.bridge=libndk_translation.so
      - ro.ndk_translation.version=0.2.2
  1. Start the container
sudo docker compose up -d
  1. Connect to the local ReDroid using ADB:
adb connect localhost:5555

# If it doesn't connect, use the following command to see what's going on inside the container.
sudo docker exec <container ID> logcat
sudo docker logs <container ID> logcat
  1. Run Scrcpy to connect to the Android desktop:
scrcpy -s localhost:5555 --audio-codec=raw
  1. This will bring you to the Android desktop.

4. Install Google Service Framework (GAPPS)
#

The author says that Google Service Framework is proprietary software and cannot be built-in in ReDroid, so you have to install it by yourself. The first method is to recompile the Android image. Tthe second is to install OpenGApps manually.

The first method is not recommended, it’s time consuming and the GApps compilation tutorial provided by the author has problems that the gapps can’t be detected by other apps.

Here I choose the second method: manual installation of gapps. Reference: Install GApps Manually - Google Groups

  1. Go to OpenGapps. Download Android 11 GApps with x86_64 architecture, and choose the minimized pico version.

  2. Unzip it and you will see the following directory

open_gapps-x86_64-11.0-pico-20220503
├── Core
├── GApps
├── META-INF
├── Optional
  1. Create a folder named system under open_gapps-x86_64-11.0-pico-20220503

  2. Next, extract the .lz files in the Core and GApps directories and move the APK in the system directory to the corresponding installation directory. For example, the GoogleTTS directory under GApps/googletts-x86_64/nodpi/app/ should be placed in /system/app.

  3. So the directory structure under system should look like this:

system
├── app
│   ├── GoogleCalendarSyncAdapter
│   │   └── GoogleCalendarSyncAdapter.apk
│   ├── GoogleContactsSyncAdapter
│   │   └── GoogleContactsSyncAdapter.apk
│   ├── GoogleExtShared
│   │   └── GoogleExtShared.apk
│   └── GoogleTTS
│       └── GoogleTTS.apk
├── etc
│   ├── default-permissions
│   │   ├── default-permissions.xml
│   │   └── opengapps-permissions-q.xml
│   ├── permissions
│   │   ├── com.google.android.dialer.support.xml
│   │   ├── com.google.android.maps.xml
│   │   ├── com.google.android.media.effects.xml
│   │   ├── privapp-permissions-google.xml
│   │   └── split-permissions-google.xml
│   ├── preferred-apps
│   │   └── google.xml
│   └── sysconfig
│       ├── dialer_experience.xml
│       ├── google_build.xml
│       ├── google_exclusives_enable.xml
│       ├── google-hiddenapi-package-whitelist.xml
│       └── google.xml
├── framework
│   ├── com.google.android.dialer.support.jar
│   ├── com.google.android.maps.jar
│   └── com.google.android.media.effects.jar
├── priv-app
│   ├── AndroidAutoPrebuiltStub
│   │   └── AndroidAutoPrebuiltStub.apk
│   ├── AndroidMigratePrebuilt
│   │   └── AndroidMigratePrebuilt.apk
│   ├── CarrierSetup
│   │   └── CarrierSetup.apk
│   ├── ConfigUpdater
│   │   └── ConfigUpdater.apk
│   ├── GoogleBackupTransport
│   │   └── GoogleBackupTransport.apk
│   ├── GoogleExtServices
│   │   └── GoogleExtServices.apk
│   ├── GoogleFeedback
│   │   └── GoogleFeedback.apk
│   ├── GoogleOneTimeInitializer
│   │   └── GoogleOneTimeInitializer.apk
│   ├── GooglePackageInstaller
│   │   └── GooglePackageInstaller.apk
│   ├── GooglePartnerSetup
│   │   └── GooglePartnerSetup.apk
│   ├── GoogleRestore
│   │   └── GoogleRestore.apk
│   ├── GoogleServicesFramework
│   │   └── GoogleServicesFramework.apk
│   ├── Phonesky
│   │   └── Phonesky.apk
│   ├── PrebuiltGmsCore
│   │   └── PrebuiltGmsCore.apk
│   └── SetupWizard
│       └── SetupWizard.apk
└── product
    └── overlay
        └── PlayStoreOverlay.apk
  1. Execute the following command to obtain root privileges:
adb connect localhost:5555
adb -s localhost:5555 root
adb -s localhost:5555 remount
adb -s localhost:5555 shell "rm -rf system/priv-app/PackageInstaller"
  1. Then push the system directory to the ReDroid system and give it permission:
adb -s localhost:5555 push system /
adb -s localhost:5555 shell "pm grant com.google.android.gms android.permission.ACCESS_COARSE_LOCATION"
adb -s localhost:5555 shell "pm grant com.google.android.gms android.permission.ACCESS_FINE_LOCATION"
adb -s localhost:5555 shell "pm grant com.google.android.setupwizard android.permission.READ_PHONE_STATE"
adb -s localhost:5555 shell "pm grant com.google.android.setupwizard android.permission.READ_CONTACTS"
adb reboot
  1. Reboot the ReDroid container:
cd ~/redroid
sudo docker compose down
sudo docker compose up -d
  1. Starting Scrcpy
scrcpy -s localhost:5555 --audio-codec=raw
  1. Open System Settings → Apps, tap “Show System Apps” in the upper right corner, and turn on both Google Play Services and Play Store permissions.

  2. Run the following command to get the Android device ID, go to Google website to register the device, wait for 30 minutes and restart the Redroid container to login to Google Play.

adb -s localhost:5555 root
adb -s localhost:5555 shell 'sqlite3 /data/data/com.google.android.gsf/databases/gservices.db \
    "select * from main where name = \"android_id\";"'

5. Install APK to ReDroid
#

At present, even if you have installed libndk, the Play Store still doesn’t allow you to download apps with ARM architecture, so please install apps from APKPure or other app stores.

In addition to using the container’s internal browser to download APK, you can also use ADB to install APK to ReDroid container. For example, go to ApkMirror to download the APK of Line, and then install it with ADB:

adb -s localhost:5555 install "jp.naver.line.android.apk"

You can also transfer files using ADB’s pull and push commands.

For screen resolution adjustment, see the instructions for ReDroid and Scrcpy.

5. How to “turn off” ReDroid
#

To shut down ReDroid, close the Scrcpy window and stop the container:

cd ~/redroid
sudo docker compose down

You can then use following command to start ReDroid. the /data data for the ReDroid container is located in the ~/redroid/redroid-11-data directory, which can be used to back up files from multiple systems.

cd ~/redroid
sudo docker compose up -d
adb connect localhost:5555
scrcpy -s localhost:5555

For your reference: Manually extracting libndk from Android Studio emulators
#

libndk is a proprietary software developed by Google, which is included in Android Studio emulator. According to the ReDroid author’s instructions, we can manually extract libndk from the new version of Android emulator and add it to lastest ReDroid image.

Taking Android 13 as an example, note that the author does not guarantee that this will work.

  1. Install Android Studio and add a new virtual machine for Android 13.

  2. Connect to the emulator via ADB

adb devices
adb shell
adb shell
  1. Create a archive of libndk
{ find /system -name arm* -type d; find /system -name *ndk_translation*; find /system/etc -name *arm*; } | tar -cf /sdcard/nb.tar -T -
  1. Create a archive of libndk.so
find system -type l | tar -cf /sdcard/so.tar -T -
  1. Exit ADB and transfer the above files back to the host
exit
exit
adb pull /sdcard/nb.tar .
adb pull /sdcard/so.tar .
  1. Add libndk.so to libndk’s archive.
tar -xvf so.tar
find system -type l | tar -rf libndk_translation.tar -T -
  1. Creatr a DOCKEEFILE with the following contents:
FROM redroid/redroid:13.0.0-latest

ADD libndk_translation.tar /
  1. Start building the Android 13 image with libndk, then the image redroid:13.0.0-libndk can be used to run the other containers.
docker build . -t redroid:13.0.0-libndk

Related

[Root] Running docker container on Redmi Note 5 Pro
Smartphone Root and Custom Rom Termux Android Linux Docker
Pine64 PineTab 2 unboxing and review by Ivon Huang
Smartphone Linux Phone Pine64 Android Linux
[Guide] Playing Android games on Linux PC with Android-x86 VM + QtScrcpy
Linux Virtual Machine and Container Android-X86 QEMU

Leave a comment

Choose the comment system you like. Giscus for codes, Disqus for anonymous comments.

Please login to your Github account to leave a comment. You can post codes here for discussion. For images, please upload to Imgur and copy links. Your comments would be visible to everyone on Github Discussions.

This comment system is provided by Disqus, you may see forcing Disqus ADs on this page. Sometimes your comment may need to be reviewed, resulting in delayed display. Thank you for your understanding.