Skip to content

Instantly share code, notes, and snippets.

@mrk-han
Last active February 27, 2024 06:47
Show Gist options
  • Save mrk-han/fa5c6e8951919b7efc1ba99fcd10496e to your computer and use it in GitHub Desktop.
Save mrk-han/fa5c6e8951919b7efc1ba99fcd10496e to your computer and use it in GitHub Desktop.
how to use experimental gRPC to control android emulators [Rough fork of GRPC MD from AOSP]

Emulator over gRPC Examples

Thanks to Erwin Jansen for these samples and this readme. (I just formatted this and threw it in a gist to make it more shareable and readable)

Samples can be downloaded here: https://android.googlesource.com/platform/external/qemu/+/refs/heads/emu-master-dev/android/android-grpc/docs/grpc-samples

Caveats: Experimental feature!!

This is currently an experimental feature, and as such there are some things lacking that might be important if you want to use this in production:

  • There is no authentication/authorization. The gRPC server does not do any authentication nor authorization. Anyone who has access to the gRPC control port can control your emulator
  • No TLS support. Currently the gRPC service inside the emulato has not turned on TLS.
  • Not all emulator control functions have been enabled. This likely means that the .proto file describing the interface will evolve.

In other words, make sure you keep this port private on your network and be ready to recompile your code when changes happen.

DO NOT RUN THIS AS IS IN A PRODUCTION ENVIRONMENT

Introduction

This document describes how you can control the emulator over the gRPC interface. To learn more about gRPC you can visit the website.

We describe several sample cases.

  • One where we will use the GO language to create a webserver that allows you to control the emulator over http.

  • An example demonstrates how you can use Javascript & React to control the emulator.

  • An example that uses the python bindings.

Note that this is still under active development, so more functionality might be added in the future.

In general all the approaches work in a similar fashion:

  1. Create the grpc bindings using protoc
  2. Place the generated bindings in the right location.
  3. Configure the EmulatorService, (i.e. set port, authentication etc.)
  4. Make calls to the emulator.

Enabling gRPC in the build

You must enable gRPC in the build, either by editing CMakeLists.txt and setting GRPC to TRUE or by building as follows:

   ./android/rebuild --cmake_option GRPC=TRUE

This will compile in the gRPC feature.

Controlling the emulator with http.

In this example we will construct an intermediate server that acts as a webserver. The webserver will enable an API that is forwarded to the emulator.

In order to run this sample you will need to have a working Go environment. You can find a Go distribution and learn more about Go here

Note: The example requires you to have the ports 5556 & 8080 available

Installation

First you need to install ProtocolBuffers 3.0.0-beta-3 or later. The installation depends on your OS.

I'm using homebrew (Mac/Linux)

Your best bet is to use homebrew and use the following

  $ brew install protobuf

I'm using linux

You must make sure you have a recent version of protobuf available:

$ mkdir tmp && cd tmp
$ git clone https://github.com/google/protobuf && cd protobuf
$ ./autogen.sh && ./configure
$ make  check
$ sudo make install

Launch the emulator and webserver

Before we can access the emulator we must launch it with the gRPC server enabled.

  $ emulator @my_avd -grpc 5556 [..other options...]

Once the emulator is launched you can build and launch the web service as follows:

  $ cd $AOSP/external/qemu/android/android-grpc/docs/grpc-samples/go && make deps && make run

Now you should be able to access the emulator over http on port 8080. For example: http://localhost:8080/v1/gps will show you the current gps settings.

The following example will send a keycode to the emulator:

curl -H "Accept: application/json" -X POST -d '{"key": "30"}' http://localhost:8080/v1/key

For more details on the endpoints look at https://android.googlesource.com/platform/external/qemu/+/refs/heads/emu-master-dev/android/android-grpc/android/emulation/control/api_config.yaml

Troubleshooting:

  • I see the following json:

      {"error":"all SubConns are in TransientFailure, latest connection error: connection error: desc = \"transport: Error while dialing dial tcp [::1]:5556: connect: connection refused\"","message":"all SubConns are in TransientFailure, latest connection error: connection error: desc = \"transport: Error while dialing dial tcp [::1]:5556: connect: connection refused\"","code":14}

    You likely restarted the emulator, restart the httpbridge.

  • Why are screenshots slow in debug builds?

    The emulator enables a lot of checks (address sanitizers, code coverage) that take up a lot of resources. You might be better of using a release build.

Controlling the emulator from JavaScript with React

The javascript example showcases how you can interact with the emulator by displaying the current screeenshot, and sending mouse events to the emulator.

The sample consists of two react components:

  • Emulator -> Responsible for sending mouse clicks, and hosting a view
  • EmulatorPngView -> Responsible for displaying a view of the emulator. (Very slow)

In the future we hope to replace the EmulatorPngView with something like an EmulatorWebRTCView that has significantly better performance characteristics.

In order to control the emulator from Javascript we will have to route the calls through an intermediate proxy. We will usegRPC-web to make it all possible.

Requirements

In order to run the demo you will need Node, dep and a protoc plugin to generate the javascript classes.

Your best bet is to use homebrew and use the following

  $ brew install dep npm

or else follow the documentation here: https://golang.github.io/dep/docs/installation.html

If you are planning to modify .proto files you willneed to acquire the proper protoc plugin from here. You can either build it yourself, or install the binary.

Launch the emulator and website

In order to launch this demo you will need the following ports available:

  • 5556 Emulator gRPC port
  • 8080 gRPC JavaScript proxy
  • 3000 npm developer port.

Before we can access the emulator we must launch it with the gRPC server enabled.

  $ emulator @my_avd -grpc 5556 [..other options...]

Once the emulator is launched you can build and launch the web application as follows:

  $ cd $AOSP/external/qemu/android/android-grpc/docs/grpc-samples/js  && make deps && make develop

Note: Make deps is only needed once

A browser should open and you should be able to interact with the emulator.

You can stop all the components by running:

  $ cd $AOSP/external/qemu/android/android-grpc/docs/grpc-samples/js  && make stop

Note: this will just kill npm and the proxy

Controlling the emulator with Python

In the python directory you will find an example that aks the emulator about the vm configuration after which it will send a series of key events with a 2ms delay.

Before we can access the emulator we must launch it with the gRPC server enabled.

  $ emulator @my_avd -grpc 5556 [..other options...]

Once the emulator is launched you can build and run the sample as follows:

  $ make deps && make run
@UsingtcNower
Copy link

Hi,
Seems that the above aosp link are not existed, could you please update it?

@mrk-han
Copy link
Author

mrk-han commented Jun 8, 2020

@UsingtcNower

Hey, check out https://github.com/google/android-emulator-container-scripts

I suggested they open-source this content and they did! So, now all of this is better supported in the link above.

Thanks for the comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment