aboutsummaryrefslogtreecommitdiffstats
path: root/android/protocol
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2011-01-26 11:19:19 -0800
committerVladimir Chtchetkine <vchtchetkine@google.com>2011-01-28 09:14:01 -0800
commit777eb68eb60cac18f4b62e2e1b14a906875cbe7a (patch)
tree5850f03e01bb348ad7fc4e92dd08695416650c48 /android/protocol
parent316669d58104cb260e2ffa1848f24547b71af49c (diff)
downloadexternal_qemu-777eb68eb60cac18f4b62e2e1b14a906875cbe7a.zip
external_qemu-777eb68eb60cac18f4b62e2e1b14a906875cbe7a.tar.gz
external_qemu-777eb68eb60cac18f4b62e2e1b14a906875cbe7a.tar.bz2
Refactored ui-core-control and core-ui-control protocols
Also cleaned the code up from obsolete ui-core-protocol.* and core-ui-protocol.* Change-Id: I194bec669d25b68a10c32b2be50bc9da50c52ebb
Diffstat (limited to 'android/protocol')
-rw-r--r--android/protocol/core-commands-api.h95
-rw-r--r--android/protocol/core-commands-impl.c440
-rw-r--r--android/protocol/core-commands-impl.h34
-rw-r--r--android/protocol/core-commands-proxy.c374
-rw-r--r--android/protocol/core-commands-proxy.h32
-rw-r--r--android/protocol/core-commands-qemu.c108
-rw-r--r--android/protocol/core-commands.h104
-rw-r--r--android/protocol/ui-commands-api.h41
-rw-r--r--android/protocol/ui-commands-impl.c257
-rw-r--r--android/protocol/ui-commands-impl.h34
-rw-r--r--android/protocol/ui-commands-proxy.c209
-rw-r--r--android/protocol/ui-commands-proxy.h41
-rw-r--r--android/protocol/ui-commands-qemu.c40
-rw-r--r--android/protocol/ui-commands.h44
-rw-r--r--android/protocol/ui-common.h53
15 files changed, 1906 insertions, 0 deletions
diff --git a/android/protocol/core-commands-api.h b/android/protocol/core-commands-api.h
new file mode 100644
index 0000000..93a569c
--- /dev/null
+++ b/android/protocol/core-commands-api.h
@@ -0,0 +1,95 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_CORE_COMMANDS_API_H
+#define _ANDROID_PROTOCOL_CORE_COMMANDS_API_H
+
+/*
+ * Contains the API for calling into the Core with UI control commands.
+ */
+
+#include "android/android.h"
+#include "android/hw-sensors.h"
+
+/* Instructs the Core to change the coarse orientation.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int corecmd_set_coarse_orientation(AndroidCoarseOrientation orient);
+
+/* Toggles the network in the Core.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int corecmd_toggle_network();
+
+/* Starts or stops tracing in the Core.
+ * Param:
+ * start - Starts (> 0), or stops (== 0) tracing.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int corecmd_trace_control(int start);
+
+/* Checks if network is disabled in the Core.
+ * Return:
+ * 0 if network is enabled, 1 if it is disabled, or < 0 on failure.
+ */
+extern int corecmd_is_network_disabled();
+
+/* Requests a NetworkSpeed instance from the Core.
+ * Param:
+ * index - Index of an entry in the NetworkSpeed array.
+ * netspeed - Upon success contains allocated and initialized NetworkSpeed
+ * instance for the given index. Note that strings addressed by "name" and
+ * "display" fileds in the returned NetworkSpeed instance are containd
+ * inside the buffer allocated for the returned NetworkSpeed instance.
+ * Caller of this routine must eventually free the buffer returned in this
+ * parameter.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int corecmd_get_netspeed(int index, NetworkSpeed** netspeed);
+
+/* Requests a NetworkLatency instance from the Core.
+ * Param:
+ * index - Index of an entry in the NetworkLatency array.
+ * netdelay - Upon success contains allocated and initialized NetworkLatency
+ * instance for the given index. Note that strings addressed by "name" and
+ * "display" fileds in the returned NetworkLatency instance are containd
+ * inside the buffer allocated for the returned NetworkLatency instance.
+ * Caller of this routine must eventually free the buffer returned in this
+ * parameter.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int corecmd_get_netdelay(int index, NetworkLatency** netdelay);
+
+/* Requests a QEMU file path from the Core.
+ * Param:
+ * type, filename - Request parameters that define the file for which path is
+ * requested.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int corecmd_get_qemu_path(int type,
+ const char* filename,
+ char* path,
+ size_t path_buf_size);
+
+/* Gets LCD density property from the core properties.
+ * Return:
+ * LCD density on success, or < 0 on failure.
+ */
+extern int corecmd_get_hw_lcd_density(void);
+
+#endif /* _ANDROID_PROTOCOL_CORE_COMMANDS_API_H */
diff --git a/android/protocol/core-commands-impl.c b/android/protocol/core-commands-impl.c
new file mode 100644
index 0000000..7fa2a0b
--- /dev/null
+++ b/android/protocol/core-commands-impl.c
@@ -0,0 +1,440 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains the Core-side implementation of the "ui-core-control" service that is
+ * part of the UI control protocol. Here we handle UI control commands sent by
+ * the UI to the Core.
+ */
+
+#include "android/android.h"
+#include "android/globals.h"
+#include "telephony/modem_driver.h"
+#include "trace.h"
+#include "android/looper.h"
+#include "android/async-utils.h"
+#include "android/sync-utils.h"
+#include "android/utils/debug.h"
+#include "android/protocol/core-commands.h"
+#include "android/protocol/core-commands-impl.h"
+
+/* Enumerates state values for the command reader in the CoreCmdImpl descriptor.
+ */
+typedef enum CoreCmdImplState {
+ /* The reader is waiting on command header. */
+ EXPECTS_HEADER,
+
+ /* The reader is waiting on command parameters. */
+ EXPECTS_PARAMETERS,
+} CoreCmdImplState;
+
+/* Descriptor for the Core-side implementation of the "ui-core-control" service.
+ */
+typedef struct CoreCmdImpl {
+ /* Reader to detect UI disconnection. */
+ AsyncReader async_reader;
+
+ /* I/O associated with this descriptor. */
+ LoopIo io;
+
+ /* Looper used to communicate with the UI. */
+ Looper* looper;
+
+ /* Writer to send responses to the UI commands. */
+ SyncSocket* sync_writer;
+
+ /* Socket descriptor for this service. */
+ int sock;
+
+ /* Command reader state. */
+ CoreCmdImplState cmd_state;
+
+ /* Incoming command header. */
+ UICmdHeader cmd_header;
+
+ /* A small preallocated buffer for command parameters. */
+ uint8_t cmd_param[256];
+
+ /* Buffer to use for reading command parameters. Depending on expected size
+ * of the parameters this buffer can point to cmd_param field of this
+ * structure (for small commands), or can be allocated for large commands. */
+ void* cmd_param_buf;
+} CoreCmdImpl;
+
+/* One and only one CoreCmdImpl instance. */
+static CoreCmdImpl _coreCmdImpl;
+
+/* Implemented in android/console.c */
+extern void destroy_corecmd_client(void);
+/* Implemented in vl-android.c */
+extern char* qemu_find_file(int type, const char* filename);
+
+/* Properly initializes cmd_param_buf field in CoreCmdImpl instance to receive
+ * the expected command parameters.
+ */
+static uint8_t*
+_alloc_cmd_param_buf(CoreCmdImpl* corecmd, uint32_t size)
+{
+ if (size < sizeof(corecmd->cmd_param)) {
+ // cmd_param can contain all request data.
+ corecmd->cmd_param_buf = &corecmd->cmd_param[0];
+ } else {
+ // Expected request us too large to fit into preallocated buffer.
+ corecmd->cmd_param_buf = qemu_malloc(size);
+ }
+ return corecmd->cmd_param_buf;
+}
+
+/* Properly frees cmd_param_buf field in CoreCmdImpl instance.
+ */
+static void
+_free_cmd_param_buf(CoreCmdImpl* corecmd)
+{
+ if (corecmd->cmd_param_buf != &corecmd->cmd_param[0]) {
+ qemu_free(corecmd->cmd_param_buf);
+ corecmd->cmd_param_buf = &corecmd->cmd_param[0];
+ }
+}
+
+/* Calculates timeout for transferring the given number of bytes via socket.
+ * Return:
+ * Number of milliseconds during which the entire number of bytes is expected
+ * to be transferred via socket for this service.
+ */
+static int
+_coreCmdImpl_get_timeout(size_t data_size)
+{
+ // Min 2 seconds + 10 millisec for each transferring byte.
+ // TODO: Come up with a better arithmetics here.
+ return 2000 + data_size * 10;
+}
+
+/* Sends command response back to the UI.
+ * Param:
+ * corecmd - CoreCmdImpl instance to use to send the response.
+ * resp - Response header.
+ * resp_data - Response data. Data size is defined by the header.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+static int
+_coreCmdImpl_respond(CoreCmdImpl* corecmd, UICmdRespHeader* resp, void* resp_data)
+{
+ int status = syncsocket_start_write(corecmd->sync_writer);
+ if (!status) {
+ // Write the header
+ status = syncsocket_write(corecmd->sync_writer, resp,
+ sizeof(UICmdRespHeader),
+ _coreCmdImpl_get_timeout(sizeof(UICmdRespHeader)));
+ // Write response data (if any).
+ if (status > 0 && resp_data != NULL && resp->resp_data_size != 0) {
+ status = syncsocket_write(corecmd->sync_writer, resp_data,
+ resp->resp_data_size,
+ _coreCmdImpl_get_timeout(resp->resp_data_size));
+ }
+ status = syncsocket_result(status);
+ syncsocket_stop_write(corecmd->sync_writer);
+ }
+ if (status < 0) {
+ derror("Core is unable to respond with %u bytes to the UI control command: %s\n",
+ resp->resp_data_size, errno_str);
+ }
+ return status;
+}
+
+/* Handles UI control command received from the UI.
+ * Param:
+ * corecmd - CoreCmdImpl instance that received the command.
+ * cmd_header - Command header.
+ * cmd_param - Command data.
+ */
+static void
+_coreCmdImpl_handle_command(CoreCmdImpl* corecmd,
+ const UICmdHeader* cmd_header,
+ const uint8_t* cmd_param)
+{
+ switch (cmd_header->cmd_type) {
+ case AUICMD_SET_COARSE_ORIENTATION:
+ {
+ UICmdSetCoarseOrientation* cmd =
+ (UICmdSetCoarseOrientation*)cmd_param;
+ android_sensors_set_coarse_orientation(cmd->orient);
+ break;
+ }
+
+ case AUICMD_TOGGLE_NETWORK:
+ qemu_net_disable = !qemu_net_disable;
+ if (android_modem) {
+ amodem_set_data_registration(
+ android_modem,
+ qemu_net_disable ? A_REGISTRATION_UNREGISTERED
+ : A_REGISTRATION_HOME);
+ }
+ break;
+
+ case AUICMD_TRACE_CONTROL:
+ {
+ UICmdTraceControl* cmd = (UICmdTraceControl*)cmd_param;
+ if (cmd->start) {
+ start_tracing();
+ } else {
+ stop_tracing();
+ }
+ break;
+ }
+
+ case AUICMD_CHK_NETWORK_DISABLED:
+ {
+ UICmdRespHeader resp;
+ resp.resp_data_size = 0;
+ resp.result = qemu_net_disable;
+ _coreCmdImpl_respond(corecmd, &resp, NULL);
+ break;
+ }
+
+ case AUICMD_GET_NETSPEED:
+ {
+ UICmdRespHeader resp;
+ UICmdGetNetSpeedResp* resp_data = NULL;
+ UICmdGetNetSpeed* cmd = (UICmdGetNetSpeed*)cmd_param;
+
+ resp.resp_data_size = 0;
+ resp.result = 0;
+
+ if (cmd->index >= android_netspeeds_count ||
+ android_netspeeds[cmd->index].name == NULL) {
+ resp.result = -1;
+ } else {
+ const NetworkSpeed* netspeed = &android_netspeeds[cmd->index];
+ // Calculate size of the response data:
+ // fixed header + zero-terminated netspeed name.
+ resp.resp_data_size = sizeof(UICmdGetNetSpeedResp) +
+ strlen(netspeed->name) + 1;
+ // Count in zero-terminated netspeed display.
+ if (netspeed->display != NULL) {
+ resp.resp_data_size += strlen(netspeed->display) + 1;
+ } else {
+ resp.resp_data_size++;
+ }
+ // Allocate and initialize response data buffer.
+ resp_data =
+ (UICmdGetNetSpeedResp*)qemu_malloc(resp.resp_data_size);
+ resp_data->upload = netspeed->upload;
+ resp_data->download = netspeed->download;
+ strcpy(resp_data->name, netspeed->name);
+ if (netspeed->display != NULL) {
+ strcpy(resp_data->name + strlen(resp_data->name) + 1,
+ netspeed->display);
+ } else {
+ strcpy(resp_data->name + strlen(resp_data->name) + 1, "");
+ }
+ }
+ _coreCmdImpl_respond(corecmd, &resp, resp_data);
+ if (resp_data != NULL) {
+ qemu_free(resp_data);
+ }
+ break;
+ }
+
+ case AUICMD_GET_NETDELAY:
+ {
+ UICmdRespHeader resp;
+ UICmdGetNetDelayResp* resp_data = NULL;
+ UICmdGetNetDelay* cmd = (UICmdGetNetDelay*)cmd_param;
+
+ resp.resp_data_size = 0;
+ resp.result = 0;
+
+ if (cmd->index >= android_netdelays_count ||
+ android_netdelays[cmd->index].name == NULL) {
+ resp.result = -1;
+ } else {
+ const NetworkLatency* netdelay = &android_netdelays[cmd->index];
+ // Calculate size of the response data:
+ // fixed header + zero-terminated netdelay name.
+ resp.resp_data_size = sizeof(UICmdGetNetDelayResp) +
+ strlen(netdelay->name) + 1;
+ // Count in zero-terminated netdelay display.
+ if (netdelay->display != NULL) {
+ resp.resp_data_size += strlen(netdelay->display) + 1;
+ } else {
+ resp.resp_data_size++;
+ }
+ // Allocate and initialize response data buffer.
+ resp_data =
+ (UICmdGetNetDelayResp*)qemu_malloc(resp.resp_data_size);
+ resp_data->min_ms = netdelay->min_ms;
+ resp_data->max_ms = netdelay->max_ms;
+ strcpy(resp_data->name, netdelay->name);
+ if (netdelay->display != NULL) {
+ strcpy(resp_data->name + strlen(resp_data->name) + 1,
+ netdelay->display);
+ } else {
+ strcpy(resp_data->name + strlen(resp_data->name) + 1, "");
+ }
+ }
+ _coreCmdImpl_respond(corecmd, &resp, resp_data);
+ if (resp_data != NULL) {
+ qemu_free(resp_data);
+ }
+ break;
+ }
+
+ case AUICMD_GET_QEMU_PATH:
+ {
+ UICmdRespHeader resp;
+ UICmdGetQemuPath* cmd = (UICmdGetQemuPath*)cmd_param;
+ char* filepath = NULL;
+
+ resp.resp_data_size = 0;
+ resp.result = -1;
+ filepath = qemu_find_file(cmd->type, cmd->filename);
+ if (filepath != NULL) {
+ resp.resp_data_size = strlen(filepath) + 1;
+ }
+ _coreCmdImpl_respond(corecmd, &resp, filepath);
+ if (filepath != NULL) {
+ qemu_free(filepath);
+ }
+ break;
+ }
+
+ case AUICMD_GET_LCD_DENSITY:
+ {
+ UICmdRespHeader resp;
+ resp.resp_data_size = 0;
+ resp.result = android_hw->hw_lcd_density;
+ _coreCmdImpl_respond(corecmd, &resp, NULL);
+ break;
+ }
+
+ default:
+ derror("Unknown UI control command %d is received by the Core.\n",
+ cmd_header->cmd_type);
+ break;
+ }
+}
+
+/* Asynchronous I/O callback reading UI control commands.
+ * Param:
+ * opaque - CoreCmdImpl instance.
+ * events - Lists I/O event (read or write) this callback is called for.
+ */
+static void
+_coreCmdImpl_io_func(void* opaque, int fd, unsigned events)
+{
+ AsyncStatus status;
+ CoreCmdImpl* corecmd;
+
+ if (events & LOOP_IO_WRITE) {
+ // We don't use async writer here, so we don't expect
+ // any write callbacks.
+ derror("Unexpected LOOP_IO_WRITE in _coreCmdImpl_io_func\n");
+ return;
+ }
+
+ corecmd = (CoreCmdImpl*)opaque;
+
+ // Read whatever is expected from the socket.
+ status = asyncReader_read(&corecmd->async_reader, &corecmd->io);
+ switch (status) {
+ case ASYNC_COMPLETE:
+ switch (corecmd->cmd_state) {
+ case EXPECTS_HEADER:
+ // We just read the command header. Now we expect the param.
+ if (corecmd->cmd_header.cmd_param_size != 0) {
+ corecmd->cmd_state = EXPECTS_PARAMETERS;
+ // Setup the reader to read expected amount of data.
+ _alloc_cmd_param_buf(corecmd,
+ corecmd->cmd_header.cmd_param_size);
+ asyncReader_init(&corecmd->async_reader,
+ corecmd->cmd_param_buf,
+ corecmd->cmd_header.cmd_param_size,
+ &corecmd->io);
+ } else {
+ // Command doesn't have param. Go ahead and handle it.
+ _coreCmdImpl_handle_command(corecmd, &corecmd->cmd_header,
+ NULL);
+ // Prepare for the next header.
+ corecmd->cmd_state = EXPECTS_HEADER;
+ asyncReader_init(&corecmd->async_reader,
+ &corecmd->cmd_header,
+ sizeof(corecmd->cmd_header),
+ &corecmd->io);
+ }
+ break;
+
+ case EXPECTS_PARAMETERS:
+ // Entore command is received. Handle it.
+ _coreCmdImpl_handle_command(corecmd, &corecmd->cmd_header,
+ corecmd->cmd_param_buf);
+ _free_cmd_param_buf(corecmd);
+ // Prepare for the next command.
+ corecmd->cmd_state = EXPECTS_HEADER;
+ asyncReader_init(&corecmd->async_reader, &corecmd->cmd_header,
+ sizeof(corecmd->cmd_header), &corecmd->io);
+ break;
+ }
+ break;
+
+ case ASYNC_ERROR:
+ loopIo_dontWantRead(&corecmd->io);
+ if (errno == ECONNRESET) {
+ // UI has exited. We need to destroy the service.
+ destroy_corecmd_client();
+ }
+ break;
+
+ case ASYNC_NEED_MORE:
+ // Transfer will eventually come back into this routine.
+ return;
+ }
+}
+
+int
+coreCmdImpl_create(int fd)
+{
+ _coreCmdImpl.sock = fd;
+ _coreCmdImpl.looper = looper_newCore();
+ loopIo_init(&_coreCmdImpl.io, _coreCmdImpl.looper, _coreCmdImpl.sock,
+ _coreCmdImpl_io_func, &_coreCmdImpl);
+ _coreCmdImpl.cmd_state = EXPECTS_HEADER;
+ _coreCmdImpl.cmd_param_buf = &_coreCmdImpl.cmd_param[0];
+ asyncReader_init(&_coreCmdImpl.async_reader, &_coreCmdImpl.cmd_header,
+ sizeof(_coreCmdImpl.cmd_header), &_coreCmdImpl.io);
+ _coreCmdImpl.sync_writer = syncsocket_init(fd);
+ if (_coreCmdImpl.sync_writer == NULL) {
+ derror("Unable to create writer for CoreCmdImpl instance: %s\n",
+ errno_str);
+ coreCmdImpl_destroy();
+ return -1;
+ }
+ return 0;
+}
+
+void
+coreCmdImpl_destroy()
+{
+ // Destroy the writer
+ if (_coreCmdImpl.sync_writer != NULL) {
+ syncsocket_close(_coreCmdImpl.sync_writer);
+ syncsocket_free(_coreCmdImpl.sync_writer);
+ }
+ if (_coreCmdImpl.looper != NULL) {
+ // Stop all I/O that may still be going on.
+ loopIo_done(&_coreCmdImpl.io);
+ looper_free(_coreCmdImpl.looper);
+ _coreCmdImpl.looper = NULL;
+ }
+ // Free allocated memory.
+ _free_cmd_param_buf(&_coreCmdImpl);
+}
diff --git a/android/protocol/core-commands-impl.h b/android/protocol/core-commands-impl.h
new file mode 100644
index 0000000..8690613
--- /dev/null
+++ b/android/protocol/core-commands-impl.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_CORE_COMMANDS_IMPL_H
+#define _ANDROID_PROTOCOL_CORE_COMMANDS_IMPL_H
+
+/*
+ * Contains the Core-side implementation of the "ui-core-control" service that is
+ * part of the UI control protocol. Here we handle UI control commands sent by
+ * the UI to the Core.
+ */
+
+/* Creates and initializes descriptor for the Core-side of the "ui-core-control"
+ * service. Note that there can be only one instance of this service in the core.
+ * Param:
+ * fd - Socket descriptor for the service.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int coreCmdImpl_create(int fd);
+
+/* Destroys the descriptor for the Core-side of the "ui-core-control" service. */
+extern void coreCmdImpl_destroy();
+
+#endif /* _ANDROID_PROTOCOL_CORE_COMMANDS_IMPL_H */
diff --git a/android/protocol/core-commands-proxy.c b/android/protocol/core-commands-proxy.c
new file mode 100644
index 0000000..6bd3d4e
--- /dev/null
+++ b/android/protocol/core-commands-proxy.c
@@ -0,0 +1,374 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains the UI-side implementation of the "ui-core-control" service that is
+ * part of the UI control protocol. Here we send UI control commands to the Core.
+ */
+
+#include "console.h"
+#include "android/looper.h"
+#include "android/core-connection.h"
+#include "android/async-utils.h"
+#include "android/sync-utils.h"
+#include "android/utils/debug.h"
+#include "android/utils/panic.h"
+#include "android/protocol/core-commands.h"
+#include "android/protocol/core-commands-proxy.h"
+#include "android/protocol/core-commands-api.h"
+
+/* Descriptor for the UI-side "ui-core-control" service. */
+typedef struct CoreCmdProxy {
+ /* Core connection established for this service. */
+ CoreConnection* core_connection;
+
+ /* Socket descriptor for the UI service. */
+ int sock;
+
+ /* Socket wrapper for sync srites. */
+ SyncSocket* sync_writer;
+
+ /* Socket wrapper for sync reads. */
+ SyncSocket* sync_reader;
+} CoreCmdProxy;
+
+/* One and only one CoreCmdProxy instance. */
+static CoreCmdProxy _coreCmdProxy = { 0 };
+
+/* Sends UI command to the core.
+ * Param:
+ * cmd_type, cmd_param, cmd_param_size - Define the command.
+ * Return:
+ * 0 On success, or < 0 on failure.
+ */
+static int
+_coreCmdProxy_send_command(uint8_t cmd_type,
+ void* cmd_param,
+ uint32_t cmd_param_size)
+{
+ int status;
+ UICmdHeader header;
+
+ // Prepare the command header.
+ header.cmd_type = cmd_type;
+ header.cmd_param_size = cmd_param_size;
+ status = syncsocket_start_write(_coreCmdProxy.sync_writer);
+ if (!status) {
+ // Send the header.
+ status = syncsocket_write(_coreCmdProxy.sync_writer, &header,
+ sizeof(header),
+ core_connection_get_timeout(sizeof(header)));
+ // If there is request data, send it too.
+ if (status > 0 && cmd_param != NULL && cmd_param_size > 0) {
+ status = syncsocket_write(_coreCmdProxy.sync_writer, cmd_param,
+ cmd_param_size,
+ core_connection_get_timeout(cmd_param_size));
+ }
+ status = syncsocket_result(status);
+ syncsocket_stop_write(_coreCmdProxy.sync_writer);
+ }
+ if (status < 0) {
+ derror("Unable to send UI control command %d (size %u): %s\n",
+ cmd_type, cmd_param_size, errno_str);
+ }
+ return status;
+}
+
+/* Reads UI control command response from the core.
+ * Param:
+ * resp - Upon success contains command response header.
+ * resp_data - Upon success contains allocated reponse data (if any). The caller
+ * is responsible for deallocating the memory returned here.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+static int
+_coreCmdProxy_get_response(UICmdRespHeader* resp, void** resp_data)
+{
+ int status = syncsocket_start_read(_coreCmdProxy.sync_reader);
+ if (!status) {
+ // Read the header.
+ status = syncsocket_read(_coreCmdProxy.sync_reader, resp,
+ sizeof(UICmdRespHeader),
+ core_connection_get_timeout(sizeof(UICmdRespHeader)));
+ // Read response data (if any).
+ if (status > 0 && resp->resp_data_size) {
+ *resp_data = malloc(resp->resp_data_size);
+ if (*resp_data == NULL) {
+ APANIC("_coreCmdProxy_get_response is unable to allocate response data buffer.\n");
+ }
+ status = syncsocket_read(_coreCmdProxy.sync_reader, *resp_data,
+ resp->resp_data_size,
+ core_connection_get_timeout(resp->resp_data_size));
+ }
+ status = syncsocket_result(status);
+ syncsocket_stop_read(_coreCmdProxy.sync_reader);
+ }
+ if (status < 0) {
+ derror("Unable to get UI command response from the Core: %s\n",
+ errno_str);
+ }
+ return status;
+}
+
+/* Destroys CoreCmdProxy instance. */
+static void
+_coreCmdProxy_destroy(void)
+{
+ if (_coreCmdProxy.sync_writer != NULL) {
+ syncsocket_close(_coreCmdProxy.sync_writer);
+ syncsocket_free(_coreCmdProxy.sync_writer);
+ }
+ if (_coreCmdProxy.sync_reader != NULL) {
+ syncsocket_close(_coreCmdProxy.sync_reader);
+ syncsocket_free(_coreCmdProxy.sync_reader);
+ }
+ if (_coreCmdProxy.core_connection != NULL) {
+ core_connection_close(_coreCmdProxy.core_connection);
+ core_connection_free(_coreCmdProxy.core_connection);
+ _coreCmdProxy.core_connection = NULL;
+ }
+}
+
+int
+corecmd_set_coarse_orientation(AndroidCoarseOrientation orient)
+{
+ UICmdSetCoarseOrientation cmd;
+ cmd.orient = orient;
+ return _coreCmdProxy_send_command(AUICMD_SET_COARSE_ORIENTATION,
+ &cmd, sizeof(cmd));
+}
+
+int
+corecmd_toggle_network()
+{
+ return _coreCmdProxy_send_command(AUICMD_TOGGLE_NETWORK, NULL, 0);
+}
+
+int
+corecmd_trace_control(int start)
+{
+ UICmdTraceControl cmd;
+ cmd.start = start;
+ return _coreCmdProxy_send_command(AUICMD_TRACE_CONTROL,
+ &cmd, sizeof(cmd));
+}
+
+int
+corecmd_is_network_disabled()
+{
+ UICmdRespHeader resp;
+ void* tmp = NULL;
+ int status;
+
+ status = _coreCmdProxy_send_command(AUICMD_CHK_NETWORK_DISABLED, NULL, 0);
+ if (status < 0) {
+ return status;
+ }
+ status = _coreCmdProxy_get_response(&resp, &tmp);
+ if (status < 0) {
+ return status;
+ }
+ return resp.result;
+}
+
+int
+corecmd_get_netspeed(int index, NetworkSpeed** netspeed)
+{
+ UICmdGetNetSpeed req;
+ UICmdRespHeader resp;
+ UICmdGetNetSpeedResp* resp_data = NULL;
+ int status;
+
+ // Initialize and send the query.
+ req.index = index;
+ status = _coreCmdProxy_send_command(AUICMD_GET_NETSPEED, &req, sizeof(req));
+ if (status < 0) {
+ return status;
+ }
+
+ // Obtain the response from the core.
+ status = _coreCmdProxy_get_response(&resp, (void**)&resp_data);
+ if (status < 0) {
+ return status;
+ }
+ if (!resp.result) {
+ NetworkSpeed* ret;
+ // Allocate memory for the returning NetworkSpeed instance.
+ // It includes: NetworkSpeed structure +
+ // size of zero-terminated "name" and "display" strings saved in
+ // resp_data.
+ *netspeed = malloc(sizeof(NetworkSpeed) + 1 +
+ resp.resp_data_size - sizeof(UICmdGetNetSpeedResp));
+ ret = *netspeed;
+
+ // Copy data obtained from the core to the returning NetworkSpeed
+ // instance.
+ ret->upload = resp_data->upload;
+ ret->download = resp_data->download;
+ ret->name = (char*)ret + sizeof(NetworkSpeed);
+ strcpy((char*)ret->name, resp_data->name);
+ ret->display = ret->name + strlen(ret->name) + 1;
+ strcpy((char*)ret->display, resp_data->name + strlen(resp_data->name) + 1);
+ }
+ if (resp_data != NULL) {
+ free(resp_data);
+ }
+ return resp.result;
+}
+
+int
+corecmd_get_netdelay(int index, NetworkLatency** netdelay)
+{
+ UICmdGetNetDelay req;
+ UICmdRespHeader resp;
+ UICmdGetNetDelayResp* resp_data = NULL;
+ int status;
+
+ // Initialize and send the query.
+ req.index = index;
+ status = _coreCmdProxy_send_command(AUICMD_GET_NETDELAY, &req, sizeof(req));
+ if (status < 0) {
+ return status;
+ }
+
+ // Obtain the response from the core.
+ status = _coreCmdProxy_get_response(&resp, (void**)&resp_data);
+ if (status < 0) {
+ return status;
+ }
+ if (!resp.result) {
+ NetworkLatency* ret;
+ // Allocate memory for the returning NetworkLatency instance.
+ // It includes: NetworkLatency structure +
+ // size of zero-terminated "name" and "display" strings saved in
+ // resp_data.
+ *netdelay = malloc(sizeof(NetworkLatency) + 1 +
+ resp.resp_data_size - sizeof(UICmdGetNetDelayResp));
+ ret = *netdelay;
+
+ // Copy data obtained from the core to the returning NetworkLatency
+ // instance.
+ ret->min_ms = resp_data->min_ms;
+ ret->max_ms = resp_data->max_ms;
+ ret->name = (char*)ret + sizeof(NetworkLatency);
+ strcpy((char*)ret->name, resp_data->name);
+ ret->display = ret->name + strlen(ret->name) + 1;
+ strcpy((char*)ret->display, resp_data->name + strlen(resp_data->name) + 1);
+ }
+ if (resp_data != NULL) {
+ free(resp_data);
+ }
+ return resp.result;
+}
+
+int
+corecmd_get_qemu_path(int type,
+ const char* filename,
+ char* path,
+ size_t path_buf_size)
+{
+ UICmdRespHeader resp;
+ char* resp_data = NULL;
+ int status;
+
+ // Initialize and send the query.
+ uint32_t cmd_data_size = sizeof(UICmdGetQemuPath) + strlen(filename) + 1;
+ UICmdGetQemuPath* req = (UICmdGetQemuPath*)malloc(cmd_data_size);
+ if (req == NULL) {
+ APANIC("corecmd_get_qemu_path is unable to allocate %u bytes\n",
+ cmd_data_size);
+ }
+ req->type = type;
+ strcpy(req->filename, filename);
+ status = _coreCmdProxy_send_command(AUICMD_GET_QEMU_PATH, req,
+ cmd_data_size);
+ if (status < 0) {
+ return status;
+ }
+
+ // Obtain the response from the core.
+ status = _coreCmdProxy_get_response(&resp, (void**)&resp_data);
+ if (status < 0) {
+ return status;
+ }
+ if (!resp.result && resp_data != NULL) {
+ strncpy(path, resp_data, path_buf_size);
+ path[path_buf_size - 1] = '\0';
+ }
+ if (resp_data != NULL) {
+ free(resp_data);
+ }
+ return resp.result;
+}
+
+int
+corecmd_get_hw_lcd_density(void)
+{
+ UICmdRespHeader resp;
+ void* tmp = NULL;
+ int status;
+
+ status = _coreCmdProxy_send_command(AUICMD_GET_LCD_DENSITY, NULL, 0);
+ if (status < 0) {
+ return status;
+ }
+ status = _coreCmdProxy_get_response(&resp, &tmp);
+ if (status < 0) {
+ return status;
+ }
+ return resp.result;
+}
+
+int
+coreCmdProxy_create(SockAddress* console_socket)
+{
+ char* handshake = NULL;
+
+ // Connect to the ui-core-control service.
+ _coreCmdProxy.core_connection =
+ core_connection_create_and_switch(console_socket, "ui-core-control",
+ &handshake);
+ if (_coreCmdProxy.core_connection == NULL) {
+ derror("Unable to connect to the ui-core-control service: %s\n",
+ errno_str);
+ return -1;
+ }
+
+ // Initialze command writer and response reader.
+ _coreCmdProxy.sock = core_connection_get_socket(_coreCmdProxy.core_connection);
+ _coreCmdProxy.sync_writer = syncsocket_init(_coreCmdProxy.sock);
+ if (_coreCmdProxy.sync_writer == NULL) {
+ derror("Unable to initialize CoreCmdProxy writer: %s\n", errno_str);
+ _coreCmdProxy_destroy();
+ return -1;
+ }
+ _coreCmdProxy.sync_reader = syncsocket_init(_coreCmdProxy.sock);
+ if (_coreCmdProxy.sync_reader == NULL) {
+ derror("Unable to initialize CoreCmdProxy reader: %s\n", errno_str);
+ _coreCmdProxy_destroy();
+ return -1;
+ }
+
+
+ fprintf(stdout, "ui-core-control is now connected to the core at %s.",
+ sock_address_to_string(console_socket));
+ if (handshake != NULL) {
+ if (handshake[0] != '\0') {
+ fprintf(stdout, " Handshake: %s", handshake);
+ }
+ free(handshake);
+ }
+ fprintf(stdout, "\n");
+
+ return 0;
+}
diff --git a/android/protocol/core-commands-proxy.h b/android/protocol/core-commands-proxy.h
new file mode 100644
index 0000000..8303ed4
--- /dev/null
+++ b/android/protocol/core-commands-proxy.h
@@ -0,0 +1,32 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_CORE_COMMANDS_PROXY_H
+#define _ANDROID_PROTOCOL_CORE_COMMANDS_PROXY_H
+
+#include "sockets.h"
+
+/*
+ * Contains the UI-side implementation of the "ui-core-control" service that is
+ * part of the UI control protocol. Here we send UI control commands to the Core.
+ */
+
+/* Creates and initializes descriptor for the UI-side of the "ui-core-control"
+ * service. Note that there can be only one instance of this service in the UI.
+ * Param:
+ * console_socket - Addresses Core's console.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int coreCmdProxy_create(SockAddress* console_socket);
+
+#endif /* _ANDROID_PROTOCOL_CORE_COMMANDS_PROXY_H */
diff --git a/android/protocol/core-commands-qemu.c b/android/protocol/core-commands-qemu.c
new file mode 100644
index 0000000..03fef64
--- /dev/null
+++ b/android/protocol/core-commands-qemu.c
@@ -0,0 +1,108 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains implementation of the API for calling into the Core with the UI
+ * control commands for standalone (monolithic) emulator.
+ */
+
+#include "android/android.h"
+#include "android/globals.h"
+#include "android/hw-sensors.h"
+#include "telephony/modem_driver.h"
+#include "trace.h"
+#include "audio/audio.h"
+#include "android/protocol/core-commands-api.h"
+
+/* Implemented in vl-android.c */
+extern char* qemu_find_file(int type, const char* filename);
+
+int
+corecmd_set_coarse_orientation(AndroidCoarseOrientation orient)
+{
+ android_sensors_set_coarse_orientation(orient);
+ return 0;
+}
+
+int
+corecmd_toggle_network()
+{
+ qemu_net_disable = !qemu_net_disable;
+ if (android_modem) {
+ amodem_set_data_registration(
+ android_modem,
+ qemu_net_disable ? A_REGISTRATION_UNREGISTERED
+ : A_REGISTRATION_HOME);
+ }
+ return 0;
+}
+
+int corecmd_trace_control(int start)
+{
+ if (start) {
+ start_tracing();
+ } else {
+ stop_tracing();
+ }
+ return 0;
+}
+
+int corecmd_is_network_disabled()
+{
+ return qemu_net_disable;
+}
+
+int
+corecmd_get_netspeed(int index, NetworkSpeed** netspeed)
+{
+ if (index >= android_netspeeds_count ||
+ android_netspeeds[index].name == NULL) {
+ return -1;
+ }
+ *netspeed = (NetworkSpeed*)malloc(sizeof(NetworkSpeed));
+ memcpy(*netspeed, &android_netspeeds[index], sizeof(NetworkSpeed));
+ return 0;
+}
+
+int
+corecmd_get_netdelay(int index, NetworkLatency** netdelay)
+{
+ if (index >= android_netdelays_count ||
+ android_netdelays[index].name == NULL) {
+ return -1;
+ }
+ *netdelay = (NetworkLatency*)malloc(sizeof(NetworkLatency));
+ memcpy(*netdelay, &android_netdelays[index], sizeof(NetworkLatency));
+ return 0;
+}
+
+int
+corecmd_get_qemu_path(int type,
+ const char* filename,
+ char* path,
+ size_t path_buf_size)
+{
+ char* filepath = qemu_find_file(type, filename);
+ if (filepath == NULL) {
+ return -1;
+ }
+ strncpy(path, filepath, path_buf_size);
+ path[path_buf_size - 1] = '\0';
+ qemu_free(filepath);
+ return 0;
+}
+
+int
+corecmd_get_hw_lcd_density(void)
+{
+ return android_hw->hw_lcd_density;
+}
diff --git a/android/protocol/core-commands.h b/android/protocol/core-commands.h
new file mode 100644
index 0000000..3ac0ca5
--- /dev/null
+++ b/android/protocol/core-commands.h
@@ -0,0 +1,104 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_CORE_COMMANDS_H
+#define _ANDROID_PROTOCOL_CORE_COMMANDS_H
+
+/*
+ * Contains declarations related to the UI control commands sent by the UI and
+ * handled by the Core.
+ */
+
+#include "android/hw-sensors.h"
+#include "android/protocol/ui-common.h"
+
+/* Sets coarse orientation. */
+#define AUICMD_SET_COARSE_ORIENTATION 1
+
+/* Toggles the network. */
+#define AUICMD_TOGGLE_NETWORK 2
+
+/* Starts / stops the tracing. */
+#define AUICMD_TRACE_CONTROL 3
+
+/* Checks if network is disabled. */
+#define AUICMD_CHK_NETWORK_DISABLED 4
+
+/* Gets network speed. */
+#define AUICMD_GET_NETSPEED 5
+
+/* Gets network delays */
+#define AUICMD_GET_NETDELAY 6
+
+/* Gets path to a QEMU file on local host. */
+#define AUICMD_GET_QEMU_PATH 7
+
+/* Gets LCD density. */
+#define AUICMD_GET_LCD_DENSITY 8
+
+/* Formats AUICMD_SET_COARSE_ORIENTATION UI control command parameters. */
+typedef struct UICmdSetCoarseOrientation {
+ AndroidCoarseOrientation orient;
+} UICmdSetCoarseOrientation;
+
+/* Formats AUICMD_TRACE_CONTROL UI control command parameters. */
+typedef struct UICmdTraceControl {
+ int start;
+} UICmdTraceControl;
+
+/* Formats AUICMD_GET_NETSPEED UI control command parameters. */
+typedef struct UICmdGetNetSpeed {
+ int index;
+} UICmdGetNetSpeed;
+
+/* Formats AUICMD_GET_NETSPEED UI control command response.
+ * Instances of this structure contains content of the NetworkSpeed structure,
+ * including actual "name" and "display" strings. */
+typedef struct UICmdGetNetSpeedResp {
+ int upload;
+ int download;
+ /* Zero-terminated NetworkSpeed's "name" strings starts here. The "display"
+ * string begins inside this structure, right after the "name"'s
+ * zero-terminator. */
+ char name[0];
+} UICmdGetNetSpeedResp;
+
+/* Formats AUICMD_GET_NETDELAY UI control command parameters. */
+typedef struct UICmdGetNetDelay {
+ int index;
+} UICmdGetNetDelay;
+
+/* Formats AUICMD_GET_NETDELAY UI control command response.
+ * Instances of this structure contains content of the NetworkLatency structure,
+ * including actual "name" and "display" strings. */
+typedef struct UICmdGetNetDelayResp {
+ int min_ms;
+ int max_ms;
+ /* Zero-terminated NetworkLatency's "name" strings starts here. The "display"
+ * string begins inside this structure, right after the "name"'s
+ * zero-terminator. */
+ char name[0];
+} UICmdGetNetDelayResp;
+
+/* Formats AUICMD_GET_QEMU_PATH UI control command parameters. */
+typedef struct UICmdGetQemuPath {
+ int type;
+ char filename[0];
+} UICmdGetQemuPath;
+
+/* Formats AUICMD_GET_QEMU_PATH UI control command response. */
+typedef struct UICmdGetQemuPathResp {
+ /* Queried qemu path begins here. */
+ char path[0];
+} UICmdGetQemuPathResp;
+
+#endif /* _ANDROID_PROTOCOL_CORE_COMMANDS_H */
diff --git a/android/protocol/ui-commands-api.h b/android/protocol/ui-commands-api.h
new file mode 100644
index 0000000..d9fe6b0
--- /dev/null
+++ b/android/protocol/ui-commands-api.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_UI_COMMANDS_API_H
+#define _ANDROID_PROTOCOL_UI_COMMANDS_API_H
+
+/*
+ * Contains the API for calling into the UI with the Core control commands.
+ */
+
+/* Changes the scale of the emulator window at runtime.
+ * Param:
+ * scale, is_dpi - New window scale parameters
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int uicmd_set_window_scale(double scale, int is_dpi);
+
+/* This is temporary redeclaration for AndroidHwLightBrightnessFunc declared
+ * in android/hw-control.h We redeclare it here in order to keep type
+ * consistency between android_core_set_brightness_change_callback and
+ * light_brightness field of AndroidHwControlFuncs structure.
+ */
+typedef void (*AndroidHwLightBrightnessCallback)(void* opaque,
+ const char* light,
+ int brightness);
+
+/* Registers a UI callback to be called when brightness is changed by the core. */
+extern int uicmd_set_brightness_change_callback(AndroidHwLightBrightnessCallback callback,
+ void* opaque);
+
+#endif /* _ANDROID_PROTOCOL_UI_COMMANDS_API_H */
diff --git a/android/protocol/ui-commands-impl.c b/android/protocol/ui-commands-impl.c
new file mode 100644
index 0000000..456c61e
--- /dev/null
+++ b/android/protocol/ui-commands-impl.c
@@ -0,0 +1,257 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains the UI-side implementation of the "core-ui-control" service that is
+ * part of the UI control protocol. Here we handle UI control commands received
+ * from the Core.
+ */
+
+#include "console.h"
+//#include "android/hw-control.h"
+#include "android/looper.h"
+#include "android/core-connection.h"
+#include "android/async-utils.h"
+#include "android/sync-utils.h"
+#include "android/utils/system.h"
+#include "android/utils/debug.h"
+#include "android/utils/panic.h"
+#include "android/protocol/ui-commands-impl.h"
+#include "android/protocol/ui-commands-api.h"
+
+/* Enumerates states for the command reader in UICmdImpl instance. */
+typedef enum UICmdImplState {
+ /* The reader is waiting on command header. */
+ EXPECTS_HEADER,
+
+ /* The reader is waiting on command parameters. */
+ EXPECTS_PARAMETERS,
+} UICmdImplState;
+
+/* Descriptor for the UI-side of the "core-ui-control" service. */
+typedef struct UICmdImpl {
+ /* Core connection established for this service. */
+ CoreConnection* core_connection;
+
+ /* Socket descriptor for the UI service. */
+ int sock;
+
+ /* Command reader state. */
+ UICmdImplState reader_state;
+
+ /* Incoming command header. */
+ UICmdHeader cmd_header;
+
+ /* Reader's buffer. This field can point to the cmd_header field of this
+ * structure (when we expect a command header), or to a buffer allocated for
+ * the (when we expect command parameters). */
+ uint8_t* reader_buffer;
+
+ /* Offset in the reader's buffer where to read next chunk of data. */
+ size_t reader_offset;
+
+ /* Total number of bytes the reader expects to read. */
+ size_t reader_bytes;
+} UICmdImpl;
+
+/* Implemented in android/qemulator.c */
+extern void android_emulator_set_window_scale(double scale, int is_dpi);
+
+/* One and only one UICmdImpl instance. */
+static UICmdImpl _uiCmdImpl;
+
+/* Display brightness change callback. */
+static AndroidHwLightBrightnessCallback _brightness_change_callback = NULL;
+static void* _brightness_change_callback_param = NULL;
+
+/* Destroys UICmdImpl instance. */
+static void
+_uiCmdImpl_destroy()
+{
+ if (_uiCmdImpl.core_connection != NULL) {
+ // Disable I/O callbacks.
+ qemu_set_fd_handler(_uiCmdImpl.sock, NULL, NULL, NULL);
+ core_connection_close(_uiCmdImpl.core_connection);
+ core_connection_free(_uiCmdImpl.core_connection);
+ _uiCmdImpl.core_connection = NULL;
+ }
+ // Properly deallocate the reader buffer.
+ if (_uiCmdImpl.reader_buffer != NULL &&
+ _uiCmdImpl.reader_buffer != (uint8_t*)&_uiCmdImpl.cmd_header) {
+ free(_uiCmdImpl.reader_buffer);
+ _uiCmdImpl.reader_buffer = (uint8_t*)&_uiCmdImpl.cmd_header;
+ }
+}
+
+/* Handles UI control command received from the core.
+ * Param:
+ * uicmd - UICmdImpl instance that received the command.
+ * header - UI control command header.
+ * data - Command parameters formatted accordingly to the command type.
+ */
+static void
+_uiCmdImpl_handle_command(UICmdImpl* uicmd,
+ const UICmdHeader* header,
+ const uint8_t* data)
+{
+ switch (header->cmd_type) {
+ case AUICMD_SET_WINDOWS_SCALE:
+ {
+ UICmdSetWindowsScale* cmd = (UICmdSetWindowsScale*)data;
+ android_emulator_set_window_scale(cmd->scale, cmd->is_dpi);
+ break;
+ }
+
+ case AUICMD_CHANGE_DISP_BRIGHTNESS:
+ {
+ UICmdChangeDispBrightness* cmd = (UICmdChangeDispBrightness*)data;
+ if (_brightness_change_callback != NULL) {
+ _brightness_change_callback(_brightness_change_callback_param,
+ cmd->light, cmd->brightness);
+ }
+ break;
+ }
+
+ default:
+ derror("Unknown command %d is received from the Core\n",
+ header->cmd_type);
+ break;
+ }
+}
+
+/* Asynchronous I/O callback reading UI control commands.
+ * Param:
+ * opaque - UICmdImpl instance.
+ */
+static void
+_uiCmdImpl_io_read(void* opaque)
+{
+ UICmdImpl* uicmd = opaque;
+ int status;
+
+ // Read requests while they are immediately available.
+ for (;;) {
+ // Read next chunk of data.
+ status = read(uicmd->sock, uicmd->reader_buffer + uicmd->reader_offset,
+ uicmd->reader_bytes - uicmd->reader_offset);
+ if (status == 0) {
+ /* Disconnection, meaning that the core process got termonated. */
+ fprintf(stderr, "core-ui-control service got disconnected\n");
+ _uiCmdImpl_destroy();
+ return;
+ }
+ if (status < 0) {
+ if (errno == EINTR) {
+ /* loop on EINTR */
+ continue;
+ } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ // Chunk is not avalable at this point. Come back later.
+ return;
+ }
+ }
+
+ uicmd->reader_offset += status;
+ if (uicmd->reader_offset != uicmd->reader_bytes) {
+ // There are still some data left in the pipe.
+ continue;
+ }
+
+ // All expected data has been read. Time to change the state.
+ if (uicmd->reader_state == EXPECTS_HEADER) {
+ // Header has been read.
+ if (uicmd->cmd_header.cmd_param_size) {
+ // Prepare for the command parameters.
+ uicmd->reader_state = EXPECTS_PARAMETERS;
+ uicmd->reader_offset = 0;
+ uicmd->reader_bytes = uicmd->cmd_header.cmd_param_size;
+ uicmd->reader_buffer = malloc(uicmd->reader_bytes);
+ if (uicmd->reader_buffer == NULL) {
+ APANIC("Unable to allocate memory for UI command parameters.\n");
+ }
+ } else {
+ // This command doesn't have any parameters. Handle it now.
+ _uiCmdImpl_handle_command(uicmd, &uicmd->cmd_header, NULL);
+ // Prepare for the next command header.
+ uicmd->reader_state = EXPECTS_HEADER;
+ uicmd->reader_offset = 0;
+ uicmd->reader_bytes = sizeof(uicmd->cmd_header);
+ uicmd->reader_buffer = (uint8_t*)&uicmd->cmd_header;
+ }
+ } else {
+ // All command data is in. Handle it.
+ _uiCmdImpl_handle_command(uicmd, &uicmd->cmd_header,
+ uicmd->reader_buffer);
+ // Prepare for the next command header.
+ free(uicmd->reader_buffer);
+ uicmd->reader_state = EXPECTS_HEADER;
+ uicmd->reader_offset = 0;
+ uicmd->reader_bytes = sizeof(uicmd->cmd_header);
+ uicmd->reader_buffer = (uint8_t*)&uicmd->cmd_header;
+ }
+ }
+}
+
+int
+uiCmdImpl_create(SockAddress* console_socket)
+{
+ char* handshake = NULL;
+
+ // Setup command reader.
+ _uiCmdImpl.reader_buffer = (uint8_t*)&_uiCmdImpl.cmd_header;
+ _uiCmdImpl.reader_state = EXPECTS_HEADER;
+ _uiCmdImpl.reader_offset = 0;
+ _uiCmdImpl.reader_bytes = sizeof(UICmdHeader);
+
+ // Connect to the core-ui-control service.
+ _uiCmdImpl.core_connection =
+ core_connection_create_and_switch(console_socket, "core-ui-control",
+ &handshake);
+ if (_uiCmdImpl.core_connection == NULL) {
+ derror("Unable to connect to the core-ui-control service: %s\n",
+ errno_str);
+ return -1;
+ }
+
+ // Initialze UI command reader.
+ _uiCmdImpl.sock = core_connection_get_socket(_uiCmdImpl.core_connection);
+ if (qemu_set_fd_handler(_uiCmdImpl.sock, _uiCmdImpl_io_read, NULL,
+ &_uiCmdImpl)) {
+ derror("Unable to set up UI _uiCmdImpl_io_read callback: %s\n",
+ errno_str);
+ _uiCmdImpl_destroy();
+ if (handshake != NULL) {
+ free(handshake);
+ }
+ return -1;
+ }
+
+ fprintf(stdout, "core-ui-control is now connected to the core at %s.",
+ sock_address_to_string(console_socket));
+ if (handshake != NULL) {
+ if (handshake[0] != '\0') {
+ fprintf(stdout, " Handshake: %s", handshake);
+ }
+ free(handshake);
+ }
+ fprintf(stdout, "\n");
+
+ return 0;
+}
+
+int
+uicmd_set_brightness_change_callback(AndroidHwLightBrightnessCallback callback,
+ void* opaque)
+{
+ _brightness_change_callback = callback;
+ _brightness_change_callback_param = opaque;
+ return 0;
+}
diff --git a/android/protocol/ui-commands-impl.h b/android/protocol/ui-commands-impl.h
new file mode 100644
index 0000000..0e5b52f
--- /dev/null
+++ b/android/protocol/ui-commands-impl.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_UI_COMMANDS_IMPL_H
+#define _ANDROID_PROTOCOL_UI_COMMANDS_IMPL_H
+
+#include "sockets.h"
+#include "android/protocol/ui-commands.h"
+
+/*
+ * Contains the UI-side implementation of the "core-ui-control" service that is
+ * part of the UI control protocol. Here we handle UI control commands sent by
+ * the Core to the UI.
+ */
+
+/* Creates and initializes descriptor for the UI-side of the "core-ui-control"
+ * service. Note that there can be only one instance of this service in the UI.
+ * Param:
+ * console_socket - Addresses Core's console.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int uiCmdImpl_create(SockAddress* console_socket);
+
+#endif /* _ANDROID_PROTOCOL_UI_COMMANDS_IMPL_H */
diff --git a/android/protocol/ui-commands-proxy.c b/android/protocol/ui-commands-proxy.c
new file mode 100644
index 0000000..76bf883
--- /dev/null
+++ b/android/protocol/ui-commands-proxy.c
@@ -0,0 +1,209 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains the Core-side implementation of the "core-ui-control" service that is
+ * part of the UI control protocol. Here we send UI control commands to the UI.
+ */
+
+#include "android/android.h"
+#include "android/hw-control.h"
+#include "android/looper.h"
+#include "android/async-utils.h"
+#include "android/sync-utils.h"
+#include "android/utils/debug.h"
+#include "android/protocol/ui-commands.h"
+#include "android/protocol/ui-commands-proxy.h"
+#include "android/protocol/ui-commands-api.h"
+
+/* Descriptor for the UI commands proxy. */
+typedef struct UICmdProxy {
+ /* I/O associated with this descriptor. */
+ LoopIo io;
+
+ /* Looper associated with this descriptor. */
+ Looper* looper;
+
+ /* Writer to send UI commands. */
+ SyncSocket* sync_writer;
+
+ /* Socket descriptor for this service. */
+ int sock;
+} UICmdProxy;
+
+/* One and only one UICmdProxy instance. */
+static UICmdProxy _uiCmdProxy;
+
+/* Implemented in android/console.c */
+extern void destroy_uicmd_client(void);
+
+/* Calculates timeout for transferring the given number of bytes via socket.
+ * Return:
+ * Number of milliseconds during which the entire number of bytes is expected
+ * to be transferred via socket.
+ */
+static int
+_uiCmdProxy_get_timeout(size_t data_size)
+{
+ // Min 2 seconds + 10 millisec for each transferring byte.
+ // TODO: Come up with a better arithmetics here.
+ return 2000 + data_size * 10;
+}
+
+/* Sends request to the UI client of this service.
+ * Param:
+ * cmd_type, cmd_param, cmd_param_size - Define the command to send.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+static int
+_uiCmdProxy_send_command(uint8_t cmd_type,
+ void* cmd_param,
+ uint32_t cmd_param_size)
+{
+ UICmdHeader header;
+ int status = syncsocket_start_write(_uiCmdProxy.sync_writer);
+ if (!status) {
+ // Initialize and send the header.
+ header.cmd_type = cmd_type;
+ header.cmd_param_size = cmd_param_size;
+ status = syncsocket_write(_uiCmdProxy.sync_writer, &header, sizeof(header),
+ _uiCmdProxy_get_timeout(sizeof(header)));
+ // If there are command parameters, send them too.
+ if (status > 0 && cmd_param != NULL && cmd_param_size > 0) {
+ status = syncsocket_write(_uiCmdProxy.sync_writer, cmd_param,
+ cmd_param_size,
+ _uiCmdProxy_get_timeout(cmd_param_size));
+ }
+ status = syncsocket_result(status);
+ syncsocket_stop_write(_uiCmdProxy.sync_writer);
+ }
+ if (status < 0) {
+ derror("Send UI command %d (%u bytes) has failed: %s\n",
+ cmd_type, cmd_param_size, errno_str);
+ }
+ return status;
+}
+
+/* Asynchronous I/O callback for UICmdProxy instance.
+ * We expect this callback to be called only on UI detachment condition. In this
+ * case the event should be LOOP_IO_READ, and read should fail with errno set
+ * to ECONNRESET.
+ * Param:
+ * opaque - UICmdProxy instance.
+ */
+static void
+_uiCmdProxy_io_func(void* opaque, int fd, unsigned events)
+{
+ UICmdProxy* uicmd = (UICmdProxy*)opaque;
+ AsyncReader reader;
+ AsyncStatus status;
+ uint8_t read_buf[1];
+
+ if (events & LOOP_IO_WRITE) {
+ derror("Unexpected LOOP_IO_WRITE in _uiCmdProxy_io_func.\n");
+ return;
+ }
+
+ // Try to read
+ asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io);
+ status = asyncReader_read(&reader, &uicmd->io);
+ // We expect only error status here.
+ if (status != ASYNC_ERROR) {
+ derror("Unexpected read status %d in _uiCmdProxy_io_func\n", status);
+ return;
+ }
+ // We expect only socket disconnection error here.
+ if (errno != ECONNRESET) {
+ derror("Unexpected read error %d (%s) in _uiCmdProxy_io_func.\n",
+ errno, errno_str);
+ return;
+ }
+
+ // Client got disconnectted.
+ destroy_uicmd_client();
+}
+/* a callback function called when the system wants to change the brightness
+ * of a given light. 'light' is a string which can be one of:
+ * 'lcd_backlight', 'button_backlight' or 'Keyboard_backlight'
+ *
+ * brightness is an integer (acceptable range are 0..255), however the
+ * default is around 105, and we probably don't want to dim the emulator's
+ * output at that level.
+ */
+static void
+_uiCmdProxy_brightness_change_callback(void* opaque,
+ const char* light,
+ int brightness)
+{
+ // Calculate size of the command parameters.
+ const size_t cmd_size = sizeof(UICmdChangeDispBrightness) + strlen(light) + 1;
+ // Allocate and initialize parameters.
+ UICmdChangeDispBrightness* cmd =
+ (UICmdChangeDispBrightness*)qemu_malloc(cmd_size);
+ cmd->brightness = brightness;
+ strcpy(cmd->light, light);
+ // Send the command.
+ _uiCmdProxy_send_command(AUICMD_CHANGE_DISP_BRIGHTNESS, cmd, cmd_size);
+ qemu_free(cmd);
+}
+
+int
+uiCmdProxy_create(int fd)
+{
+ // Initialize the only UICmdProxy instance.
+ _uiCmdProxy.sock = fd;
+ _uiCmdProxy.looper = looper_newCore();
+ loopIo_init(&_uiCmdProxy.io, _uiCmdProxy.looper, _uiCmdProxy.sock,
+ _uiCmdProxy_io_func, &_uiCmdProxy);
+ loopIo_wantRead(&_uiCmdProxy.io);
+ _uiCmdProxy.sync_writer = syncsocket_init(fd);
+ if (_uiCmdProxy.sync_writer == NULL) {
+ derror("Unable to initialize UICmdProxy writer: %s\n", errno_str);
+ uiCmdProxy_destroy();
+ return -1;
+ }
+ {
+ // Set brighness change callback, so we can notify
+ // the UI about the event.
+ AndroidHwControlFuncs funcs;
+ funcs.light_brightness = _uiCmdProxy_brightness_change_callback;
+ android_hw_control_init(&_uiCmdProxy, &funcs);
+ }
+ return 0;
+}
+
+void
+uiCmdProxy_destroy()
+{
+ // Destroy the sync writer.
+ if (_uiCmdProxy.sync_writer != NULL) {
+ syncsocket_close(_uiCmdProxy.sync_writer);
+ syncsocket_free(_uiCmdProxy.sync_writer);
+ }
+ if (_uiCmdProxy.looper != NULL) {
+ // Stop all I/O that may still be going on.
+ loopIo_done(&_uiCmdProxy.io);
+ looper_free(_uiCmdProxy.looper);
+ _uiCmdProxy.looper = NULL;
+ }
+ _uiCmdProxy.sock = -1;
+}
+
+int
+uicmd_set_window_scale(double scale, int is_dpi)
+{
+ UICmdSetWindowsScale cmd;
+ cmd.scale = scale;
+ cmd.is_dpi = is_dpi;
+ return _uiCmdProxy_send_command(AUICMD_SET_WINDOWS_SCALE, &cmd, sizeof(cmd));
+}
diff --git a/android/protocol/ui-commands-proxy.h b/android/protocol/ui-commands-proxy.h
new file mode 100644
index 0000000..8627537
--- /dev/null
+++ b/android/protocol/ui-commands-proxy.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_UI_COMMANDS_PROXY_H
+#define _ANDROID_PROTOCOL_UI_COMMANDS_PROXY_H
+
+/*
+ * Contains the Core-side implementation of the "core-ui-control" service that is
+ * part of the UI control protocol. Here we send UI control commands to the UI.
+ */
+
+/* Creates and initializes descriptor for the Core-side of the "core-ui-control"
+ * service. Note that there can be only one instance of this service in the core.
+ * Param:
+ * fd - Socket descriptor for the proxy.
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int uiCmdProxy_create(int fd);
+
+/* Destroys the descriptor for the Core-side of the "core-ui-control" service. */
+extern void uiCmdProxy_destroy();
+
+/* Changes the scale of the emulator window at runtime.
+ * Param:
+ * scale, is_dpi - New window scale parameters
+ * Return:
+ * 0 on success, or < 0 on failure.
+ */
+extern int uicmd_set_window_scale(double scale, int is_dpi);
+
+#endif /* _ANDROID_PROTOCOL_UI_COMMANDS_PROXY_H */
diff --git a/android/protocol/ui-commands-qemu.c b/android/protocol/ui-commands-qemu.c
new file mode 100644
index 0000000..3dbed31
--- /dev/null
+++ b/android/protocol/ui-commands-qemu.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains implementation of the API for calling into the UI with the Core
+ * control commands for standalone (monolithic) emulator.
+ */
+
+#include "android/android.h"
+#include "android/hw-control.h"
+#include "android/protocol/ui-commands-api.h"
+
+/* Implemented in android/qemulator.c */
+extern void android_emulator_set_window_scale(double scale, int is_dpi);
+
+int
+uicmd_set_window_scale(double scale, int is_dpi)
+{
+ android_emulator_set_window_scale(scale, is_dpi);
+ return 0;
+}
+
+int
+uicmd_set_brightness_change_callback(AndroidHwLightBrightnessCallback callback,
+ void* opaque)
+{
+ AndroidHwControlFuncs funcs;
+ funcs.light_brightness = callback;
+ android_hw_control_init(opaque, &funcs);
+ return 0;
+}
diff --git a/android/protocol/ui-commands.h b/android/protocol/ui-commands.h
new file mode 100644
index 0000000..4e47b83
--- /dev/null
+++ b/android/protocol/ui-commands.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_UI_COMMANDS_H
+#define _ANDROID_PROTOCOL_UI_COMMANDS_H
+
+/*
+ * Contains declarations related to the UI control commands sent by the Core and
+ * handled by the UI.
+ */
+
+#include "android/protocol/ui-common.h"
+
+/* Sets window scale. */
+#define AUICMD_SET_WINDOWS_SCALE 1
+
+/* Changes display brightness. */
+#define AUICMD_CHANGE_DISP_BRIGHTNESS 2
+
+/* Formats AUICMD_SET_WINDOWS_SCALE UI control command parameters.
+ * Contains parameters required by android_emulator_set_window_scale routine.
+ */
+typedef struct UICmdSetWindowsScale {
+ double scale;
+ int is_dpi;
+} UICmdSetWindowsScale;
+
+/* Formats AUICMD_CHANGE_DISP_BRIGHTNESS UI control command parameters.
+ */
+typedef struct UICmdChangeDispBrightness {
+ int brightness;
+ char light[0];
+} UICmdChangeDispBrightness;
+
+#endif /* _ANDROID_PROTOCOL_UI_COMMANDS_H */
diff --git a/android/protocol/ui-common.h b/android/protocol/ui-common.h
new file mode 100644
index 0000000..003ed6d
--- /dev/null
+++ b/android/protocol/ui-common.h
@@ -0,0 +1,53 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#ifndef _ANDROID_PROTOCOL_UI_COMMON_H
+#define _ANDROID_PROTOCOL_UI_COMMON_H
+
+/*
+ * Contains declarations for UI control protocol used by both the Core,
+ * and the UI.
+ */
+
+/* UI control command header.
+ * Every UI control command sent by the Core, or by the UI begins with this
+ * header, immediately followed by the command parameters (if there are any).
+ * Command type is defined by cmd_type field of this header. If command doesn't
+ * have any command-specific parameters, cmd_param_size field of this header
+ * must be 0.
+ */
+typedef struct UICmdHeader {
+ /* Command type. */
+ uint8_t cmd_type;
+
+ /* Byte size of the buffer containing parameters for the comand defined by
+ * the cmd_type field. The buffer containing parameters must immediately
+ * follow this header. If command doesn't have any parameters, this field
+ * must be 0 */
+ uint32_t cmd_param_size;
+} UICmdHeader;
+
+/* UI control command response header.
+ * If UI control command assumes a response from the remote end, the response
+ * must start with this header, immediately followed by the response data buffer.
+ */
+typedef struct UICmdRespHeader {
+ /* Result of the command handling. */
+ int result;
+
+ /* Byte size of the buffer containing response data immediately following
+ * this header. If there are no response data for the command, this field
+ * must be 0. */
+ uint32_t resp_data_size;
+} UICmdRespHeader;
+
+#endif /* _ANDROID_PROTOCOL_UI_COMMON_H */