diff options
Diffstat (limited to 'android/android-device.h')
-rw-r--r-- | android/android-device.h | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/android/android-device.h b/android/android-device.h new file mode 100644 index 0000000..9fde906 --- /dev/null +++ b/android/android-device.h @@ -0,0 +1,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_ */ |