• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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