4

I'm using a VNC client (Remmina) to connect to an Android Emulator running in a Docker container, and it worked with APIs from 19 to 27, but 28 errors when using with the VNC option (but works without VNC):

qemu-system-x86_64: VNC supports only guest GPU, add "-gpu guest" option

My environment:

myrepo/app-tools:android-dev-1.0.2

FROM ubuntu:18.04

ENV DEBIAN_FRONTEND noninteractive
RUN echo "debconf shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections && \
    echo "debconf shared/accepted-oracle-license-v1-1 seen true" | debconf-set-selections

ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip" \
    ANDROID_HOME="/usr/local/android-sdk" \
    ANDROID_VERSION="28" \
    ANDROID_BUILD_TOOLS_VERSION="28.0.3" \
    GRADLE_VERSION="5.0"
ENV GRADLE_URL="https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" \
    GRADLE_HOME="/opt/gradle/gradle-${GRADLE_VERSION}" \
    PATH="/opt/gradle/gradle-${GRADLE_VERSION}/bin:${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools"

COPY android/repositories.cfg /root/.android/

# Download JDK-8 and fix certificate issues
RUN apt-get update \ 
 && apt-get install -y openjdk-8-jdk \
 && apt-get install -y ant \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/* \
 && rm -rf /var/cache/oracle-jdk8-installer \
 && apt-get update \ 
 && apt-get install -y ca-certificates-java \
 && apt-get clean \
 && update-ca-certificates -f \
 && rm -rf /var/lib/apt/lists/* \
 && rm -rf /var/cache/oracle-jdk8-installer

# Download Android SDK
RUN cd /tmp \
 && apt-get update \
 && apt-get install -y nano zip curl net-tools socat \
 && curl -o gradle.zip -L "$GRADLE_URL" \
 && unzip -d /opt/gradle gradle.zip \
 && rm gradle.zip \
 && mkdir "$ANDROID_HOME" .android \
 && cd "$ANDROID_HOME" \
 && curl -o sdk.zip $SDK_URL \
 && unzip sdk.zip \
 && rm sdk.zip \
 && yes | "$ANDROID_HOME/tools/bin/sdkmanager" --licenses \
 && "$ANDROID_HOME/tools/bin/sdkmanager" --update \
 && "$ANDROID_HOME/tools/bin/sdkmanager" \
    "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
    "platforms;android-${ANDROID_VERSION}" \
    "platform-tools" \
    "emulator"

RUN mkdir /main
WORKDIR /main

android/repositories.cfg

### User Sources for Android SDK Manager
#Fri Nov 03 10:11:27 CET 2017 count=0

android-dev.dockerfile

FROM myrepo/app-tools:android-dev-1.0.2

ENV ANDROID_SDK="/usr/local/android-sdk"
ENV PATH="$ANDROID_SDK/emulator:$ANDROID_SDK/tools:$PATH"

RUN /usr/local/android-sdk/tools/bin/sdkmanager "system-images;android-19;google_apis;x86" \
 && /usr/local/android-sdk/tools/bin/sdkmanager --licenses

RUN /usr/local/android-sdk/tools/bin/sdkmanager "system-images;android-23;google_apis;x86" \
 && /usr/local/android-sdk/tools/bin/sdkmanager --licenses

RUN /usr/local/android-sdk/tools/bin/sdkmanager "system-images;android-28;google_apis;x86" \
 && /usr/local/android-sdk/tools/bin/sdkmanager --licenses

RUN /usr/local/android-sdk/tools/bin/avdmanager create avd -n avd19 -k "system-images;android-19;google_apis;x86" -b x86 -d 7 -f \
 && /usr/local/android-sdk/tools/bin/avdmanager create avd -n avd23 -k "system-images;android-23;google_apis;x86" -b x86 -d 7 -f \
 && /usr/local/android-sdk/tools/bin/avdmanager create avd -n avd28 -k "system-images;android-28;google_apis;x86" -b x86 -d 7 -f

COPY scripts/android-dev-startup.sh /root/start.sh

scripts/android-dev-startup.sh

#!/bin/bash
set -eou pipefail

socat tcp-listen:5037,bind=android-dev,fork tcp:127.0.0.1:5037 &
socat tcp-listen:5554,bind=android-dev,fork tcp:127.0.0.1:5554 &
socat tcp-listen:5555,bind=android-dev,fork tcp:127.0.0.1:5555 &

sleep infinity

docker-compose

android-dev:
  build: 
    context: ./
    dockerfile: android-dev.dockerfile
  hostname: android-dev
  volumes:
  - .:/main:rw
  devices:
  - "/dev/kvm:/dev/kvm"
  ports:
  - "5037:5037"
  - "5554:5554"
  - "5555:5555"
  - "5900:5900"
  command: /root/start.sh

Then, if I run the command to start the emulator, it works in all cases except when using the emulator with android-28 (when using VNC):

# works
emulator -memory 4096 -avd avd19 -noaudio -no-window -gpu off -verbose -qemu -vnc :0

# works
emulator -memory 4096 -avd avd23 -noaudio -no-window -gpu off -verbose -qemu -vnc :0

# works
emulator -memory 4096 -avd avd28 -noaudio -no-window -gpu off -verbose -qemu

# doesn't work
# qemu-system-x86_64: VNC supports only guest GPU, add "-gpu guest" option
emulator -memory 4096 -avd avd28 -noaudio -no-window -gpu off -verbose -qemu -vnc :0

# doesn't work
# qemu-system-x86_64: VNC supports only guest GPU, add "-gpu guest" option
emulator -memory 4096 -avd avd28 -noaudio -no-window -gpu guest -verbose -qemu -vnc :0

I think the error comes from this file:

https://android.googlesource.com/platform/external/qemu/+/emu-master-dev/vl.c

Is there a way to make it work with VNC?

Lucas Basquerotto
  • 7,260
  • 2
  • 47
  • 61
  • Ha. So it is only related to API28? I encountered the same issue: https://stackoverflow.com/questions/57629274/emulator-headless-with-vnc-server – reardenlife Aug 25 '19 at 04:12
  • At least in my case it worked with all APIs till 27, but not 28, I don't know what changed to give such error, nor if the validation is really necessary, but in any case it is making it hard for me to test in non privileged containers (for new devices). – Lucas Basquerotto Aug 25 '19 at 11:09
  • There is a file: hardware-qemu.ini inside ~/.android/avd/android-28-x86.avd/. The only meaningful difference from android-27 is that: hw.gpu.enabled = true, hw.gpu.mode = swiftshared_indirect. I tried to modify that file, but it keeps bounce back as though it is not for configuration but for indication. I think emulator-headless doesn't respect options from command line you specify and deem to use host gpu that's why we are getting the error mentioned. – reardenlife Aug 26 '19 at 00:20

1 Answers1

2

I found something interesting in the output of the emulator-headless:

emulator: WARNING: Your AVD has been configured with an in-guest renderer, but the system image does not support guest rendering.Falling back to 'swiftshader_indirect' mode.
emulator: GPU emulation enabled using 'swiftshader_indirect' mode
emulator: Initializing hardware OpenGLES emulation support

https://androidstudio.googleblog.com/2018/11/emulator-28016-stable.html?m=1

-gpu guest (software rendering in the guest) has been deprecated. API 28+ system images will now auto switch to using Swiftshader (-gpu swiftshader_indirect).

So it switches to swiftshader_indirect, which makes it unable to use vnc. Uh oh.

So now I wonder if one can use environmental variable DISPLAY to make emulator-headless render the graphics into virtual display that one will create with some another VNC server...

Edit: Yes, it seems to be working well on 2 Xeon cores 3.3Ghz each and 4GB RAM.

echo 'no' | avdmanager create avd --force --name android-28-x86 --abi google_apis_playstore/x86 --package 'system-images;android-28;google_apis_playstore;x86'

apt install tightvnc
apt install xfonts-base
sudo apt-get install gnome-core xfce4 firefox nano -y --force-yes

# ~/.vnc/xstatup
unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS startxfce4 & [ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources xsetroot -solid grey vncconfig -iconic &

vncserver :2 -geometry 1080x1920 -depth 24
export DISPLAY=:2.0
emulator @android-28-x86 -verbose -memory 2048 -gpu swiftshader_indirect -no-audio -no-snapshot -wipe-data -no-boot-anim -skin 768x1280

I still have no idea why the android emulator developers decided to disable vnc support in their product if everything works well with gpu software emulation on standalone vnc server..?

Edit2: It always loads CPU 100% though. Apparently it requires a fix. https://gist.github.com/yazinsai/652f0e6e77c9594a2356dd6314a9c3d8 LMK if you want to implement it.

reardenlife
  • 317
  • 4
  • 15
  • That must be the reason. Although it should have a way to use API28+ with a remote VNC otherwise that change would break things in my case (it's already breaking things, actually). – Lucas Basquerotto Aug 26 '19 at 11:55