• 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 of the "user events" service. Here we receive and
15  * handle user events sent from the UI.
16  */
17 
18 #include "user-events.h"
19 #include "android/globals.h"
20 #include "android/android.h"
21 #include "android/looper.h"
22 #include "android/async-utils.h"
23 #include "android/sync-utils.h"
24 #include "android/utils/system.h"
25 #include "android/utils/debug.h"
26 #include "android/protocol/user-events-protocol.h"
27 #include "android/protocol/user-events-impl.h"
28 
29 /* Enumerates state values for the event reader in the UserEventsImpl descriptor.
30  */
31 typedef enum UserEventsImplState {
32     /* The reader is waiting on event header. */
33     EXPECTS_HEADER,
34 
35     /* The reader is waiting on event parameters. */
36     EXPECTS_PARAMETERS,
37 } UserEventsImplState;
38 
39 
40 /* Core user events service descriptor. */
41 typedef struct UserEventsImpl {
42     /* Reader to receive user events. */
43     AsyncReader         user_events_reader;
44 
45     /* I/O associated with this descriptor. */
46     LoopIo              io;
47 
48     /* Looper used to communicate user events. */
49     Looper*             looper;
50 
51     /* Socket for this service. */
52     int                 sock;
53 
54     /* State of the service (see UE_STATE_XXX for possible values). */
55     UserEventsImplState state;
56 
57     /* Current event header. */
58     UserEventHeader     event_header;
59 
60     /* Current event parameters. */
61     union {
62         UserEventGeneric    generic_event;
63         UserEventMouse      mouse_event;
64         UserEventKeycode    keycode_event;
65     };
66 } UserEventsImpl;
67 
68 /* Implemented in android/console.c */
69 extern void destroy_user_events_client(void);
70 
71 /* One and only one UserEventsImpl instance. */
72 static UserEventsImpl   _UserEventsImpl;
73 
74 /* Asynchronous I/O callback reading user events.
75  * Param:
76  *  opaque - UserEventsImpl instance.
77  */
78 static void
_userEventsImpl_io_func(void * opaque,int fd,unsigned events)79 _userEventsImpl_io_func(void* opaque, int fd, unsigned events)
80 {
81     UserEventsImpl* ueimpl;
82     AsyncStatus status;
83 
84     if (events & LOOP_IO_WRITE) {
85         // We don't use async writer here, so we don't expect
86         // any write callbacks.
87         derror("Unexpected LOOP_IO_WRITE in _userEventsImpl_io_func\n");
88         return;
89     }
90 
91     ueimpl = (UserEventsImpl*)opaque;
92     // Read whatever is expected from the socket.
93     status = asyncReader_read(&ueimpl->user_events_reader);
94 
95 
96     switch (status) {
97         case ASYNC_COMPLETE:
98             switch (ueimpl->state) {
99                 case EXPECTS_HEADER:
100                     // We just read event header. Now we expect event parameters.
101                     ueimpl->state = EXPECTS_PARAMETERS;
102                     // Setup the reader depending on the event type.
103                     switch (ueimpl->event_header.event_type) {
104                         case AUSER_EVENT_MOUSE:
105                             asyncReader_init(&ueimpl->user_events_reader,
106                                              &ueimpl->mouse_event,
107                                              sizeof(ueimpl->mouse_event),
108                                              &ueimpl->io);
109                             break;
110 
111                         case AUSER_EVENT_KEYCODE:
112                             asyncReader_init(&ueimpl->user_events_reader,
113                                              &ueimpl->keycode_event,
114                                              sizeof(ueimpl->keycode_event),
115                                              &ueimpl->io);
116                             break;
117 
118                         case AUSER_EVENT_GENERIC:
119                             asyncReader_init(&ueimpl->user_events_reader,
120                                              &ueimpl->generic_event,
121                                              sizeof(ueimpl->generic_event),
122                                              &ueimpl->io);
123                             break;
124 
125                         default:
126                             derror("Unexpected user event type %d\n",
127                                    ueimpl->event_header.event_type);
128                             break;
129                     }
130                     break;
131 
132                 case EXPECTS_PARAMETERS:
133                     // We just read event parameters. Lets fire the event.
134                     switch (ueimpl->event_header.event_type) {
135                         case AUSER_EVENT_MOUSE:
136                             user_event_mouse(ueimpl->mouse_event.dx,
137                                              ueimpl->mouse_event.dy,
138                                              ueimpl->mouse_event.dz,
139                                              ueimpl->mouse_event.buttons_state);
140                             break;
141 
142                         case AUSER_EVENT_KEYCODE:
143                             user_event_keycode(ueimpl->keycode_event.keycode);
144                             break;
145 
146                         case AUSER_EVENT_GENERIC:
147                             user_event_generic(ueimpl->generic_event.type,
148                                                ueimpl->generic_event.code,
149                                                ueimpl->generic_event.value);
150                             break;
151 
152                         default:
153                             derror("Unexpected user event type %d\n",
154                                    ueimpl->event_header.event_type);
155                             break;
156                     }
157                     // Prepare to receive the next event header.
158                     ueimpl->event_header.event_type = -1;
159                     ueimpl->state = EXPECTS_HEADER;
160                     asyncReader_init(&ueimpl->user_events_reader,
161                                      &ueimpl->event_header,
162                                      sizeof(ueimpl->event_header), &ueimpl->io);
163                     break;
164             }
165             break;
166         case ASYNC_ERROR:
167             loopIo_dontWantRead(&ueimpl->io);
168             if (errno == ECONNRESET) {
169                 // UI has exited. We need to destroy user event service.
170                 destroy_user_events_client();
171             } else {
172                 derror("User event read error %d -> %s\n", errno, errno_str);
173             }
174             break;
175 
176         case ASYNC_NEED_MORE:
177             // Transfer will eventually come back into this routine.
178             return;
179     }
180 }
181 
182 int
userEventsImpl_create(int fd)183 userEventsImpl_create(int fd)
184 {
185     _UserEventsImpl.sock = fd;
186     _UserEventsImpl.event_header.event_type = -1;
187     _UserEventsImpl.state = EXPECTS_HEADER;
188     _UserEventsImpl.looper = looper_newCore();
189     loopIo_init(&_UserEventsImpl.io, _UserEventsImpl.looper, _UserEventsImpl.sock,
190                 _userEventsImpl_io_func, &_UserEventsImpl);
191     asyncReader_init(&_UserEventsImpl.user_events_reader,
192                      &_UserEventsImpl.event_header,
193                      sizeof(_UserEventsImpl.event_header), &_UserEventsImpl.io);
194     return 0;
195 }
196 
197 void
userEventsImpl_destroy(void)198 userEventsImpl_destroy(void)
199 {
200     if (_UserEventsImpl.looper != NULL) {
201         // Stop all I/O that may still be going on.
202         loopIo_done(&_UserEventsImpl.io);
203         looper_free(_UserEventsImpl.looper);
204         _UserEventsImpl.looper = NULL;
205     }
206 }
207