aboutsummaryrefslogtreecommitdiffstats
path: root/android/sdk-controller-socket.h
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2012-04-05 16:22:55 -0700
committerVladimir Chtchetkine <vchtchetkine@google.com>2012-04-06 14:33:17 -0700
commitc8aa2c570d30098da59f1967d5158024ed28570d (patch)
tree894bf051d609573a856e9ec27c50b5b2247e94da /android/sdk-controller-socket.h
parent0f719d093468913f6af7455a7d2d5d7f04edd961 (diff)
downloadexternal_qemu-c8aa2c570d30098da59f1967d5158024ed28570d.zip
external_qemu-c8aa2c570d30098da59f1967d5158024ed28570d.tar.gz
external_qemu-c8aa2c570d30098da59f1967d5158024ed28570d.tar.bz2
Implements SDKCtlSocket that implements communication protocol wih SdkController
In addition, this CL contains some minor tweaks to async-socket, and async-socket-connector that improve tracebility. Change-Id: Ib1309b19dcd02e96379155fea7015019d93160e7
Diffstat (limited to 'android/sdk-controller-socket.h')
-rw-r--r--android/sdk-controller-socket.h440
1 files changed, 440 insertions, 0 deletions
diff --git a/android/sdk-controller-socket.h b/android/sdk-controller-socket.h
new file mode 100644
index 0000000..03b12f4
--- /dev/null
+++ b/android/sdk-controller-socket.h
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SDKCONTROL_SOCKET_H_
+#define ANDROID_SDKCONTROL_SOCKET_H_
+
+#include "android/async-socket.h"
+
+/*
+ * Contains declaration of an API that encapsulates communication protocol with
+ * SdkController running on an Android device.
+ *
+ * SdkController is used to provide:
+ *
+ * - Realistic sensor emulation.
+ * - Multi-touch emulation.
+ * - Open for other types of emulation.
+ *
+ * The idea behind this type of emulation is such that there is an actual
+ * Android device that is connected via USB to the host running the emulator.
+ * On the device there is an SdkController service running that enables
+ * communication between an Android application that gathers information required
+ * by the emulator, and transmits that info to the emulator.
+ *
+ * SdkController service on the device, and SDKCtlSocket API implemented here
+ * implement the exchange protocol between an Android application, and emulation
+ * engine running inside the emulator.
+ *
+ * In turn, the exchange protocol is implemented on top of asynchronous socket
+ * communication (abstracted in AsyncSocket protocol implemented in
+ * android/async-socket.*). It means that connection, and all data transfer
+ * (both, in, and out) are completely asynchronous, and results of each operation
+ * are reported through callbacks.
+ *
+ * Essentially, this entire API implements two types of protocols:
+ *
+ * - Connection protocol.
+ * - Data exchange protocol.
+ *
+ * 1. Connection protocol.
+ *
+ * Connecting to SdkController service on the attached device can be broken down
+ * into two phases:
+ * - Connecting to a TCP socket.
+ * - Sending a "handshake" query to the SdkController.
+ *
+ * 1.1. Connecting to the socket.
+ *
+ * TCP socket connection with SdkController is enabled by using adb port
+ * forwarding. SdkController is always listening to a local abstract socket named
+ * 'android.sdk.controller', so to enable connecting to it from the host, run
+ *
+ * adb forward tcp:<port> localabstract: android.sdk.controller
+ *
+ * After that TCP socket for the requested port can be used to connect to
+ * SdkController, and connecting to it is no different than connecting to any
+ * socket server. Except for one thing: adb port forwarding is implemented in
+ * such a way, that socket_connect will always succeed, even if there is no
+ * server listening to that port on the other side of connection. Moreover,
+ * even socked_send will succeed in this case, so the only way to ensure that
+ * SdkController in deed is listening is to exchange a handshake with it:
+ * Fortunatelly, an attempt to read from forwarded TCP port on condition that
+ * there is no listener on the oher side will fail.
+ *
+ * 1.2. Handshake query.
+ *
+ * Handshake query is a special type of query that SDKCtlSocket sends to the
+ * SdkController upon successful socket connection. This query served two
+ * purposes:
+ * - Informs the SdkController about host endianness. This information is
+ * important, because SdkController needs it in order to format its messages
+ * with proper endianness.
+ * - Ensures that SdkController is in deed listening on the other side of the
+ * connected socket.
+ *
+ * Connection with SdkController is considered to be successfuly established when
+ * SdkController responds to the handshake query, thus, completing the connection.
+ *
+ * 2. Data exchange protocol.
+ *
+ * As it was mentioned above, all data transfer in this API is completely
+ * asynchronous, and result of each data transfer is reported via callbacks.
+ * This also complicates destruction of data involved in exchange, since in an
+ * asynchronous environment it's hard to control the lifespan of an object, its
+ * owner, and who and when is responsible to free resources allocated for the
+ * transfer. To address this issue, all the descriptors that this API operates
+ * with are referenced on use / released after use, and get freed when reference
+ * counter for them drops to zero, indicating that there is no component that is
+ * interested in that particular descriptor.
+ *
+ * There are three types of data in the exchange protocol:
+ * - A packet - the simplest type of data that doesn't require any replies.
+ * - A query - A message that require a reply, and
+ * - A query reply - A message that delivers query reply.
+ */
+
+/* Declares SDK controller socket descriptor. */
+typedef struct SDKCtlSocket SDKCtlSocket;
+
+/* Declares SDK controller data packet descriptor. */
+typedef struct SDKCtlPacket SDKCtlPacket;
+
+/* Declares SDK controller query descriptor. */
+typedef struct SDKCtlQuery SDKCtlQuery;
+
+/* Defines client's callback set to monitor SDK controller socket connection.
+ *
+ * SDKCtlSocket will invoke this callback when connection to TCP port is
+ * established, but before handshake query is processed. The client should use
+ * on_sdkctl_handshake_cb to receive notification about an operational connection
+ * with SdkController.
+ *
+ * The main purpose of this callback for the client is to monitor connection
+ * state: in addition to TCP port connection, this callback will be invoked when
+ * connection with the port is lost.
+ *
+ * Param:
+ * client_opaque - An opaque pointer associated with the client.
+ * sdkctl - Initialized SDKCtlSocket instance.
+ * status - Socket connection status. Can be one of these:
+ * - ASIO_STATE_SUCCEEDED : Socket is connected to the port.
+ * - ASIO_STATE_FAILED : Connection attempt has failed, or connection with
+ * the port is lost.
+ * Return:
+ * One of the AsyncIOAction values.
+ */
+typedef AsyncIOAction (*on_sdkctl_connection_cb)(void* client_opaque,
+ SDKCtlSocket* sdkctl,
+ AsyncIOState status);
+
+/* Defines client's callback set to receive handshake reply from the SdkController
+ * service running on the device.
+ *
+ * Successful handshake means that connection between the client and SDK
+ * controller service has been established.
+ *
+ * Param:
+ * client_opaque - An opaque pointer associated with the client.
+ * sdkctl - Initialized SDKCtlSocket instance.
+ * handshake - Handshake message received from the SDK controller service.
+ * handshake_size - Size of the fandshake message received from the SDK
+ * controller service.
+ * status - Handshake status. Note that handshake, and handshake_size are valid
+ * only if this parameter is set to ASIO_STATE_SUCCEEDED.
+ */
+typedef void (*on_sdkctl_handshake_cb)(void* client_opaque,
+ SDKCtlSocket* sdkctl,
+ void* handshake,
+ uint32_t handshake_size,
+ AsyncIOState status);
+
+/* Defines a message notification callback.
+ * Param:
+ * client_opaque - An opaque pointer associated with the client.
+ * sdkctl - Initialized SDKCtlSocket instance.
+ * message - Descriptor for received message. Note that message descriptor will
+ * be released upon exit from this callback (thus, could be freed along
+ * with message data). If the client is interested in working with that
+ * message after the callback returns, it should reference the message
+ * descriptor in this callback.
+ * msg_type - Message type.
+ * msg_data, msg_size - Message data.
+ */
+typedef void (*on_sdkctl_message_cb)(void* client_opaque,
+ SDKCtlSocket* sdkctl,
+ SDKCtlPacket* message,
+ int msg_type,
+ void* msg_data,
+ int msg_size);
+
+/* Defines query completion callback.
+ * Param:
+ * query_opaque - An opaque pointer associated with the query by the client.
+ * query - Query descriptor. Note that query descriptor will be released upon
+ * exit from this callback (thus, could be freed along with query data). If
+ * the client is interested in working with that query after the callback
+ * returns, it should reference the query descriptor in this callback.
+ * status - Query status. Can be one of these:
+ * - ASIO_STATE_CONTINUES : Query data has been transmitted to the service,
+ * and query is now waiting for response.
+ * - ASIO_STATE_SUCCEEDED : Query has been successfully completed.
+ * - ASIO_STATE_FAILED : Query has failed on an I/O.
+ * - ASIO_STATE_TIMED_OUT : Deadline set for the query has expired.
+ * - ASIO_STATE_CANCELLED : Query has been cancelled due to socket
+ * disconnection.
+ * Return:
+ * One of the AsyncIOAction values.
+ */
+typedef AsyncIOAction (*on_sdkctl_query_cb)(void* query_opaque,
+ SDKCtlQuery* query,
+ AsyncIOState status);
+
+/********************************************************************************
+ * SDKCtlPacket API
+ ********************************************************************************/
+
+/* References SDKCtlPacket object.
+ * Param:
+ * packet - Initialized SDKCtlPacket instance.
+ * Return:
+ * Number of outstanding references to the object.
+ */
+extern int sdkctl_packet_reference(SDKCtlPacket* packet);
+
+/* Releases SDKCtlPacket object.
+ * Note that upon exiting from this routine the object might be destroyed, even
+ * if this routine returns value other than zero.
+ * Param:
+ * packet - Initialized SDKCtlPacket instance.
+ * Return:
+ * Number of outstanding references to the object.
+ */
+extern int sdkctl_packet_release(SDKCtlPacket* packet);
+
+/********************************************************************************
+ * SDKCtlQuery API
+ ********************************************************************************/
+
+/* Creates, and partially initializes query descriptor.
+ * Note that returned descriptor is referenced, and it must be eventually
+ * released with a call to sdkctl_query_release.
+ * Param:
+ * sdkctl - SDKCtlSocket instance for the query.
+ * query_type - Defines query type.
+ * in_data_size Size of the query's input buffer (data to be sent with this
+ * query). Note that buffer for query data will be allocated along with the
+ * query descriptor. Use sdkctl_query_get_buffer_in to get address of data
+ * buffer for this query.
+ * Return:
+ * Referenced SDKCtlQuery descriptor.
+ */
+extern SDKCtlQuery* sdkctl_query_new(SDKCtlSocket* sdkctl,
+ int query_type,
+ uint32_t in_data_size);
+
+/* Creates, and fully initializes query descriptor.
+ * Note that returned descriptor is referenced, and it must be eventually
+ * released with a call to sdkctl_query_release.
+ * Param:
+ * sdkctl - SDKCtlSocket instance for the query.
+ * query_type - Defines query type.
+ * in_data_size Size of the query's input buffer (data to be sent with this
+ * query). Note that buffer for query data will be allocated along with the
+ * query descriptor. Use sdkctl_query_get_buffer_in to get address of data
+ * buffer for this query.
+ * in_data - Data to initialize query's input buffer with.
+ * response_buffer - Contains address of the buffer addressing preallocated
+ * response buffer on the way in, and address of the buffer containing query
+ * response on query completion. If this parameter is NULL, the API will
+ * allocate its own query response buffer, which is going to be freed after
+ * query completion.
+ * response_size - Contains size of preallocated response buffer on the way in,
+ * and size of the received response on query completion. Can be NULL.
+ * query_cb - A callback to monitor query state.
+ * query_opaque - An opaque pointer associated with the query.
+ * Return:
+ * Referenced SDKCtlQuery descriptor.
+ */
+extern SDKCtlQuery* sdkctl_query_new_ex(SDKCtlSocket* sdkctl,
+ int query_type,
+ uint32_t in_data_size,
+ const void* in_data,
+ void** response_buffer,
+ uint32_t* response_size,
+ on_sdkctl_query_cb query_cb,
+ void* query_opaque);
+
+/* Sends query to SDK controller.
+ * Param:
+ * query - Query to send. Note that this must be a fully initialized query
+ * descriptor.
+ * to - Milliseconds to allow for the query to complete. Negative value means
+ * "forever".
+ */
+extern void sdkctl_query_send(SDKCtlQuery* query, int to);
+
+/* Creates, fully initializes query descriptor, and sends the query to SDK
+ * controller.
+ * Note that returned descriptor is referenced, and it must be eventually
+ * released with a call to sdkctl_query_release.
+ * Param:
+ * sdkctl - SDKCtlSocket instance for the query.
+ * query_type - Defines query type.
+ * in_data_size Size of the query's input buffer (data to be sent with this
+ * query). Note that buffer for query data will be allocated along with the
+ * query descriptor. Use sdkctl_query_get_buffer_in to get address of data
+ * buffer for this query.
+ * in_data - Data to initialize query's input buffer with.
+ * response_buffer - Contains address of the buffer addressing preallocated
+ * response buffer on the way in, and address of the buffer containing query
+ * response on query completion. If this parameter is NULL, the API will
+ * allocate its own query response buffer, which is going to be freed after
+ * query completion.
+ * response_size - Contains size of preallocated response buffer on the way in,
+ * and size of the received response on query completion. Can be NULL.
+ * query_cb - A callback to monitor query state.
+ * query_opaque - An opaque pointer associated with the query.
+ * to - Milliseconds to allow for the query to complete. Negative value means
+ * "forever".
+ * Return:
+ * Referenced SDKCtlQuery descriptor for the query that has been sent.
+ */
+extern SDKCtlQuery* sdkctl_query_build_and_send(SDKCtlSocket* sdkctl,
+ int query_type,
+ uint32_t in_data_size,
+ const void* in_data,
+ void** response_buffer,
+ uint32_t* response_size,
+ on_sdkctl_query_cb query_cb,
+ void* query_opaque,
+ int to);
+
+/* References SDKCtlQuery object.
+ * Param:
+ * query - Initialized SDKCtlQuery instance.
+ * Return:
+ * Number of outstanding references to the object.
+ */
+extern int sdkctl_query_reference(SDKCtlQuery* query);
+
+/* Releases SDKCtlQuery object.
+ * Note that upon exit from this routine the object might be destroyed, even if
+ * this routine returns value other than zero.
+ * Param:
+ * query - Initialized SDKCtlQuery instance.
+ * Return:
+ * Number of outstanding references to the object.
+ */
+extern int sdkctl_query_release(SDKCtlQuery* query);
+
+/* Gets address of query's input data buffer (data to be send).
+ * Param:
+ * query - Query to get data buffer for.
+ * Return:
+ * Address of query's input data buffer.
+ */
+extern void* sdkctl_query_get_buffer_in(SDKCtlQuery* query);
+
+/********************************************************************************
+ * SDKCtlSocket API
+ ********************************************************************************/
+
+/* Creates an SDK controller socket descriptor.
+ * Param:
+ * reconnect_to - Timeout before trying to reconnect, or retry connection
+ * attempts after disconnection, or on connection failures.
+ * service_name - Name of the SdkController service for this socket (such as
+ * 'sensors', 'milti-touch', etc.)
+ * on_connection - A callback to invoke on socket connection events.
+ * on_handshake - A callback to invoke on handshake events.
+ * on_message - A callback to invoke when a message is received from the SDK
+ * controller.
+ * opaque - An opaque pointer to associate with the socket.
+ * Return:
+ * Initialized SDKCtlSocket instance on success, or NULL on failure.
+ */
+extern SDKCtlSocket* sdkctl_socket_new(int reconnect_to,
+ const char* service_name,
+ on_sdkctl_connection_cb on_connection,
+ on_sdkctl_handshake_cb on_handshake,
+ on_sdkctl_message_cb on_message,
+ void* opaque);
+
+/* Improves throughput by recycling memory allocated for buffers transferred via
+ * this API.
+ *
+ * In many cases data exchanged between SDK controller sides are small, and,
+ * although may come quite often, are coming in a sequential manner. For instance,
+ * sensor service on the device may send us sensor updates every 20ms, one after
+ * another. For such data traffic it makes perfect sense to recycle memory
+ * allocated for the previous sensor update, rather than to free it just to
+ * reallocate same buffer in 20ms. This routine sets properties of the recycler
+ * for the given SDK controller connection. Recycling includes memory allocated
+ * for all types of data transferred in this API: packets, and queries.
+ * Param:
+ * sdkctl - Initialized SDKCtlSocket instance.
+ * data_size - Size of buffer to allocate for each data block.
+ * max_recycled_num - Maximum number of allocated buffers to keep in the
+ * recycler.
+ */
+extern void sdkctl_init_recycler(SDKCtlSocket* sdkctl,
+ uint32_t data_size,
+ int max_recycled_num);
+
+/* References SDKCtlSocket object.
+ * Param:
+ * sdkctl - Initialized SDKCtlSocket instance.
+ * Return:
+ * Number of outstanding references to the object.
+ */
+extern int sdkctl_socket_reference(SDKCtlSocket* sdkctl);
+
+/* Releases SDKCtlSocket object.
+ * Note that upon exit from this routine the object might be destroyed, even if
+ * this routine returns value other than zero.
+ * Param:
+ * sdkctl - Initialized SDKCtlSocket instance.
+ * Return:
+ * Number of outstanding references to the object.
+ */
+extern int sdkctl_socket_release(SDKCtlSocket* sdkctl);
+
+/* Asynchronously connects to SDK controller.
+ * Param:
+ * sdkctl - Initialized SDKCtlSocket instance.
+ * port - TCP port to connect the socket to.
+ * retry_to - Number of milliseconds to wait before retrying a failed
+ * connection attempt.
+ */
+extern void sdkctl_socket_connect(SDKCtlSocket* sdkctl, int port, int retry_to);
+
+/* Asynchronously reconnects to SDK controller.
+ * Param:
+ * sdkctl - Initialized SDKCtlSocket instance.
+ * port - TCP port to reconnect the socket to.
+ * retry_to - Number of milliseconds to wait before reconnecting. Same timeout
+ * will be used for retrying a failed connection attempt.
+ */
+extern void sdkctl_socket_reconnect(SDKCtlSocket* sdkctl, int port, int retry_to);
+
+/* Disconnects from SDK controller.
+ * Param:
+ * sdkctl - Initialized SDKCtlSocket instance.
+ */
+extern void sdkctl_socket_disconnect(SDKCtlSocket* sdkctl);
+
+#endif /* ANDROID_SDKCONTROL_SOCKET_H_ */