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 #include "android/async-utils.h" 22 23 /* 24 * Contains declaration of an API that encapsulates communication protocol with 25 * SdkController running on an Android device. 26 * 27 * SdkController is used to provide: 28 * 29 * - Realistic sensor emulation. 30 * - Multi-touch emulation. 31 * - Open for other types of emulation. 32 * 33 * The idea behind this type of emulation is such that there is an actual 34 * Android device that is connected via USB to the host running the emulator. 35 * On the device there is an SdkController service running that enables 36 * communication between an Android application that gathers information required 37 * by the emulator, and transmits that info to the emulator. 38 * 39 * SdkController service on the device, and SDKCtlSocket API implemented here 40 * implement the exchange protocol between an Android application, and emulation 41 * engine running inside the emulator. 42 * 43 * In turn, the exchange protocol is implemented on top of asynchronous socket 44 * communication (abstracted in AsyncSocket protocol implemented in 45 * android/async-socket.*). It means that connection, and all data transfer 46 * (both, in, and out) are completely asynchronous, and results of each operation 47 * are reported through callbacks. 48 * 49 * Essentially, this entire API implements two types of protocols: 50 * 51 * - Connection protocol. 52 * - Data exchange protocol. 53 * 54 * 1. Connection protocol. 55 * 56 * Connecting to SdkController service on the attached device can be broken down 57 * into two phases: 58 * - Connecting to a TCP socket. 59 * - Sending a "handshake" query to the SdkController. 60 * 61 * 1.1. Connecting to the socket. 62 * 63 * TCP socket connection with SdkController is enabled by using adb port 64 * forwarding. SdkController is always listening to a local abstract socket named 65 * 'android.sdk.controller', so to enable connecting to it from the host, run 66 * 67 * adb forward tcp:<port> localabstract: android.sdk.controller 68 * 69 * After that TCP socket for the requested port can be used to connect to 70 * SdkController, and connecting to it is no different than connecting to any 71 * socket server. Except for one thing: adb port forwarding is implemented in 72 * such a way, that socket_connect will always succeed, even if there is no 73 * server listening to that port on the other side of connection. Moreover, 74 * even socked_send will succeed in this case, so the only way to ensure that 75 * SdkController in deed is listening is to exchange a handshake with it: 76 * Fortunatelly, an attempt to read from forwarded TCP port on condition that 77 * there is no listener on the oher side will fail. 78 * 79 * 1.2. Handshake query. 80 * 81 * Handshake query is a special type of query that SDKCtlSocket sends to the 82 * SdkController upon successful socket connection. This query served two 83 * purposes: 84 * - Informs the SdkController about host endianness. This information is 85 * important, because SdkController needs it in order to format its messages 86 * with proper endianness. 87 * - Ensures that SdkController is in deed listening on the other side of the 88 * connected socket. 89 * 90 * Connection with SdkController is considered to be successfuly established when 91 * SdkController responds to the handshake query, thus, completing the connection. 92 * 93 * 2. Data exchange protocol. 94 * 95 * As it was mentioned above, all data transfer in this API is completely 96 * asynchronous, and result of each data transfer is reported via callbacks. 97 * This also complicates destruction of data involved in exchange, since in an 98 * asynchronous environment it's hard to control the lifespan of an object, its 99 * owner, and who and when is responsible to free resources allocated for the 100 * transfer. To address this issue, all the descriptors that this API operates 101 * with are referenced on use / released after use, and get freed when reference 102 * counter for them drops to zero, indicating that there is no component that is 103 * interested in that particular descriptor. 104 * 105 * There are three types of data in the exchange protocol: 106 * - A message - the simplest type of data that doesn't require any replies. 107 * - A query - A message that require a reply, and 108 * - A query reply - A message that delivers query reply. 109 */ 110 111 /* Default TCP port to use for connection with SDK controller. */ 112 #define SDKCTL_DEFAULT_TCP_PORT 1970 113 114 /* Declares SDK controller socket descriptor. */ 115 typedef struct SDKCtlSocket SDKCtlSocket; 116 117 /* Declares SDK controller message descriptor. */ 118 typedef struct SDKCtlMessage SDKCtlMessage; 119 120 /* Declares SDK controller query descriptor. */ 121 typedef struct SDKCtlQuery SDKCtlQuery; 122 123 /* Declares SDK controller direct packet descriptor. 124 * Direct packet (unlike message, or query packets) doesn't contain data buffer, 125 * but rather references message, or query data allocated by the client. 126 */ 127 typedef struct SDKCtlDirectPacket SDKCtlDirectPacket; 128 129 /* Defines client's callback set to monitor SDK controller socket connection. 130 * 131 * SDKCtlSocket will invoke this callback when connection to TCP port is 132 * established, but before handshake query is processed. The client should use 133 * on_sdkctl_handshake_cb to receive notification about an operational connection 134 * with SdkController. 135 * 136 * The main purpose of this callback for the client is to monitor connection 137 * state: in addition to TCP port connection, this callback will be invoked when 138 * connection with the port is lost. 139 * 140 * Param: 141 * client_opaque - An opaque pointer associated with the client. 142 * sdkctl - Initialized SDKCtlSocket instance. 143 * status - Socket connection status. Can be one of these: 144 * - ASIO_STATE_SUCCEEDED : Socket is connected to the port. 145 * - ASIO_STATE_FAILED : Connection attempt has failed, or connection with 146 * the port is lost. 147 * Return: 148 * One of the AsyncIOAction values. 149 */ 150 typedef AsyncIOAction (*on_sdkctl_socket_connection_cb)(void* client_opaque, 151 SDKCtlSocket* sdkctl, 152 AsyncIOState status); 153 154 /* Enumerates port connection statuses passed to port connection callback. 155 */ 156 typedef enum SdkCtlPortStatus { 157 /* Service-side port has connected to the socket. */ 158 SDKCTL_PORT_DISCONNECTED, 159 /* Service-side port has disconnected from the socket. */ 160 SDKCTL_PORT_CONNECTED, 161 /* Service-side port has enabled emulation */ 162 SDKCTL_PORT_ENABLED, 163 /* Service-side port has disabled emulation */ 164 SDKCTL_PORT_DISABLED, 165 /* Handshake request has succeeded, and service-side port is connected. */ 166 SDKCTL_HANDSHAKE_CONNECTED, 167 /* Handshake request has succeeded, but service-side port is not connected. */ 168 SDKCTL_HANDSHAKE_NO_PORT, 169 /* Handshake request has failed due to port duplication. */ 170 SDKCTL_HANDSHAKE_DUP, 171 /* Handshake request has failed on an unknown query. */ 172 SDKCTL_HANDSHAKE_UNKNOWN_QUERY, 173 /* Handshake request has failed on an unknown response. */ 174 SDKCTL_HANDSHAKE_UNKNOWN_RESPONSE, 175 } SdkCtlPortStatus; 176 177 /* Defines client's callback set to receive port connection status. 178 * 179 * Port connection is different than socket connection, and indicates whether 180 * or not a service-side port that provides requested emulation functionality is 181 * hooked up with the connected socket. For instance, multi-touch port may be 182 * inactive at the time when socket is connected. So, there is a successful 183 * socket connection, but there is no service at the device end that provides 184 * multi-touch functionality. So, for multi-touch example, this callback will be 185 * invoked when multi-touch port at the device end becomes active, and hooks up 186 * with the socket that was connected before. 187 * 188 * Param: 189 * client_opaque - An opaque pointer associated with the client. 190 * sdkctl - Initialized SDKCtlSocket instance. 191 * status - Port connection status. 192 */ 193 typedef void (*on_sdkctl_port_connection_cb)(void* client_opaque, 194 SDKCtlSocket* sdkctl, 195 SdkCtlPortStatus status); 196 197 /* Defines a message notification callback. 198 * Param: 199 * client_opaque - An opaque pointer associated with the client. 200 * sdkctl - Initialized SDKCtlSocket instance. 201 * message - Descriptor for received message. Note that message descriptor will 202 * be released upon exit from this callback (thus, could be freed along 203 * with message data). If the client is interested in working with that 204 * message after the callback returns, it should reference the message 205 * descriptor in this callback. 206 * msg_type - Message type. 207 * msg_data, msg_size - Message data. 208 */ 209 typedef void (*on_sdkctl_message_cb)(void* client_opaque, 210 SDKCtlSocket* sdkctl, 211 SDKCtlMessage* message, 212 int msg_type, 213 void* msg_data, 214 int msg_size); 215 216 /* Defines query completion callback. 217 * Param: 218 * query_opaque - An opaque pointer associated with the query by the client. 219 * query - Query descriptor. Note that query descriptor will be released upon 220 * exit from this callback (thus, could be freed along with query data). If 221 * the client is interested in working with that query after the callback 222 * returns, it should reference the query descriptor in this callback. 223 * status - Query status. Can be one of these: 224 * - ASIO_STATE_CONTINUES : Query data has been transmitted to the service, 225 * and query is now waiting for response. 226 * - ASIO_STATE_SUCCEEDED : Query has been successfully completed. 227 * - ASIO_STATE_FAILED : Query has failed on an I/O. 228 * - ASIO_STATE_TIMED_OUT : Deadline set for the query has expired. 229 * - ASIO_STATE_CANCELLED : Query has been cancelled due to socket 230 * disconnection. 231 * Return: 232 * One of the AsyncIOAction values. 233 */ 234 typedef AsyncIOAction (*on_sdkctl_query_cb)(void* query_opaque, 235 SDKCtlQuery* query, 236 AsyncIOState status); 237 238 /* Defines direct packet completion callback. 239 * Param: 240 * opaque - An opaque pointer associated with the direct packet by the client. 241 * packet - Packet descriptor. Note that packet descriptor will be released 242 * upon exit from this callback (thus, could be freed). If the client is 243 * interested in working with that packet after the callback returns, it 244 * should reference the packet descriptor in this callback. 245 * status - Packet status. Can be one of these: 246 * - ASIO_STATE_SUCCEEDED : Packet has been successfully sent. 247 * - ASIO_STATE_FAILED : Packet has failed on an I/O. 248 * - ASIO_STATE_CANCELLED : Packet has been cancelled due to socket 249 * disconnection. 250 * Return: 251 * One of the AsyncIOAction values. 252 */ 253 typedef AsyncIOAction (*on_sdkctl_direct_cb)(void* opaque, 254 SDKCtlDirectPacket* packet, 255 AsyncIOState status); 256 257 /******************************************************************************** 258 * SDKCtlDirectPacket API 259 ********************************************************************************/ 260 261 /* Creates new SDKCtlDirectPacket descriptor. 262 * Param: 263 * sdkctl - Initialized SDKCtlSocket instance to create a direct packet for. 264 * Return: 265 * Referenced SDKCtlDirectPacket instance. 266 */ 267 extern SDKCtlDirectPacket* sdkctl_direct_packet_new(SDKCtlSocket* sdkctl); 268 269 /* References SDKCtlDirectPacket object. 270 * Param: 271 * packet - Initialized SDKCtlDirectPacket instance. 272 * Return: 273 * Number of outstanding references to the object. 274 */ 275 extern int sdkctl_direct_packet_reference(SDKCtlDirectPacket* packet); 276 277 /* Releases SDKCtlDirectPacket object. 278 * Note that upon exiting from this routine the object might be destroyed, even 279 * if this routine returns value other than zero. 280 * Param: 281 * packet - Initialized SDKCtlDirectPacket instance. 282 * Return: 283 * Number of outstanding references to the object. 284 */ 285 extern int sdkctl_direct_packet_release(SDKCtlDirectPacket* packet); 286 287 /* Sends direct packet. 288 * Param: 289 * packet - Packet descriptor for the direct packet to send. 290 * data - Data to send with the packet. Must be fully initialized message, or 291 * query header. 292 * cb, cb_opaque - Callback to invoke on packet transmission events. 293 */ 294 extern void sdkctl_direct_packet_send(SDKCtlDirectPacket* packet, 295 void* data, 296 on_sdkctl_direct_cb cb, 297 void* cb_opaque); 298 299 /******************************************************************************** 300 * SDKCtlMessage API 301 ********************************************************************************/ 302 303 /* References SDKCtlMessage object. 304 * Param: 305 * msg - Initialized SDKCtlMessage instance. 306 * Return: 307 * Number of outstanding references to the object. 308 */ 309 extern int sdkctl_message_reference(SDKCtlMessage* msg); 310 311 /* Releases SDKCtlMessage object. 312 * Note that upon exiting from this routine the object might be destroyed, even 313 * if this routine returns value other than zero. 314 * Param: 315 * msg - Initialized SDKCtlMessage instance. 316 * Return: 317 * Number of outstanding references to the object. 318 */ 319 extern int sdkctl_message_release(SDKCtlMessage* msg); 320 321 /* Builds and sends a message to the device. 322 * Param: 323 * sdkctl - SDKCtlSocket instance for the message. 324 * msg_type - Defines message type. 325 * data - Message data. Can be NULL if there is no data associated with the 326 * message. 327 * size - Byte size of the data buffer. 328 * Return: 329 * Referenced SDKCtlQuery descriptor. 330 */ 331 extern SDKCtlMessage* sdkctl_message_send(SDKCtlSocket* sdkctl, 332 int msg_type, 333 const void* data, 334 uint32_t size); 335 336 /* Gets message header size */ 337 extern int sdkctl_message_get_header_size(void); 338 339 /* Initializes message header. 340 * Param: 341 * msg - Beginning of the message packet. 342 * msg_type - Message type. 343 * msg_size - Message data size. 344 */ 345 extern void sdkctl_init_message_header(void* msg, int msg_type, int msg_size); 346 347 /******************************************************************************** 348 * SDKCtlQuery API 349 ********************************************************************************/ 350 351 /* Creates, and partially initializes query descriptor. 352 * Note that returned descriptor is referenced, and it must be eventually 353 * released with a call to sdkctl_query_release. 354 * Param: 355 * sdkctl - SDKCtlSocket instance for the query. 356 * query_type - Defines query type. 357 * in_data_size Size of the query's input buffer (data to be sent with this 358 * query). Note that buffer for query data will be allocated along with the 359 * query descriptor. Use sdkctl_query_get_buffer_in to get address of data 360 * buffer for this query. 361 * Return: 362 * Referenced SDKCtlQuery descriptor. 363 */ 364 extern SDKCtlQuery* sdkctl_query_new(SDKCtlSocket* sdkctl, 365 int query_type, 366 uint32_t in_data_size); 367 368 /* Creates, and fully initializes query descriptor. 369 * Note that returned descriptor is referenced, and it must be eventually 370 * released with a call to sdkctl_query_release. 371 * Param: 372 * sdkctl - SDKCtlSocket instance for the query. 373 * query_type - Defines query type. 374 * in_data_size Size of the query's input buffer (data to be sent with this 375 * query). Note that buffer for query data will be allocated along with the 376 * query descriptor. Use sdkctl_query_get_buffer_in to get address of data 377 * buffer for this query. 378 * in_data - Data to initialize query's input buffer with. 379 * response_buffer - Contains address of the buffer addressing preallocated 380 * response buffer on the way in, and address of the buffer containing query 381 * response on query completion. If this parameter is NULL, the API will 382 * allocate its own query response buffer, which is going to be freed after 383 * query completion. 384 * response_size - Contains size of preallocated response buffer on the way in, 385 * and size of the received response on query completion. Can be NULL. 386 * query_cb - A callback to monitor query state. 387 * query_opaque - An opaque pointer associated with the query. 388 * Return: 389 * Referenced SDKCtlQuery descriptor. 390 */ 391 extern SDKCtlQuery* sdkctl_query_new_ex(SDKCtlSocket* sdkctl, 392 int query_type, 393 uint32_t in_data_size, 394 const void* in_data, 395 void** response_buffer, 396 uint32_t* response_size, 397 on_sdkctl_query_cb query_cb, 398 void* query_opaque); 399 400 /* Sends query to SDK controller. 401 * Param: 402 * query - Query to send. Note that this must be a fully initialized query 403 * descriptor. 404 * to - Milliseconds to allow for the query to complete. Negative value means 405 * "forever". 406 */ 407 extern void sdkctl_query_send(SDKCtlQuery* query, int to); 408 409 /* Creates, fully initializes query descriptor, and sends the query to SDK 410 * controller. 411 * Note that returned descriptor is referenced, and it must be eventually 412 * released with a call to sdkctl_query_release. 413 * Param: 414 * sdkctl - SDKCtlSocket instance for the query. 415 * query_type - Defines query type. 416 * in_data_size Size of the query's input buffer (data to be sent with this 417 * query). Note that buffer for query data will be allocated along with the 418 * query descriptor. Use sdkctl_query_get_buffer_in to get address of data 419 * buffer for this query. 420 * in_data - Data to initialize query's input buffer with. 421 * response_buffer - Contains address of the buffer addressing preallocated 422 * response buffer on the way in, and address of the buffer containing query 423 * response on query completion. If this parameter is NULL, the API will 424 * allocate its own query response buffer, which is going to be freed after 425 * query completion. 426 * response_size - Contains size of preallocated response buffer on the way in, 427 * and size of the received response on query completion. Can be NULL. 428 * query_cb - A callback to monitor query state. 429 * query_opaque - An opaque pointer associated with the query. 430 * to - Milliseconds to allow for the query to complete. Negative value means 431 * "forever". 432 * Return: 433 * Referenced SDKCtlQuery descriptor for the query that has been sent. 434 */ 435 extern SDKCtlQuery* sdkctl_query_build_and_send(SDKCtlSocket* sdkctl, 436 int query_type, 437 uint32_t in_data_size, 438 const void* in_data, 439 void** response_buffer, 440 uint32_t* response_size, 441 on_sdkctl_query_cb query_cb, 442 void* query_opaque, 443 int to); 444 445 /* References SDKCtlQuery object. 446 * Param: 447 * query - Initialized SDKCtlQuery instance. 448 * Return: 449 * Number of outstanding references to the object. 450 */ 451 extern int sdkctl_query_reference(SDKCtlQuery* query); 452 453 /* Releases SDKCtlQuery object. 454 * Note that upon exit from this routine the object might be destroyed, even if 455 * this routine returns value other than zero. 456 * Param: 457 * query - Initialized SDKCtlQuery instance. 458 * Return: 459 * Number of outstanding references to the object. 460 */ 461 extern int sdkctl_query_release(SDKCtlQuery* query); 462 463 /* Gets address of query's input data buffer (data to be send). 464 * Param: 465 * query - Query to get data buffer for. 466 * Return: 467 * Address of query's input data buffer. 468 */ 469 extern void* sdkctl_query_get_buffer_in(SDKCtlQuery* query); 470 471 /* Gets address of query's output data buffer (response data). 472 * Param: 473 * query - Query to get data buffer for. 474 * Return: 475 * Address of query's output data buffer. 476 */ 477 extern void* sdkctl_query_get_buffer_out(SDKCtlQuery* query); 478 479 /******************************************************************************** 480 * SDKCtlSocket API 481 ********************************************************************************/ 482 483 /* Creates an SDK controller socket descriptor. 484 * Param: 485 * reconnect_to - Timeout before trying to reconnect, or retry connection 486 * attempts after disconnection, or on connection failures. 487 * service_name - Name of the SdkController service for this socket (such as 488 * 'sensors', 'milti-touch', etc.) 489 * on_socket_connection - A callback to invoke on socket connection events. 490 * on_port_connection - A callback to invoke on port connection events. 491 * on_message - A callback to invoke when a message is received from the SDK 492 * controller. 493 * opaque - An opaque pointer to associate with the socket. 494 * Return: 495 * Initialized SDKCtlSocket instance on success, or NULL on failure. 496 */ 497 extern SDKCtlSocket* sdkctl_socket_new(int reconnect_to, 498 const char* service_name, 499 on_sdkctl_socket_connection_cb on_socket_connection, 500 on_sdkctl_port_connection_cb on_port_connection, 501 on_sdkctl_message_cb on_message, 502 void* opaque); 503 504 /* Improves throughput by recycling memory allocated for buffers transferred via 505 * this API. 506 * 507 * In many cases data exchanged between SDK controller sides are small, and, 508 * although may come quite often, are coming in a sequential manner. For instance, 509 * sensor service on the device may send us sensor updates every 20ms, one after 510 * another. For such data traffic it makes perfect sense to recycle memory 511 * allocated for the previous sensor update, rather than to free it just to 512 * reallocate same buffer in 20ms. This routine sets properties of the recycler 513 * for the given SDK controller connection. Recycling includes memory allocated 514 * for all types of data transferred in this API: packets, and queries. 515 * Param: 516 * sdkctl - Initialized SDKCtlSocket instance. 517 * data_size - Size of buffer to allocate for each data block. 518 * max_recycled_num - Maximum number of allocated buffers to keep in the 519 * recycler. 520 */ 521 extern void sdkctl_init_recycler(SDKCtlSocket* sdkctl, 522 uint32_t data_size, 523 int max_recycled_num); 524 525 /* References SDKCtlSocket object. 526 * Param: 527 * sdkctl - Initialized SDKCtlSocket instance. 528 * Return: 529 * Number of outstanding references to the object. 530 */ 531 extern int sdkctl_socket_reference(SDKCtlSocket* sdkctl); 532 533 /* Releases SDKCtlSocket object. 534 * Note that upon exit from this routine the object might be destroyed, even if 535 * this routine returns value other than zero. 536 * Param: 537 * sdkctl - Initialized SDKCtlSocket instance. 538 * Return: 539 * Number of outstanding references to the object. 540 */ 541 extern int sdkctl_socket_release(SDKCtlSocket* sdkctl); 542 543 /* Asynchronously connects to SDK controller. 544 * Param: 545 * sdkctl - Initialized SDKCtlSocket instance. 546 * port - TCP port to connect the socket to. 547 * retry_to - Number of milliseconds to wait before retrying a failed 548 * connection attempt. 549 */ 550 extern void sdkctl_socket_connect(SDKCtlSocket* sdkctl, int port, int retry_to); 551 552 /* Asynchronously reconnects to SDK controller. 553 * Param: 554 * sdkctl - Initialized SDKCtlSocket instance. 555 * port - TCP port to reconnect the socket to. 556 * retry_to - Number of milliseconds to wait before reconnecting. Same timeout 557 * will be used for retrying a failed connection attempt. 558 */ 559 extern void sdkctl_socket_reconnect(SDKCtlSocket* sdkctl, int port, int retry_to); 560 561 /* Disconnects from SDK controller. 562 * Param: 563 * sdkctl - Initialized SDKCtlSocket instance. 564 */ 565 extern void sdkctl_socket_disconnect(SDKCtlSocket* sdkctl); 566 567 /* Checks if SDK controller socket is connected. 568 * Param: 569 * sdkctl - Initialized SDKCtlSocket instance. 570 * Return: 571 * Boolean: 1 if socket is connected, 0 if socket is not connected. 572 */ 573 extern int sdkctl_socket_is_connected(SDKCtlSocket* sdkctl); 574 575 /* Checks if SDK controller port is ready for emulation. 576 * Param: 577 * sdkctl - Initialized SDKCtlSocket instance. 578 * Return: 579 * Boolean: 1 if port is ready, 0 if port is not ready. 580 */ 581 extern int sdkctl_socket_is_port_ready(SDKCtlSocket* sdkctl); 582 583 /* Gets status of the SDK controller port for this socket. 584 * Param: 585 * sdkctl - Initialized SDKCtlSocket instance. 586 * Return: 587 * Status of the SDK controller port for this socket. 588 */ 589 extern SdkCtlPortStatus sdkctl_socket_get_port_status(SDKCtlSocket* sdkctl); 590 591 /* Checks if handshake was successful. 592 * Param: 593 * sdkctl - Initialized SDKCtlSocket instance. 594 * Return: 595 * Boolean: 1 if handshake was successful, 0 if handshake was not successful. 596 */ 597 extern int sdkctl_socket_is_handshake_ok(SDKCtlSocket* sdkctl); 598 599 #endif /* ANDROID_SDKCONTROL_SOCKET_H_ */ 600