blob: 68258197f19386a37eaff05cc2a80f094a7db3c4 [file] [log] [blame]
/*
* 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
/* Enumerates results of asynchronous data transfer.
*/
typedef enum ATResult {
/* Data transfer has been completed. */
ATR_SUCCESS,
/* Socket got disconnected while data transfer has been in progress. */
ATR_DISCONNECT,
/* An I/O error has occured. 'errno' contains error value. */
ATR_IO_ERROR,
} ATResult;
/* 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);
/* Callback routine that is invoked when an asynchronous data send has been
* completed.
* Param:
* opaque - An opaque pointer associated with the data.
* res - Result of data transfer.
* data, size - Transferred data buffer.
* sent - Number of sent bytes.
*/
typedef void (*async_send_cb)(void* opaque,
ATResult res,
void* data,
int size,
int sent);
/********************************************************************************
* 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);
/* Starts a query that may require more than one buffer transfer.
* This routine allows to initiate a query that may require more than one call to
* send_data, or may have a format that differs from the usual (a zero-terminated
* string). For instance, sending a BLOB data should use this routine to start a
* a query, then use android_device_send_query_data to transfer the data, and
* then call android_device_complete_query to obtain the response.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* query - Zero-terminated query string.
* 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_start_query(AndroidDevice* ad,
const char* query,
int to);
/* Sends data block for a query started with android_device_start_query
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* data, size - Data to transfer.
* Return:
* Number of bytes transferred on success, or -1 on failure with errno
* containing the reason for failure.
*/
extern int android_device_send_query_data(AndroidDevice* ad,
const void* data,
int size);
/* Completes a query started with android_device_start_query, and receives the
* query response.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* buff, buffsize - Buffer where to receive the response to the query.
* Return:
* Zero on success, or non-zero value on failure with 'errno' properly set.
*/
extern int android_device_complete_query(AndroidDevice* ad, char* buff, size_t buffsize);
/* 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);
/* Asynchronously sends data to the android device.
* Param:
* ad - Android device descriptor, returned from android_device_init API.
* data, size - Buffer containing data to send.
* free_on_close - A boolean flag indicating whether the data buffer should be
* freed upon data transfer completion.
* cb - Callback to invoke when data transfer is completed.
* opaque - An opaque pointer to pass to the transfer completion callback.
*/
extern int android_device_send_async(AndroidDevice* ad,
void* data,
int size,
int free_on_close,
async_send_cb cb,
void* opaque);
#endif /* ANDROID_ANDROID_DEVICE_H_ */