1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_SDKCONTROL_SOCKET_H_ 18 #define ANDROID_SDKCONTROL_SOCKET_H_ 19 20 #include "android/async-socket.h" 21 22 /* 23 * Contains declaration of an API that encapsulates communication protocol with 24 * SdkController running on an Android device. 25 * 26 * SdkController is used to provide: 27 * 28 * - Realistic sensor emulation. 29 * - Multi-touch emulation. 30 * - Open for other types of emulation. 31 * 32 * The idea behind this type of emulation is such that there is an actual 33 * Android device that is connected via USB to the host running the emulator. 34 * On the device there is an SdkController service running that enables 35 * communication between an Android application that gathers information required 36 * by the emulator, and transmits that info to the emulator. 37 * 38 * SdkController service on the device, and SDKCtlSocket API implemented here 39 * implement the exchange protocol between an Android application, and emulation 40 * engine running inside the emulator. 41 * 42 * In turn, the exchange protocol is implemented on top of asynchronous socket 43 * communication (abstracted in AsyncSocket protocol implemented in 44 * android/async-socket.*). It means that connection, and all data transfer 45 * (both, in, and out) are completely asynchronous, and results of each operation 46 * are reported through callbacks. 47 * 48 * Essentially, this entire API implements two types of protocols: 49 * 50 * - Connection protocol. 51 * - Data exchange protocol. 52 * 53 * 1. Connection protocol. 54 * 55 * Connecting to SdkController service on the attached device can be broken down 56 * into two phases: 57 * - Connecting to a TCP socket. 58 * - Sending a "handshake" query to the SdkController. 59 * 60 * 1.1. Connecting to the socket. 61 * 62 * TCP socket connection with SdkController is enabled by using adb port 63 * forwarding. SdkController is always listening to a local abstract socket named 64 * 'android.sdk.controller', so to enable connecting to it from the host, run 65 * 66 * adb forward tcp:<port> localabstract: android.sdk.controller 67 * 68 * After that TCP socket for the requested port can be used to connect to 69 * SdkController, and connecting to it is no different than connecting to any 70 * socket server. Except for one thing: adb port forwarding is implemented in 71 * such a way, that socket_connect will always succeed, even if there is no 72 * server listening to that port on the other side of connection. Moreover, 73 * even socked_send will succeed in this case, so the only way to ensure that 74 * SdkController in deed is listening is to exchange a handshake with it: 75 * Fortunatelly, an attempt to read from forwarded TCP port on condition that 76 * there is no listener on the oher side will fail. 77 * 78 * 1.2. Handshake query. 79 * 80 * Handshake query is a special type of query that SDKCtlSocket sends to the 81 * SdkController upon successful socket connection. This query served two 82 * purposes: 83 * - Informs the SdkController about host endianness. This information is 84 * important, because SdkController needs it in order to format its messages 85 * with proper endianness. 86 * - Ensures that SdkController is in deed listening on the other side of the 87 * connected socket. 88 * 89 * Connection with SdkController is considered to be successfuly established when 90 * SdkController responds to the handshake query, thus, completing the connection. 91 * 92 * 2. Data exchange protocol. 93 * 94 * As it was mentioned above, all data transfer in this API is completely 95 * asynchronous, and result of each data transfer is reported via callbacks. 96 * This also complicates destruction of data involved in exchange, since in an 97 * asynchronous environment it's hard to control the lifespan of an object, its 98 * owner, and who and when is responsible to free resources allocated for the 99 * transfer. To address this issue, all the descriptors that this API operates 100 * with are referenced on use / released after use, and get freed when reference 101 * counter for them drops to zero, indicating that there is no component that is 102 * interested in that particular descriptor. 103 * 104 * There are three types of data in the exchange protocol: 105 * - A packet - the simplest type of data that doesn't require any replies. 106 * - A query - A message that require a reply, and 107 * - A query reply - A message that delivers query reply. 108 */ 109 110 /* Declares SDK controller socket descriptor. */ 111 typedef struct SDKCtlSocket SDKCtlSocket; 112 113 /* Declares SDK controller data packet descriptor. */ 114 typedef struct SDKCtlPacket SDKCtlPacket; 115 116 /* Declares SDK controller query descriptor. */ 117 typedef struct SDKCtlQuery SDKCtlQuery; 118 119 /* Defines client's callback set to monitor SDK controller socket connection. 120 * 121 * SDKCtlSocket will invoke this callback when connection to TCP port is 122 * established, but before handshake query is processed. The client should use 123 * on_sdkctl_handshake_cb to receive notification about an operational connection 124 * with SdkController. 125 * 126 * The main purpose of this callback for the client is to monitor connection 127 * state: in addition to TCP port connection, this callback will be invoked when 128 * connection with the port is lost. 129 * 130 * Param: 131 * client_opaque - An opaque pointer associated with the client. 132 * sdkctl - Initialized SDKCtlSocket instance. 133 * status - Socket connection status. Can be one of these: 134 * - ASIO_STATE_SUCCEEDED : Socket is connected to the port. 135 * - ASIO_STATE_FAILED : Connection attempt has failed, or connection with 136 * the port is lost. 137 * Return: 138 * One of the AsyncIOAction values. 139 */ 140 typedef AsyncIOAction (*on_sdkctl_connection_cb)(void* client_opaque, 141 SDKCtlSocket* sdkctl, 142 AsyncIOState status); 143 144 /* Defines client's callback set to receive handshake reply from the SdkController 145 * service running on the device. 146 * 147 * Successful handshake means that connection between the client and SDK 148 * controller service has been established. 149 * 150 * Param: 151 * client_opaque - An opaque pointer associated with the client. 152 * sdkctl - Initialized SDKCtlSocket instance. 153 * handshake - Handshake message received from the SDK controller service. 154 * handshake_size - Size of the fandshake message received from the SDK 155 * controller service. 156 * status - Handshake status. Note that handshake, and handshake_size are valid 157 * only if this parameter is set to ASIO_STATE_SUCCEEDED. 158 */ 159 typedef void (*on_sdkctl_handshake_cb)(void* client_opaque, 160 SDKCtlSocket* sdkctl, 161 void* handshake, 162 uint32_t handshake_size, 163 AsyncIOState status); 164 165 /* Defines a message notification callback. 166 * Param: 167 * client_opaque - An opaque pointer associated with the client. 168 * sdkctl - Initialized SDKCtlSocket instance. 169 * message - Descriptor for received message. Note that message descriptor will 170 * be released upon exit from this callback (thus, could be freed along 171 * with message data). If the client is interested in working with that 172 * message after the callback returns, it should reference the message 173 * descriptor in this callback. 174 * msg_type - Message type. 175 * msg_data, msg_size - Message data. 176 */ 177 typedef void (*on_sdkctl_message_cb)(void* client_opaque, 178 SDKCtlSocket* sdkctl, 179 SDKCtlPacket* message, 180 int msg_type, 181 void* msg_data, 182 int msg_size); 183 184 /* Defines query completion callback. 185 * Param: 186 * query_opaque - An opaque pointer associated with the query by the client. 187 * query - Query descriptor. Note that query descriptor will be released upon 188 * exit from this callback (thus, could be freed along with query data). If 189 * the client is interested in working with that query after the callback 190 * returns, it should reference the query descriptor in this callback. 191 * status - Query status. Can be one of these: 192 * - ASIO_STATE_CONTINUES : Query data has been transmitted to the service, 193 * and query is now waiting for response. 194 * - ASIO_STATE_SUCCEEDED : Query has been successfully completed. 195 * - ASIO_STATE_FAILED : Query has failed on an I/O. 196 * - ASIO_STATE_TIMED_OUT : Deadline set for the query has expired. 197 * - ASIO_STATE_CANCELLED : Query has been cancelled due to socket 198 * disconnection. 199 * Return: 200 * One of the AsyncIOAction values. 201 */ 202 typedef AsyncIOAction (*on_sdkctl_query_cb)(void* query_opaque, 203 SDKCtlQuery* query, 204 AsyncIOState status); 205 206 /******************************************************************************** 207 * SDKCtlPacket API 208 ********************************************************************************/ 209 210 /* References SDKCtlPacket object. 211 * Param: 212 * packet - Initialized SDKCtlPacket instance. 213 * Return: 214 * Number of outstanding references to the object. 215 */ 216 extern int sdkctl_packet_reference(SDKCtlPacket* packet); 217 218 /* Releases SDKCtlPacket object. 219 * Note that upon exiting from this routine the object might be destroyed, even 220 * if this routine returns value other than zero. 221 * Param: 222 * packet - Initialized SDKCtlPacket instance. 223 * Return: 224 * Number of outstanding references to the object. 225 */ 226 extern int sdkctl_packet_release(SDKCtlPacket* packet); 227 228 /******************************************************************************** 229 * SDKCtlQuery API 230 ********************************************************************************/ 231 232 /* Creates, and partially initializes query descriptor. 233 * Note that returned descriptor is referenced, and it must be eventually 234 * released with a call to sdkctl_query_release. 235 * Param: 236 * sdkctl - SDKCtlSocket instance for the query. 237 * query_type - Defines query type. 238 * in_data_size Size of the query's input buffer (data to be sent with this 239 * query). Note that buffer for query data will be allocated along with the 240 * query descriptor. Use sdkctl_query_get_buffer_in to get address of data 241 * buffer for this query. 242 * Return: 243 * Referenced SDKCtlQuery descriptor. 244 */ 245 extern SDKCtlQuery* sdkctl_query_new(SDKCtlSocket* sdkctl, 246 int query_type, 247 uint32_t in_data_size); 248 249 /* Creates, and fully initializes query descriptor. 250 * Note that returned descriptor is referenced, and it must be eventually 251 * released with a call to sdkctl_query_release. 252 * Param: 253 * sdkctl - SDKCtlSocket instance for the query. 254 * query_type - Defines query type. 255 * in_data_size Size of the query's input buffer (data to be sent with this 256 * query). Note that buffer for query data will be allocated along with the 257 * query descriptor. Use sdkctl_query_get_buffer_in to get address of data 258 * buffer for this query. 259 * in_data - Data to initialize query's input buffer with. 260 * response_buffer - Contains address of the buffer addressing preallocated 261 * response buffer on the way in, and address of the buffer containing query 262 * response on query completion. If this parameter is NULL, the API will 263 * allocate its own query response buffer, which is going to be freed after 264 * query completion. 265 * response_size - Contains size of preallocated response buffer on the way in, 266 * and size of the received response on query completion. Can be NULL. 267 * query_cb - A callback to monitor query state. 268 * query_opaque - An opaque pointer associated with the query. 269 * Return: 270 * Referenced SDKCtlQuery descriptor. 271 */ 272 extern SDKCtlQuery* sdkctl_query_new_ex(SDKCtlSocket* sdkctl, 273 int query_type, 274 uint32_t in_data_size, 275 const void* in_data, 276 void** response_buffer, 277 uint32_t* response_size, 278 on_sdkctl_query_cb query_cb, 279 void* query_opaque); 280 281 /* Sends query to SDK controller. 282 * Param: 283 * query - Query to send. Note that this must be a fully initialized query 284 * descriptor. 285 * to - Milliseconds to allow for the query to complete. Negative value means 286 * "forever". 287 */ 288 extern void sdkctl_query_send(SDKCtlQuery* query, int to); 289 290 /* Creates, fully initializes query descriptor, and sends the query to SDK 291 * controller. 292 * Note that returned descriptor is referenced, and it must be eventually 293 * released with a call to sdkctl_query_release. 294 * Param: 295 * sdkctl - SDKCtlSocket instance for the query. 296 * query_type - Defines query type. 297 * in_data_size Size of the query's input buffer (data to be sent with this 298 * query). Note that buffer for query data will be allocated along with the 299 * query descriptor. Use sdkctl_query_get_buffer_in to get address of data 300 * buffer for this query. 301 * in_data - Data to initialize query's input buffer with. 302 * response_buffer - Contains address of the buffer addressing preallocated 303 * response buffer on the way in, and address of the buffer containing query 304 * response on query completion. If this parameter is NULL, the API will 305 * allocate its own query response buffer, which is going to be freed after 306 * query completion. 307 * response_size - Contains size of preallocated response buffer on the way in, 308 * and size of the received response on query completion. Can be NULL. 309 * query_cb - A callback to monitor query state. 310 * query_opaque - An opaque pointer associated with the query. 311 * to - Milliseconds to allow for the query to complete. Negative value means 312 * "forever". 313 * Return: 314 * Referenced SDKCtlQuery descriptor for the query that has been sent. 315 */ 316 extern SDKCtlQuery* sdkctl_query_build_and_send(SDKCtlSocket* sdkctl, 317 int query_type, 318 uint32_t in_data_size, 319 const void* in_data, 320 void** response_buffer, 321 uint32_t* response_size, 322 on_sdkctl_query_cb query_cb, 323 void* query_opaque, 324 int to); 325 326 /* References SDKCtlQuery object. 327 * Param: 328 * query - Initialized SDKCtlQuery instance. 329 * Return: 330 * Number of outstanding references to the object. 331 */ 332 extern int sdkctl_query_reference(SDKCtlQuery* query); 333 334 /* Releases SDKCtlQuery object. 335 * Note that upon exit from this routine the object might be destroyed, even if 336 * this routine returns value other than zero. 337 * Param: 338 * query - Initialized SDKCtlQuery instance. 339 * Return: 340 * Number of outstanding references to the object. 341 */ 342 extern int sdkctl_query_release(SDKCtlQuery* query); 343 344 /* Gets address of query's input data buffer (data to be send). 345 * Param: 346 * query - Query to get data buffer for. 347 * Return: 348 * Address of query's input data buffer. 349 */ 350 extern void* sdkctl_query_get_buffer_in(SDKCtlQuery* query); 351 352 /******************************************************************************** 353 * SDKCtlSocket API 354 ********************************************************************************/ 355 356 /* Creates an SDK controller socket descriptor. 357 * Param: 358 * reconnect_to - Timeout before trying to reconnect, or retry connection 359 * attempts after disconnection, or on connection failures. 360 * service_name - Name of the SdkController service for this socket (such as 361 * 'sensors', 'milti-touch', etc.) 362 * on_connection - A callback to invoke on socket connection events. 363 * on_handshake - A callback to invoke on handshake events. 364 * on_message - A callback to invoke when a message is received from the SDK 365 * controller. 366 * opaque - An opaque pointer to associate with the socket. 367 * Return: 368 * Initialized SDKCtlSocket instance on success, or NULL on failure. 369 */ 370 extern SDKCtlSocket* sdkctl_socket_new(int reconnect_to, 371 const char* service_name, 372 on_sdkctl_connection_cb on_connection, 373 on_sdkctl_handshake_cb on_handshake, 374 on_sdkctl_message_cb on_message, 375 void* opaque); 376 377 /* Improves throughput by recycling memory allocated for buffers transferred via 378 * this API. 379 * 380 * In many cases data exchanged between SDK controller sides are small, and, 381 * although may come quite often, are coming in a sequential manner. For instance, 382 * sensor service on the device may send us sensor updates every 20ms, one after 383 * another. For such data traffic it makes perfect sense to recycle memory 384 * allocated for the previous sensor update, rather than to free it just to 385 * reallocate same buffer in 20ms. This routine sets properties of the recycler 386 * for the given SDK controller connection. Recycling includes memory allocated 387 * for all types of data transferred in this API: packets, and queries. 388 * Param: 389 * sdkctl - Initialized SDKCtlSocket instance. 390 * data_size - Size of buffer to allocate for each data block. 391 * max_recycled_num - Maximum number of allocated buffers to keep in the 392 * recycler. 393 */ 394 extern void sdkctl_init_recycler(SDKCtlSocket* sdkctl, 395 uint32_t data_size, 396 int max_recycled_num); 397 398 /* References SDKCtlSocket object. 399 * Param: 400 * sdkctl - Initialized SDKCtlSocket instance. 401 * Return: 402 * Number of outstanding references to the object. 403 */ 404 extern int sdkctl_socket_reference(SDKCtlSocket* sdkctl); 405 406 /* Releases SDKCtlSocket object. 407 * Note that upon exit from this routine the object might be destroyed, even if 408 * this routine returns value other than zero. 409 * Param: 410 * sdkctl - Initialized SDKCtlSocket instance. 411 * Return: 412 * Number of outstanding references to the object. 413 */ 414 extern int sdkctl_socket_release(SDKCtlSocket* sdkctl); 415 416 /* Asynchronously connects to SDK controller. 417 * Param: 418 * sdkctl - Initialized SDKCtlSocket instance. 419 * port - TCP port to connect the socket to. 420 * retry_to - Number of milliseconds to wait before retrying a failed 421 * connection attempt. 422 */ 423 extern void sdkctl_socket_connect(SDKCtlSocket* sdkctl, int port, int retry_to); 424 425 /* Asynchronously reconnects to SDK controller. 426 * Param: 427 * sdkctl - Initialized SDKCtlSocket instance. 428 * port - TCP port to reconnect the socket to. 429 * retry_to - Number of milliseconds to wait before reconnecting. Same timeout 430 * will be used for retrying a failed connection attempt. 431 */ 432 extern void sdkctl_socket_reconnect(SDKCtlSocket* sdkctl, int port, int retry_to); 433 434 /* Disconnects from SDK controller. 435 * Param: 436 * sdkctl - Initialized SDKCtlSocket instance. 437 */ 438 extern void sdkctl_socket_disconnect(SDKCtlSocket* sdkctl); 439 440 #endif /* ANDROID_SDKCONTROL_SOCKET_H_ */ 441