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
_attachUiProxy_io_func(void * opaque,int fd,unsigned events)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
attachUiProxy_create(int fd)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
attachUiProxy_destroy(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