Home | History | Annotate | Download | only in android
      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