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