blob: f45169a82a066689d375617e55a6c2541b27eb3b [file] [log] [blame]
Vladimir Chtchetkine250b2e02011-01-28 10:56:16 -08001/* 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
David 'Digit' Turnerd4e803c2013-12-14 23:45:50 +010018#include "android/user-events.h"
Vladimir Chtchetkine250b2e02011-01-28 10:56:16 -080019#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.
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +010093 status = asyncReader_read(&ueimpl->user_events_reader);
Vladimir Chtchetkine250b2e02011-01-28 10:56:16 -080094
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}