1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
/*
* Copyright (C) 2011 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_ANDROID_DEVICE_H_
#define ANDROID_ANDROID_DEVICE_H_
/*
* Encapsulates an exchange protocol between the emulator, and an Android device
* that is connected to the host via USB. The communication is established over
* a TCP port forwarding, enabled by ADB (always use 'adb -d forward ...' variant
* of this command, so ADB will know to enable port forwarding on the connected
* device, and not on the emulator's guest system).
*
* Exchange protocol contains two channel:
*
* - Query channel.
* - Event channel.
*
* Both channels are implemented on top of TCP sockets that are connected to the
* same port.
*
* I QUERY CHANNEL.
* Query channel is intended to send queries to and receive responses from the
* connected device. It is implemented on top of iolooper_xxx API (see iolooper.h)
* because it must work outside of the main event loop. This is required to enable
* proper initialization of components (such as sensors) that must be set up
* before emulator enters the main loop.
*
* II EVENT CHANNEL.
* Event channel is intended to listen on events sent from the device, and
* asynchronously report them back to the client of this API by invoking an event
* callback that was registered by the client. Event channel is implemented on
* top of asyncXxx API (see android/async-utils.*). Note that using of asyncXxx
* API limits the use of event channel to the time after the emulator has entered
* its main event loop. The only exception is if event channel is connected from
* android_device_connect_sync API, in which case iolooper_xxx API is used to
* establish the connection. However, even in this case listening for events will
* not be available until after the emulator enters its event loop, since event
* listening always uses asyncXxx API.
*
* III. ESTABLISHING CONNECTION.
* ADB port forwarding requires that the server socket is to be run on the device,
* while emulator must use a client socket for communication. Thus, it's the
* emulator that initiates the connection.
*
* There are two ways how emulator can initiate the connection:
*
* - Synchronous connection.
* - Asynchronous connection.
*
* III.I SYNCHROUNOUS CONNECTION.
* Synchronous connection is initiated via android_device_connect_sync API, and
* completes synchronously.
*
* This API should be used when connection with the device is required at the time
* of the call. For instance, when initializing sensor emulation, connection with
* the device is required to properly set up the emulator before the guest system
* starts, and before emulator enters its main event loop.
*
* III.II ASYNCHRONOUS CONNECTION.
* Asynchronous connection is initiated via android_device_connect_async API. The
* main difference with the synchronous connection is that this API will not fail
* if connection is not immediately available. If connection is not available at
* the time of the call, the API will schedule a retry (based on a timer), and
* will continue reprying untill connection becomes available, or until an error
* occurs that prevent further retries.
*
* This API should be used when ... Well, whenever appropriate. For instance,
* sensor emulation will use this API to restore lost connection with the device.
*
* NOTE: Asynchronous connection will complete no sooner than the emulator enters
* its main loop.
*
* IV EXCHANGE PROTOCOL.
* Obviously, there must be some application running on the device, that implements
* a socket server listening on the forwarded TCP port, and accepting the clients.
*
* IV.I Query vs. event channel.
* The exchange protocol assumes, that when a channel is connected, it will
* identify itself by sending a string containing channel type. Only after such
* identification has been made the channel becomes available for use.
*
* IV.II Message format.
* All data that is transferred in both directions over both channels are zero-
* terminated strings.
*/
#include "qemu-common.h"
#include "android/async-utils.h"
#include "android/utils/debug.h"
/* TCP port reserved for sensor emulation. */
#define AD_SENSOR_PORT 1968
/* Definis infinite timeout. */
#define AD_INFINITE_WAIT -1
/* Android device descriptor. */
typedef struct AndroidDevice AndroidDevice;
/********************************************************************************
* Callback declarations
*******************************************************************************/
/* Callback routine that is invoked when android device is connected, or failed
* to connect. As discussed above, this callback is called when both, query and
* event channels have been connected. This callback is used only for asynchronous
* connections.
* Param:
* opaque - Opaque pointer that was passed to android_device_init API.
* ad - Androd device descriptor for the connection.
* failure - Zero indicates that connection with the device has been successfuly
* established. Non-zero vaule passed in this parameter indicates a failure,
* and contains 'errno'-reason for failure.
*/
typedef void (*device_connected_cb)(void* opaque, AndroidDevice* ad, int failure);
/* Callback routine that is invoked on an event received in the event channel.
* NOTE: It's important to check 'errno' in this callback. If 'errno' is set to
* ENOMEM, this signals that buffer passed to android_device_listen was too small
* to contain the entire event message.
* Param:
* opaque - Opaque pointer that was passed to android_device_init API.
* ad - Androd device descriptor for the connection.
* msg - Event message (a zero-terminated string) received from the device.
* msgsize - Event message size (including zero-terminator).
*/
typedef void (*event_cb)(void* opaque, AndroidDevice* ad, char* msg, int msgsize);
/* Callback routine that is invoked when an I/O failure occurs on a channel.
* Note that this callback will not be invoked on connection failures.
* Param:
* opaque - Opaque pointer that was passed to android_device_init API.
* ad - Android device instance
* failure - Contains 'errno' indicating the reason for failure.
*/
typedef void (*io_failure_cb)(void* opaque, AndroidDevice* ad, int failure);
/********************************************************************************
* Android Device API.
*******************************************************************************/
/* Initializes android device descriptor.
* Param:
* opaque - An opaque pointer to associate with the descriptor. This pointer
* will be passed to all callbacks (see above) that were invoked by the
* initializing android device instance.
* port - TCP port to use for connection.
* on_io_failure - Callback to invoke when an I/O failure occurs on a channel
* used by the initializing android device instance. Can be NULL.
* Return:
* Initialized android device descriptor on success, or NULL on failure.
*/
extern AndroidDevice* android_device_init(void* opaque,
int port,
io_failure_cb on_io_failure);
/* Disconnects and destroys android device descriptor.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* Note that memory allocated for this descriptor will be freed in this
* routine.
*/
extern void android_device_destroy(AndroidDevice* ad);
/* Synchronously connects to the device. See notes above for more details.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* to - Milliseconds to wait for connection to be established.
* Return:
* Zero on success, or non-zero value on failure with 'errno' properly set.
*/
extern int android_device_connect_sync(AndroidDevice* ad, int to);
/* Asynchronously connects to the device. See notes above for more details.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* on_connected - Callback to invoke when connection is completed (i,e, both,
* event, and query channels have been connected). This parameter can be
* NULL. Note that connection errors will be also reported through this
* callback. Also note that this callback will be invoked even if this
* routine returns with a failure.
* Return:
* Zero on success, or non-zero value on failure with 'errno' properly set.
*/
extern int android_device_connect_async(AndroidDevice* ad,
device_connected_cb on_connected);
/* Disconnects from the android device.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
*/
extern void android_device_disconnect(AndroidDevice* ad);
/* Queries the device via query channel.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* query - Zero-terminated query string.
* buff, buffsize - Buffer where to receive the response to the query.
* to - Milliseconds to wait for the entire query to complete.
* Return:
* Zero on success, or non-zero value on failure with 'errno' properly set:
* - 0 Indicates that the server has failed the query.
* - Anything else indicates an I/O error.
*/
extern int android_device_query(AndroidDevice* ad,
const char* query,
char* buff,
size_t buffsize,
int to);
/* Start listening on the event channel.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* buff, buffsize - Buffer where to receive the event message.
* on_event - Callback to invoke on event. Note that this callback will be
* invoked even if this routine returns with a failure.
* Return:
* Zero on success, or non-zero value on failure with 'errno' properly set.
*/
extern int android_device_listen(AndroidDevice* ad,
char* buff,
int buffsize,
event_cb on_event);
#endif /* ANDROID_ANDROID_DEVICE_H_ */
|