1 /* Copyright (C) 2010 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 13 /* 14 * Contains the Core-side implementation of the "attach-ui" service that is 15 * used to establish connection between the UI and the Core. 16 */ 17 18 #include "android/android.h" 19 #include "android/globals.h" 20 #include "android/looper.h" 21 #include "android/async-utils.h" 22 #include "android/sync-utils.h" 23 #include "android/utils/debug.h" 24 #include "android/protocol/core-commands.h" 25 #include "android/protocol/core-commands-impl.h" 26 27 /* Descriptor for the UI attach-ui proxy. */ 28 typedef struct AttachUIProxy { 29 /* Reader to detect UI disconnection. */ 30 AsyncReader async_reader; 31 32 /* I/O associated with this descriptor. */ 33 LoopIo io; 34 35 /* Looper used to communicate with the UI. */ 36 Looper* looper; 37 38 /* Socket descriptor for this service. */ 39 int sock; 40 } AttachUIProxy; 41 42 /* One and only one AttachUIProxy instance. */ 43 static AttachUIProxy _attachUiProxy; 44 45 /* Implemented in android/console.c */ 46 extern void destroy_attach_ui_client(void); 47 48 /* Asynchronous I/O callback for AttachUIProxy instance. 49 * We expect this callback to be called only on UI detachment condition. In this 50 * case the event should be LOOP_IO_READ, and read should fail with errno set 51 * to ECONNRESET. 52 * Param: 53 * opaque - AttachUIProxy instance. 54 */ 55 static void 56 _attachUiProxy_io_func(void* opaque, int fd, unsigned events) 57 { 58 AttachUIProxy* uicmd = (AttachUIProxy*)opaque; 59 AsyncReader reader; 60 AsyncStatus status; 61 uint8_t read_buf[1]; 62 63 if (events & LOOP_IO_WRITE) { 64 derror("Unexpected LOOP_IO_WRITE in _attachUiProxy_io_func.\n"); 65 return; 66 } 67 68 // Try to read 69 asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io); 70 status = asyncReader_read(&reader); 71 // We expect only error status here. 72 if (status != ASYNC_ERROR) { 73 derror("Unexpected read status %d in _attachUiProxy_io_func\n", status); 74 return; 75 } 76 // We expect only socket disconnection error here. 77 if (errno != ECONNRESET) { 78 derror("Unexpected read error %d (%s) in _attachUiProxy_io_func.\n", 79 errno, errno_str); 80 return; 81 } 82 83 // Client got disconnectted. 84 destroy_attach_ui_client(); 85 } 86 87 int 88 attachUiProxy_create(int fd) 89 { 90 // Initialize the only AttachUIProxy instance. 91 _attachUiProxy.sock = fd; 92 _attachUiProxy.looper = looper_newCore(); 93 loopIo_init(&_attachUiProxy.io, _attachUiProxy.looper, _attachUiProxy.sock, 94 _attachUiProxy_io_func, &_attachUiProxy); 95 loopIo_wantRead(&_attachUiProxy.io); 96 97 return 0; 98 } 99 100 void 101 attachUiProxy_destroy(void) 102 { 103 if (_attachUiProxy.looper != NULL) { 104 // Stop all I/O that may still be going on. 105 loopIo_done(&_attachUiProxy.io); 106 looper_free(_attachUiProxy.looper); 107 _attachUiProxy.looper = NULL; 108 } 109 _attachUiProxy.sock = -1; 110 } 111