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 */
31typedef 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. */
41typedef 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 */
69extern void destroy_user_events_client(void);
70
71/* One and only one UserEventsImpl instance. */
72static UserEventsImpl   _UserEventsImpl;
73
74/* Asynchronous I/O callback reading user events.
75 * Param:
76 *  opaque - UserEventsImpl instance.
77 */
78static void
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
182int
183userEventsImpl_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
197void
198userEventsImpl_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