From 92c5038d59884381abc451ec4647fea031ff68a5 Mon Sep 17 00:00:00 2001 From: Alexandre Richonnier Date: Tue, 20 Feb 2024 17:06:32 +0000 Subject: [PATCH] fix accel - add docker-compose - fix keys --- .gitignore | 86 +++++++++++++++++++++++++++++++ Dockerfile | 52 ++++++++++--------- Dockerfile.gpu | 59 +++++++++++----------- README.md | 39 ++++++++++++++ docker-compose.yml | 92 ++++++++++++++++++++++++++++++++++ scripts/emulator-monitoring.sh | 23 +++++++++ scripts/start-emulator.sh | 25 +++++++-- 7 files changed, 319 insertions(+), 57 deletions(-) create mode 100644 .gitignore create mode 100644 docker-compose.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7dfa935 --- /dev/null +++ b/.gitignore @@ -0,0 +1,86 @@ +keys +# Created by https://www.toptal.com/developers/gitignore/api/linux,macos,windows,powershell +# Edit at https://www.toptal.com/developers/gitignore?templates=linux,macos,windows,powershell + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### PowerShell ### +# Exclude packaged modules +*.zip + +# Exclude .NET assemblies from source +*.dll + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/linux,macos,windows,powershell \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 2305767..9eeb8f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,26 @@ -FROM adoptopenjdk/openjdk11:alpine-jre +FROM openjdk:18-jdk-slim + +ENV DEBIAN_FRONTEND noninteractive + +#WORKDIR / +#============================= +# Install Dependenices +#============================= +SHELL ["/bin/bash", "-c"] + +RUN apt update && apt install -y curl \ + sudo wget unzip bzip2 libdrm-dev \ + libxkbcommon-dev libgbm-dev libasound-dev libnss3 \ + libxcursor1 libpulse-dev libxshmfence-dev \ + xauth xvfb x11vnc fluxbox wmctrl libdbus-glib-1-2 socat \ + virt-manager + # Docker labels. LABEL maintainer "Halim Qarroum " LABEL description "A Docker image allowing to run an Android emulator" LABEL version "1.0.0" -# Installing required packages. -RUN apk update && \ - apk upgrade && \ - apk add --no-cache \ - bash \ - unzip \ - wget \ - libvirt-daemon \ - dbus \ - polkit \ - socat \ - virt-manager && \ - # Cleanup APK. - rm -rf /tmp/* /var/tmp/* /var/cache/apk/* # Arguments that can be overriden at build-time. ARG INSTALL_ANDROID_SDK=1 @@ -31,15 +33,15 @@ ARG GPU_ACCELERATED=false # Environment variables. ENV ANDROID_SDK_ROOT=/opt/android \ - ANDROID_PLATFORM_VERSION="platforms;android-$API_LEVEL" \ - PACKAGE_PATH="system-images;android-${API_LEVEL};${IMG_TYPE};${ARCHITECTURE}" \ - API_LEVEL=$API_LEVEL \ - DEVICE_ID=$DEVICE_ID \ - ARCHITECTURE=$ARCHITECTURE \ - ABI=${IMG_TYPE}/${ARCHITECTURE} \ - GPU_ACCELERATED=$GPU_ACCELERATED \ - QTWEBENGINE_DISABLE_SANDBOX=1 \ - ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL=10 + ANDROID_PLATFORM_VERSION="platforms;android-$API_LEVEL" \ + PACKAGE_PATH="system-images;android-${API_LEVEL};${IMG_TYPE};${ARCHITECTURE}" \ + API_LEVEL=$API_LEVEL \ + DEVICE_ID=$DEVICE_ID \ + ARCHITECTURE=$ARCHITECTURE \ + ABI=${IMG_TYPE}/${ARCHITECTURE} \ + GPU_ACCELERATED=$GPU_ACCELERATED \ + QTWEBENGINE_DISABLE_SANDBOX=1 \ + ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL=10 # Exporting environment variables to keep in the path # Android SDK binaries and shared libraries. @@ -60,7 +62,7 @@ RUN mkdir /root/.android/ && \ touch /root/.android/repositories.cfg # Exporting ADB keys. -COPY keys/* /root/.android/ +#COPY keys/* /root/.android/ # The following layers will download the Android command-line tools # to install the Android SDK, emulator and system images. diff --git a/Dockerfile.gpu b/Dockerfile.gpu index 2987139..31f058a 100644 --- a/Dockerfile.gpu +++ b/Dockerfile.gpu @@ -1,27 +1,29 @@ -FROM nvidia/cuda:12.1.0-base-ubuntu22.04 +FROM nvidia/cuda:12.3.1-base-ubuntu22.04 # Docker labels. LABEL maintainer "Halim Qarroum " LABEL description "A Docker image allowing to run an Android emulator" -LABEL version "1.1.0" +LABEL version "1.2.0" +ENV DEBIAN_FRONTEND noninteractive # Installing required packages. RUN apt update -y && \ - DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends \ - bash \ - unzip \ - wget \ - libvirt-daemon \ - dbus \ - openjdk-11-jdk \ - virt-manager \ - libvulkan1 \ - xvfb \ - libgl1-mesa-glx \ - libgl1-mesa-dri \ - socat \ - iproute2 && \ - rm -rf /var/lib/apt/lists/* + apt install -y --no-install-recommends \ + bash \ + unzip \ + wget \ + libvirt-daemon \ + dbus \ + openjdk-18-jre-headless \ + virt-manager \ + libvulkan1 \ + xvfb \ + libgl1-mesa-glx \ + libgl1-mesa-dri \ + socat \ + htop \ + iproute2 && \ + rm -rf /var/lib/apt/lists/* # Arguments that can be overriden at build-time. ARG INSTALL_ANDROID_SDK=1 @@ -34,15 +36,15 @@ ARG GPU_ACCELERATED=true # Environment variables. ENV ANDROID_SDK_ROOT=/opt/android \ - ANDROID_PLATFORM_VERSION="platforms;android-$API_LEVEL" \ - PACKAGE_PATH="system-images;android-${API_LEVEL};${IMG_TYPE};${ARCHITECTURE}" \ - API_LEVEL=$API_LEVEL \ - DEVICE_ID=$DEVICE_ID \ - ARCHITECTURE=$ARCHITECTURE \ - ABI=${IMG_TYPE}/${ARCHITECTURE} \ - GPU_ACCELERATED=$GPU_ACCELERATED \ - QTWEBENGINE_DISABLE_SANDBOX=1 \ - ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL=10 + ANDROID_PLATFORM_VERSION="platforms;android-$API_LEVEL" \ + PACKAGE_PATH="system-images;android-${API_LEVEL};${IMG_TYPE};${ARCHITECTURE}" \ + API_LEVEL=$API_LEVEL \ + DEVICE_ID=$DEVICE_ID \ + ARCHITECTURE=$ARCHITECTURE \ + ABI=${IMG_TYPE}/${ARCHITECTURE} \ + GPU_ACCELERATED=$GPU_ACCELERATED \ + QTWEBENGINE_DISABLE_SANDBOX=1 \ + ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL=10 # Exporting environment variables for keeping in the path # Android SDK binaries and shared libraries. @@ -60,10 +62,10 @@ EXPOSE 5554 5555 # Initializing the required directories. RUN mkdir /root/.android/ && \ - touch /root/.android/repositories.cfg + touch /root/.android/repositories.cfg # Exporting ADB keys. -COPY keys/* /root/.android/ +#COPY keys/* /root/.android/ # The following layers will download the Android command-line tools # to install the Android SDK, emulator and system images. @@ -76,6 +78,5 @@ RUN /opt/install-sdk.sh COPY scripts/start-emulator.sh /opt/ COPY scripts/emulator-monitoring.sh /opt/ RUN chmod +x /opt/*.sh - # Set the entrypoint ENTRYPOINT ["/opt/start-emulator.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 8ebc0e8..b2ff15c 100644 --- a/README.md +++ b/README.md @@ -45,10 +45,38 @@ Without SDK and emulator | 414 MB | 138 MB | By default, a build will bundle the Android SDK, platform tools and emulator with the image. +with docker-compose: + +```bash +docker compose up android-emulator +``` + +or with GPU acceleration +```bash +docker compose up android-emulator-cuda +``` + +or for example with GPU acceleration and google playstore +```bash +docker compose up android-emulator-cuda-store +``` + +with only docker + + ```bash docker build -t android-emulator . ``` +## Keys + +To run google_apis_playstore image, you need to have same adbkey between emulator and client. + +You can generate one by running `adb keygen adbkey`, that generates 2 files - adbkey and adbkey.pub. + +override them inside ./keys directory. + + ### Running the container Once the image is built, you can mount your KVM driver on the container and expose its ADB port. @@ -113,6 +141,17 @@ docker build \ --tag android-emulator . ``` +### Variables + +#### Disable animation +DISABLE_ANIMATION=false + +#### Disable hidden policy +DISABLE_HIDDEN_POLICY=true + +#### skip adb authentication +SKIP_AUTH=false + ### Mount an external drive in the container It might be sometimes useful to have the entire Android SDK folder outside of the container (stored on a shared distributed filesystem such as NFS for example), to significantly reduce the size and the build time of the image. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..4df14ef --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,92 @@ +version: "4" +services: + android-emulator: + build: + context: . + args: + - API_LEVEL=34 + - CMD_LINE_VERSION=11076708_latest + - IMG_TYPE=google_apis + ports: + - 5554:5554 + - 5555:5555 + environment: + - DISABLE_ANIMATION=false + - DISABLE_HIDDEN_POLICY=true + - SKIP_AUTH=false + #- ANDROID_ADB_SERVER_ADDRESS=host.docker.internal + privileged: true + tty: true + stdin_open: true + volumes: + - ./keys/adbkey:/root/.android/adbkey:ro + - ./keys/adbkey.pub:/root/.android/adbkey.pub:ro + extra_hosts: + - "host.docker.internal:host-gateway" + + android-emulator-cuda: + build: + context: . + dockerfile: ./Dockerfile.gpu + args: + - API_LEVEL=34 + - CMD_LINE_VERSION=11076708_latest + - IMG_TYPE=google_apis + ports: + - 5554:5554 + - 5555:5555 + environment: + - DISABLE_ANIMATION=false + - DISABLE_HIDDEN_POLICY=true + - SKIP_AUTH=false + #- ANDROID_ADB_SERVER_ADDRESS=host.docker.internal + privileged: true + tty: true + stdin_open: true + volumes: + - ./keys/adbkey:/root/.android/adbkey:ro + - ./keys/adbkey.pub:/root/.android/adbkey.pub:ro + extra_hosts: + - "host.docker.internal:host-gateway" + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: 1 + capabilities: [gpu] + + android-emulator-cuda-store: + build: + context: . + dockerfile: ./Dockerfile.gpu + args: + - API_LEVEL=34 + - CMD_LINE_VERSION=11076708_latest + - IMG_TYPE=google_apis_playstore + ports: + - 5554:5554 + - 5555:5555 + environment: + - DISABLE_ANIMATION=false + - DISABLE_HIDDEN_POLICY=true + - SKIP_AUTH=false + #- ANDROID_ADB_SERVER_ADDRESS=host.docker.internal + privileged: true + tty: true + stdin_open: true + volumes: + - ./keys/adbkey:/root/.android/adbkey:ro + - ./keys/adbkey.pub:/root/.android/adbkey.pub:ro + # volumes: + # - ./:/mnt + extra_hosts: + - "host.docker.internal:host-gateway" + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: 1 + capabilities: [gpu] + \ No newline at end of file diff --git a/scripts/emulator-monitoring.sh b/scripts/emulator-monitoring.sh index 7fabfd0..827a230 100644 --- a/scripts/emulator-monitoring.sh +++ b/scripts/emulator-monitoring.sh @@ -13,6 +13,19 @@ function update_state() { write_log "state-update" "$1" } +function disable_animation() { + adb shell "settings put global window_animation_scale 0.0" + adb shell "settings put global transition_animation_scale 0.0" + adb shell "settings put global animator_duration_scale 0.0" + echo "...Disable animations" +}; + +function hidden_policy() { + adb shell "settings put global hidden_api_policy_pre_p_apps 1;settings put global hidden_api_policy_p_apps 1;settings put global hidden_api_policy 1" + echo "...Hidden policy" +}; + + # Waits for the emulator to boot and writes # state updates on the standard output. function wait_for_boot() { @@ -30,5 +43,15 @@ function wait_for_boot() { COMPLETED=$(adb shell getprop sys.boot_completed | tr -d '\r') sleep 5 done + sleep 1 + if [ "$DISABLE_ANIMATION" = "true" ]; then + disable_animation + sleep 1 + fi + + if [ "$DISABLE_HIDDEN_POLICY" = "true" ]; then + hidden_policy + sleep 1 + fi update_state "ANDROID_READY" } \ No newline at end of file diff --git a/scripts/start-emulator.sh b/scripts/start-emulator.sh index 49a928d..36e1868 100644 --- a/scripts/start-emulator.sh +++ b/scripts/start-emulator.sh @@ -8,7 +8,10 @@ source ./emulator-monitoring.sh EMULATOR_CONSOLE_PORT=5554 # The ADB port used to connect to ADB. ADB_PORT=5555 - +MEMORY=16048 +CORES=10 +SKIP_AUTH=true +AUTH_FLAG= # Start ADB server by listening on all interfaces. echo "Starting the ADB server ..." adb -a -P 5037 server nodaemon & @@ -31,6 +34,10 @@ echo no | avdmanager create avd \ --package "$PACKAGE_PATH" \ --device "$DEVICE_ID" +if [ "$SKIP_AUTH" == "true" ]; then + AUTH_FLAG="-skip-adb-auth" +fi + # If GPU acceleration is enabled, we create a virtual framebuffer # to be used by the emulator when running with GPU acceleration. # We also set the GPU mode to `host` to force the emulator to use @@ -48,10 +55,22 @@ fi wait_for_boot & # Start the emulator with no audio, no GUI, and no snapshots. -echo "Starting the emulator ..." +echo "Starting the emulator ... " +echo "OPTIONS: " +echo "GPU - $GPU_MODE" +echo "MEMORY - $MEMORY" +echo "CORES - $CORES" emulator \ -avd android \ -gpu "$GPU_MODE" \ + -memory $MEMORY \ -no-boot-anim \ + -cores $CORES \ + -ranchu \ + $AUTH_FLAG \ -no-window \ - -no-snapshot || update_state "ANDROID_STOPPED" + -no-snapshot || update_state "ANDROID_STOPPED" + + + # -qemu \ + # -smp 8,sockets=1,cores=4,threads=2,maxcpus=8 \ No newline at end of file