通过VNC在Docker容器中连接Android模拟器(API 28出现错误)

4

我正在使用一个VNC客户端(Remmina)连接到运行在Docker容器中的Android模拟器,对于API 19到27都可以正常工作,但当使用VNC选项时会出现28错误(不使用VNC可以正常工作):

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

我的环境:

我的仓库/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

接下来,如果我运行启动模拟器的命令,在除了使用带有android-28(使用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

我认为错误来自于这个文件:

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

是否有一种方法可以使它与VNC一起工作?


哈。所以这只与API28有关?我遇到了同样的问题:https://stackoverflow.com/questions/57629274/emulator-headless-with-vnc-server - reardenlife
至少在我的情况下,它适用于所有API直到27,但不是28,我不知道发生了什么改变导致这样的错误,也不知道验证是否真的必要,但无论如何,它让我很难在非特权容器中进行测试(对于新设备)。 - Lucas Basquerotto
有一个文件:hardware-qemu.ini,位于~/.android/avd/android-28-x86.avd/中。与android-27唯一有意义的区别是:hw.gpu.enabled = true,hw.gpu.mode = swiftshared_indirect。我试图修改该文件,但它会反弹回来,好像它不是用于配置而是用于指示。我认为emulator-headless不尊重您指定的命令行选项,并认为使用主机gpu,这就是我们遇到的错误的原因。 - reardenlife
1个回答

2
我在模拟器-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).

所以它切换到了swiftshader_indirect,这使得它无法使用vnc。哎呀。

现在我想知道是否可以使用DISPLAY环境变量,使得emulator-headless将图形渲染到我们将使用其他VNC服务器创建的虚拟显示器中...

编辑: 是的,它似乎在每个Xeon核心3.3Ghz和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

我仍然不明白为什么安卓模拟器的开发人员决定在其产品中禁用vnc支持,如果一切在独立的vnc服务器上使用gpu软件仿真正常运行...?

编辑2:尽管如此,它总是会加载100%的CPU。 显然需要修复。 https://gist.github.com/yazinsai/652f0e6e77c9594a2356dd6314a9c3d8 如果您想实施,请告诉我。

那一定是原因。虽然应该有一种方法可以使用API28+与远程VNC,否则这种更改会在我的情况下破坏事物(实际上已经破坏了事物)。 - Lucas Basquerotto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接