David Turner | 4735694 | 2009-04-05 14:23:06 -0700 | [diff] [blame] | 1 | THE ANDROID "QEMUD" MULTIPLEXING DAEMON |
| 2 | |
| 3 | I. Overview: |
| 4 | ------------ |
| 5 | |
| 6 | The Android system image includes a small daemon program named "qemud" |
| 7 | which is started at boot time. Its purpose is to provide a multiplexing |
| 8 | communication channel between the emulated system and the emulator program |
Vladimir Chtchetkine | 7ffddd6 | 2011-08-05 10:15:04 -0700 | [diff] [blame] | 9 | itself. Another way to support communication between the emulated system and |
| 10 | the emulator program is using qemu pipes (see ANDROID-QEMU-PIPE.TXT for details |
| 11 | on qemu pipes). |
David Turner | 4735694 | 2009-04-05 14:23:06 -0700 | [diff] [blame] | 12 | |
| 13 | Its goal is to allow certain parts of the system to talk directly to the |
| 14 | emulator without requiring special kernel support; this simplifies a lot of |
| 15 | things since it does *not* require: |
| 16 | |
| 17 | - writing/configuring a specific kernel driver |
David 'Digit' Turner | 6ba28da | 2014-01-10 12:21:19 +0100 | [diff] [blame] | 18 | - writing the corresponding hardware emulation code in hw/android/goldfish/*.c |
David Turner | 4735694 | 2009-04-05 14:23:06 -0700 | [diff] [blame] | 19 | - dealing with device allocation and permission issues in the emulated system |
| 20 | |
| 21 | The emulator provides 'services' to various parts of the emulated system. |
| 22 | Each service is identified by a name and serves a specific purpose. For |
| 23 | example: |
| 24 | |
| 25 | "gsm" Used to communicate with the emulated GSM modem with |
| 26 | AT commands. |
| 27 | |
| 28 | "gps" Used to receive NMEA sentences broadcasted from the |
| 29 | emulated GPS device. |
| 30 | |
| 31 | "sensors" Used to list the number of emulated sensors, as well as |
| 32 | enable/disable reception of specific sensor events. |
| 33 | |
| 34 | "control" Used to control misc. simple emulated hardware devices |
| 35 | (e.g. vibrator, leds, LCD backlight, etc...) |
| 36 | |
| 37 | |
| 38 | II. Implementation: |
| 39 | ------------------- |
| 40 | |
| 41 | Since the "cupcake" platform, this works as follows: |
| 42 | |
| 43 | - A 'qemud client' is any part of the emulated system that wants to talk |
| 44 | to the emulator. It does so by: |
| 45 | |
| 46 | - connecting to the /dev/socket/qemud Unix domain socket |
| 47 | - sending the service name through the socket |
| 48 | - receives two bytes of data, which will be "OK" in case of |
| 49 | success, or "KO" in case of failure. |
| 50 | |
| 51 | After an OK, the same connection can be used to talk directly to the |
| 52 | corresponding service. |
| 53 | |
| 54 | |
| 55 | - The /dev/socket/qemud Unix socket is created by init and owned by the |
| 56 | 'qemud' daemon started at boot by /system/etc/init.goldfish.rc |
| 57 | |
| 58 | The daemon also opens an emulated serial port (e.g. /dev/ttyS1) and |
| 59 | will pass all messages between clients and emulator services. Thus, |
| 60 | everything looks like the following: |
| 61 | |
| 62 | |
| 63 | emulator <==serial==> qemud <---> /dev/socket/qemud <-+--> client1 |
| 64 | | |
| 65 | +--> client2 |
| 66 | |
| 67 | A very simple multiplexing protocol is used on the serial connection: |
| 68 | |
| 69 | offset size description |
| 70 | |
| 71 | 0 2 2-char hex string giving the destination or |
| 72 | source channel |
| 73 | |
| 74 | 2 4 4-char hex string giving the payload size |
| 75 | |
| 76 | 6 n the message payload |
| 77 | |
| 78 | Where each client gets a 'channel' number allocated by the daemon |
| 79 | at connection time. |
| 80 | |
| 81 | Note that packets larger than 65535 bytes cannot be sent directly |
| 82 | through the qemud channel. This is intentional; for large data |
| 83 | communication, the client and service should use a fragmentation |
| 84 | convention that deals with this. |
| 85 | |
| 86 | Zero-sized packets are silently discard by qemud and the emulator and |
| 87 | should normally not appear on the serial port. |
| 88 | |
| 89 | Channel 0 is reserved for control messages between the daemon and the |
| 90 | emulator. These are the following: |
| 91 | |
| 92 | - When a client connects to /dev/socket/qemud and sends a service |
| 93 | name to the daemon, the later sends to the emulator: |
| 94 | |
| 95 | connect:<service>:<id> |
| 96 | |
David Turner | 94088e2 | 2009-04-14 14:46:08 -0700 | [diff] [blame] | 97 | where <service> is the service name, and <id> is a 2-hexchar string |
David Turner | 4735694 | 2009-04-05 14:23:06 -0700 | [diff] [blame] | 98 | giving the allocated channel index for the client. |
| 99 | |
| 100 | |
| 101 | - The emulator can respond in case of success with: |
| 102 | |
| 103 | ok:connect:<id> |
| 104 | |
| 105 | or, in case of failure, with: |
| 106 | |
| 107 | ok:connect:<id>:<reason> |
| 108 | |
| 109 | where <reason> is a liberal string giving the reason for failure. |
| 110 | It is never sent to clients (which will only receive a "KO") and |
| 111 | is used strictly for debugging purposes. |
| 112 | |
| 113 | - After a succesful connect, all messages between the client and |
| 114 | the corresponding emulator service will be passed through the |
| 115 | corresponding numbered channel. |
| 116 | |
| 117 | But if the client disconnects from the socket, the daemon will |
| 118 | send through channel 0 this message to the emulator: |
| 119 | |
| 120 | disconnect:<id> |
| 121 | |
| 122 | - If an emulator service decides, for some reason, to disconnect |
| 123 | a client, the emulator will send to the daemon (on channel 0): |
| 124 | |
| 125 | disconnect:<id> |
| 126 | |
| 127 | The daemon deals with this gracefully (e.g. it will wait that the |
| 128 | client has read all buffered data in the daemon before closing the |
| 129 | socket, to avoid packet loss). |
| 130 | |
| 131 | - Any other command sent from the daemon to the emulator will result |
| 132 | in the following answer: |
| 133 | |
| 134 | ko:bad command |
| 135 | |
| 136 | - Which exact serial port to open is determined by the emulator at startup |
| 137 | and is passed to the system as a kernel parameter, e.g.: |
| 138 | |
| 139 | android.qemud=ttyS1 |
| 140 | |
| 141 | |
| 142 | - The code to support services and their clients in the emulator is located |
| 143 | in android/hw-qemud.c. This code is heavily commented. |
| 144 | |
| 145 | The daemon's source is in $ROOT/development/emulator/qemud/qemud.c |
| 146 | |
| 147 | The header in $ROOT/hardware/libhardware/include/hardware/qemud.h |
| 148 | can be used by clients to ease connecting and talking to QEMUD-based |
| 149 | services. |
| 150 | |
| 151 | This is used by $ROOT/developement/emulator/sensors/sensors_qemu.c which |
| 152 | implements emulator-specific sensor support in the system by talking to |
| 153 | the "sensors" service provided by the emulator (if available). |
| 154 | |
| 155 | Code in $ROOT/hardware/libhardware_legacy also uses QEMUD-based services. |
| 156 | |
| 157 | |
| 158 | - Certain services also implement a simple framing protocol when exchanging |
| 159 | messages with their clients. The framing happens *after* serial port |
| 160 | multiplexing and looks like: |
| 161 | |
| 162 | offset size description |
| 163 | |
| 164 | 0 4 4-char hex string giving the payload size |
| 165 | |
| 166 | 4 n the message payload |
| 167 | |
| 168 | This is needed because the framing protocol used on the serial port is |
| 169 | not preserved when talking to clients through /dev/socket/qemud. |
| 170 | |
| 171 | Certain services do not need it at all (GSM, GPS) so it is optional and |
| 172 | must be used depending on which service you talk to by clients. |
| 173 | |
Vladimir Chtchetkine | 7ffddd6 | 2011-08-05 10:15:04 -0700 | [diff] [blame] | 174 | - QEMU pipe communication model works similarly to the serial port multiplexing, |
| 175 | but also has some differences as far as connecting client with the service is |
| 176 | concerned: |
| 177 | |
| 178 | emulator <-+--> /dev/qemu_pipe/qemud:srv1 <---> client1 |
| 179 | | |
| 180 | +--> /dev/qemu_pipe/qemud:srv2 <---> client2 |
| 181 | |
| 182 | In the pipe model each client gets connected to the emulator through a unique |
| 183 | handle to /dev/qemu_pipe (a "pipe"), so there is no need for multiplexing the |
| 184 | channels. |
David Turner | 4735694 | 2009-04-05 14:23:06 -0700 | [diff] [blame] | 185 | |
| 186 | III. Legacy 'qemud': |
| 187 | -------------------- |
| 188 | |
| 189 | The system images provided by the 1.0 and 1.1 releases of the Android SDK |
| 190 | implement an older variant of the qemud daemon that uses a slightly |
| 191 | different protocol to communicate with the emulator. |
| 192 | |
| 193 | This is documented here since this explains some subtleties in the |
| 194 | implementation code of android/hw-qemud.c |
| 195 | |
| 196 | The old scheme also used a serial port to allow the daemon and the emulator |
David Turner | 94088e2 | 2009-04-14 14:46:08 -0700 | [diff] [blame] | 197 | to communicate. However, the multiplexing protocol swaps the position of |
| 198 | 'channel' and 'length' in the header: |
| 199 | |
| 200 | offset size description |
| 201 | |
| 202 | 0 4 4-char hex string giving the payload size |
| 203 | |
| 204 | 4 2 2-char hex string giving the destination or |
| 205 | source channel |
| 206 | |
| 207 | 6 n the message payload |
| 208 | |
| 209 | Several other differences, best illustrated by the following graphics: |
David Turner | 4735694 | 2009-04-05 14:23:06 -0700 | [diff] [blame] | 210 | |
| 211 | emulator <==serial==> qemud <-+--> /dev/socket/qemud_gsm <--> GSM client |
| 212 | | |
| 213 | +--> /dev/socket/qemud_gps <--> GPS client |
| 214 | | |
| 215 | +--> /dev/socket/qemud_control <--> client(s) |
| 216 | |
| 217 | Now, for the details: |
| 218 | |
| 219 | - instead of a single /dev/socket/qemud, init created several Unix domain |
| 220 | sockets, one per service: |
| 221 | |
| 222 | /dev/socket/qemud_gsm |
| 223 | /dev/socket/qemud_gps |
| 224 | /dev/socket/qemud_control |
| 225 | |
| 226 | note that there is no "sensors" socket in 1.0 and 1.1 |
| 227 | |
| 228 | - the daemon created a de-facto numbered channel for each one of these |
| 229 | services, even if no client did connect to it (only one client could |
| 230 | connect to a given service at a time). |
| 231 | |
| 232 | - at startup, the emulator does query the channel numbers of all services |
| 233 | it implements, e.g. it would send *to* the daemon on channel 0: |
| 234 | |
| 235 | connect:<service> |
| 236 | |
| 237 | where <service> can be one of "gsm", "gps" or "control" |
| 238 | |
| 239 | (Note that on the current implementation, the daemon is sending connection |
| 240 | messages to the emulator instead). |
| 241 | |
| 242 | - the daemon would respond with either: |
| 243 | |
| 244 | ok:connect:<service>:<hxid> |
| 245 | |
| 246 | where <service> would be the service name, and <hxid> a 4-hexchar channel |
| 247 | number (NOTE: 4 chars, not 2). Or with: |
| 248 | |
| 249 | ko:connect:bad name |
| 250 | |
| 251 | |
| 252 | This old scheme was simpler to implement in both the daemon and the emulator |
| 253 | but lacked a lot of flexibility: |
| 254 | |
| 255 | - adding a new service required to modify /system/etc/init.goldfish.rc |
| 256 | as well as the daemon source file (which contained a hard-coded list |
| 257 | of sockets to listen to for client connections). |
| 258 | |
| 259 | - only one client could be connected to a given service at a time, |
| 260 | except for the GPS special case which was a unidirectionnal broadcast |
| 261 | by convention. |
| 262 | |
| 263 | The current implementation moves any service-specific code to the emulator, |
| 264 | only uses a single socket and allows concurrent clients for a all services. |
Ot ten Thije | 871da2a | 2010-09-20 10:29:22 +0100 | [diff] [blame] | 265 | |
| 266 | |
| 267 | IV. State snapshots: |
| 268 | -------------------- |
| 269 | |
Vladimir Chtchetkine | 7ffddd6 | 2011-08-05 10:15:04 -0700 | [diff] [blame] | 270 | Support for snapshots relies on the symmetric qemud_*_save and qemud_*_load |
Ot ten Thije | 871da2a | 2010-09-20 10:29:22 +0100 | [diff] [blame] | 271 | functions which save the state of the various Qemud* structs defined in |
| 272 | android/hw-qemud.c. The high-level process is as follows. |
| 273 | |
| 274 | When a snapshot is made, the names and configurations of all services are |
| 275 | saved. Services can register a custom callback, which is invoked at this point |
| 276 | to allow saving of service-specific state. Next, clients are saved following |
| 277 | the same pattern. We save the channel id and the name of service they are |
| 278 | registered to, then invoke a client-specific callback. |
| 279 | |
| 280 | When a snapshot is restored, the first step is to check whether all services |
| 281 | that were present when the snapshot was made are available. There is currently |
| 282 | no functionality to start start missing services, so loading fails if a service |
| 283 | is not present. If all services are present, callbacks are used to restore |
| 284 | service-specific state. |
| 285 | |
| 286 | Next, all active clients are shut down. Information from the snapshot is used |
| 287 | to start new clients for the services and channels as they were when the |
| 288 | snapshot was made. This completes the restore process. |