blob: 03b12f4db794e13379d13cb5b4c75b35cdcfdc4f [file] [log] [blame]
Vladimir Chtchetkinec8aa2c52012-04-05 16:22:55 -07001/*
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. */
111typedef struct SDKCtlSocket SDKCtlSocket;
112
113/* Declares SDK controller data packet descriptor. */
114typedef struct SDKCtlPacket SDKCtlPacket;
115
116/* Declares SDK controller query descriptor. */
117typedef 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 */
140typedef 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 */
159typedef 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 */
177typedef 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 */
202typedef 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 */
216extern 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 */
226extern 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 */
245extern 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 */
272extern 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 */
288extern 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 */
316extern 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 */
332extern 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 */
342extern 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 */
350extern 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 */
370extern 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 */
394extern 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 */
404extern 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 */
414extern 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 */
423extern 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 */
432extern 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 */
438extern void sdkctl_socket_disconnect(SDKCtlSocket* sdkctl);
439
440#endif /* ANDROID_SDKCONTROL_SOCKET_H_ */