2. PURPOSE
• To understand important details of emulator.
• To get familiar with recent upstream changes and possibly ongoing plans.
• To evaluate upstream contribution process (for potential back porting).
• For fun, of course.
4. GET THE EMULATOR SOURCE
$ mkdir emu-master-dev && cd emu-master-dev
$ repo init -u https://android.googlesource.com/platform/manifest -b emu-master-dev
$ repo sync
emu-master-dev (~12GB) master (~36GB)
external
frameworks
prebuilts
sdk
tools
abi
art
bionic
bootable
build
cts
dalvik
developers
development
device
docs
external
frameworks
hardware
libcore
libnativehelper
Makefile
ndk
packages
pdk
prebuilts
sdk
system
toolchain
tools
5. BUILD THE EMULATOR
classic
- Use QEMU 0.10.5 since ~2009
- Android Cupcake ~ Lollipop
- Goldfish virtual platform
- @external/qemu
qemu2
- Use QEMU 2.2.0 since ~2015
- Android M ~
- Ranchu virtual platform
- @external/qemu-android
The classic and qemu2 emulator
$ cd external/qemu
$ ./android-rebuild.sh --build-qemu-android
Build both
the output is under objs directory
6. BUILD EMULATOR WITH QT
• Android Emulator is moving to Qt.
• In development. Unstable.
• Providing Tool Window.
• Default option remains SDL2.
$ cd external/qemu
$ ./android/scripts/download-sources.sh
$ ./android/scripts/build-qt.sh
$ ./android/scripts/build-libxml2.sh
$ ./android-rebuild.sh --ui=qt
7. APPARENTLY…
… android emulator should have a floating toolbox ?
Xamarin Android Player (VirtualBox) Visual Studio Emulator for Android (Hyper V)
8. EMULATOR BINARIES
- emulator: front-end used to find proper emulation engine and setup environment
variables (mainly LD_LIBRARY_PATH).
- green nodes: classic emulation engines.
- blue nodes: qemu2 emulation engines.
- orange nodes: GLES / EGL emulation libraries.
9. 3 WAYS TO LAUNCH EMULATOR
• Setup an Android Virtual Device, or
• Setup corresponding environment variables (in build-root), or
• Skip front-end and pass all arguments manually to emulation engine.
13. WRITABLE SYSTEM IMAGE
• system.img and userdata.img are read-only initial images.
• usedata-‐qemu.img is generated automatically on first launch.
• Temporarily writable system image is generated on each launch under /tmp.
• To make system image writable by default, move system.img to system-‐qemu.img.
• See emulator
-‐help-‐disk-‐images for more information
$ ls -lh /tmp/android-freesamael/
-rw------- 1 freesamael wheel 750M Sep 15 17:46 emulator-w1MQmT
17. MAIN LOOP
• The core of QEMU is event driven - by using an
event loop.
• Waits for file descriptors (files, sockets, pipes,…)
to become readable or writable.
• Polls charpipe (android-specific).
• Runs expired timers.
• Runs bottom-halves (BHs) scheduled by above
handlers.
20. SKIN (2/2) parts {
device {
display {
width 320
height 480
x 0
y 0
}
}
basic_controls {
background {
image basic.png
width 159
height 55
}
buttons {
volume-down {
image button.png
x 1
y 9
}
…
}
}
…
}
struct SkinSurface {
int refcount;
int w;
int h;
SDL_Surface* surface;
SDL_Texture* texture;
};
struct SkinSurface {
int refcount;
int id;
QImage *bitmap;
int w, h, original_w, original_h;
EmulatorQtWindow *window;
};
Layout Snippet
SDL2 SkinSurface
Qt SkinSurface
21. SKIN UI REFRESH
• Emulator skin refreshes at 60Hz by registered a timer to the main loop.
• gui_update() / nographic_update()
• Processes input events or passes them to the emulated system (multiple
events might be passed at the same time).
• Refresh the emulated framebuffer, if OpenGL emulation is not in use.
30. DESIGN
• Discoverability: which memory address and interrupt a device uses?
• Platform bus: a special platform device to enumerate other devices.
• Goldfish platform bus design
• MMIO address region 0xff001000 to 0xff801000.
• 0xff001000 - 0xff001fff are reserved by goldfish_device_bus as a set of
32bit I/O registers for bus operations.
• The bus itself uses IRQ 1 on ARM, IRQ 4 on x86.
31. I/O REGISTERS
Device properties:
Name: goldfish_device_bus
Id: -1
IrqCount: 1
32-bit I/O registers (offset, name, abstract)
0x00 BUS_OP R: Iterate to next device in enumeration.
W: Start device enumeration.
0x04 GET_NAME W: Copy device name to kernel memory.
0x08 NAME_LEN R: Read length of current device's name.
0x0c ID R: Read id of current device.
0x10 IO_BASE R: Read I/O base address of current device.
0x14 IO_SIZE R: Read I/O base size of current device.
0x18 IRQ_BASE R: Read base IRQ of current device.
0x1c IRQ_COUNT R: Read IRQ count of current device.
40. DESIGN
• Fast communication channel between guest and emulator.
• /dev/qemu_pipe or /dev/goldfish_pipe (since kernel 3.10).
• Kernel driver: drivers/misc/qemupipe/qemu_pipe.c
• No extra drivers necessary for QEMU Pipe Services.
• 4 pipe services implemented.
44. WORKFLOW (1/3)
• Kernel side:
• Sends the command PIPE_CMD_OPEN with a channel id.
• Emulator side:
• Generates a pipe connection with the given channel id.
• Generates a pipe connector, which has the interface as a pipe service,
on the pipe channel.
fd = open("/dev/qemu_pipe", O_RDWR);
const char* pipeName = "<pipename>";
ret = write(fd, pipeName, strlen(pipeName)+1);
if (ret < 0) {
// error
}
... ready to go
47. WORKFLOW (3/3)
+------+ +----------------+
| fd |<------pipe channel------>| pipe service |
+------+ +----------------+
/* Do the evil switch now */
pipe->opaque = peer;
pipe->service = svc;
pipe->funcs = &svc->funcs;
pipe->args = ASTRDUP(pipeArgs);
AFREE(pcon);
48. R/W WAITING
• When a service not able to consume more writes, or provide anything to
read temporarily: PIPE_ERROR_AGAIN.
• Kernel driver sends PIPE_CMD_WAKE_ON_READ/WRITE to wait.
• When service is available, emulator triggers an IRQ.
• Kernel reads
PIPE_REG_CHANNEL register to find the channel id, and
PIPE_REG_WAKES to find out what the event is (read / write / close).
55. SERVICE REGISTRATION
/* A function that will be called each time a new client in the emulated
* system tries to connect to a given qemud service. This should typically
* call qemud_client_new() to register a new client.
*/
typedef QemudClient* (*QemudServiceConnect)( void* opaque,
QemudService* service,
int channel,
const char* client_param );
QemudService*
qemud_service_register( const char* service_name,
int max_clients,
void* serv_opaque,
QemudServiceConnect serv_connect,
QemudServiceSave serv_save,
QemudServiceLoad serv_load );
56. ACCEPTING A CLIENT
/* A function that will be called when the client sends a message to the
* service through qemud.
*/
typedef void
(*QemudClientRecv) ( void* opaque, uint8_t* msg, int msglen, QemudClient* client );
extern QemudClient* qemud_client_new( QemudService* service,
int channel_id,
const char* client_param,
void* clie_opaque,
QemudClientRecv clie_recv,
QemudClientClose clie_close,
QemudClientSave clie_save,
QemudClientLoad clie_load );
57. CALLBACKS MAPPING
QEMU Pipe Callback QEMUD Callback Purpose
GoldfishPipeFuncs.init QemudServiceConnect accepting incoming client
GoldfishPipeFuncs.sendBuffers QemudClientRecv client is sendings messages
GoldfishPipeFuncs.recvBuffers - client is reading messages
GoldfishPipeFuncs.close QemudClientClose client closed connection
QEMUD services send messages to clients proactively through
qemud_client_send() or qemud_service_broadcast().
64. CHAR DRIVER STATE
• CharDriver is an object to operate on a specific type of char devices.
• TCPCharDriver with tcp_chr_ functions for TCP net console.
• CharDriverState forms an unified interface between a char driver and a
user operating on the char driver (often shorted as cs in code).
• CharDriver plays the backend of CharDriverState.
• Char devices are usually polled in the main loop (qemu_iohandler_poll).
69. CHAR BUFFER
• CharDriverState doesn’t tell how many bytes it can accept, nor notify
when it’s ready again.
• CharBuffer: a wrapper on top of CS with internal buffer to keep writing on
each polling until buffer empties.
• Simplify the implementation of a CharDriverState user.
+-------+ +-------------+ +--------------+
| QEMUD |------>| GSM Service |--CharBuffer-->| Radio Device |
+-------+ +-------------+ +--------------+
70. CHAR PIPE
• CharBuffer creates a write buffer on a CharDriverState;
CharPipe works as if 2 CharBuffers are connected to each other.
• Bidirectional communication channel between 2 CS users.
• Plays the backend of CS on both side. Writing on one endpoint triggers
the read handler on the other endpoint directly.
• CharBuffer / CharPipe rely on main loop polling (charpipe_poll).
+-------+ +-------------+ +-------------+
| QEMUD |------>| GSM Service |<---CharPipe--->| ModemDriver |
+-------+ +-------------+ +-------------+
82. QEMU2 EMULATOR STATUS
• Device Trees to replace Platform Bus.
• VirtIO to replace Goldfish NAND / MMC.
• QEMUD is completely abandoned / services porting is in progress.
• x86 support is still in development.
• No skin support yet.