/* 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 "attach-ui" service that is * used to establish connection between the UI and the Core. */ #include "android/android.h" #include "android/globals.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" /* Descriptor for the UI attach-ui proxy. */ typedef struct AttachUIProxy { /* 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; /* Socket descriptor for this service. */ int sock; } AttachUIProxy; /* One and only one AttachUIProxy instance. */ static AttachUIProxy _attachUiProxy; /* Implemented in android/console.c */ extern void destroy_attach_ui_client(void); /* Asynchronous I/O callback for AttachUIProxy 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 - AttachUIProxy instance. */ static void _attachUiProxy_io_func(void* opaque, int fd, unsigned events) { AttachUIProxy* uicmd = (AttachUIProxy*)opaque; AsyncReader reader; AsyncStatus status; uint8_t read_buf[1]; if (events & LOOP_IO_WRITE) { derror("Unexpected LOOP_IO_WRITE in _attachUiProxy_io_func.\n"); return; } // Try to read asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io); status = asyncReader_read(&reader); // We expect only error status here. if (status != ASYNC_ERROR) { derror("Unexpected read status %d in _attachUiProxy_io_func\n", status); return; } // We expect only socket disconnection error here. if (errno != ECONNRESET) { derror("Unexpected read error %d (%s) in _attachUiProxy_io_func.\n", errno, errno_str); return; } // Client got disconnectted. destroy_attach_ui_client(); } int attachUiProxy_create(int fd) { // Initialize the only AttachUIProxy instance. _attachUiProxy.sock = fd; _attachUiProxy.looper = looper_newCore(); loopIo_init(&_attachUiProxy.io, _attachUiProxy.looper, _attachUiProxy.sock, _attachUiProxy_io_func, &_attachUiProxy); loopIo_wantRead(&_attachUiProxy.io); return 0; } void attachUiProxy_destroy(void) { if (_attachUiProxy.looper != NULL) { // Stop all I/O that may still be going on. loopIo_done(&_attachUiProxy.io); looper_free(_attachUiProxy.looper); _attachUiProxy.looper = NULL; } _attachUiProxy.sock = -1; }