aboutsummaryrefslogtreecommitdiffstats
path: root/android/protocol/core-commands-proxy.c
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/core-commands-proxy.c
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/core-commands-proxy.c')
-rw-r--r--android/protocol/core-commands-proxy.c374
1 files changed, 374 insertions, 0 deletions
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;
+}