Vladimir Chtchetkine | 250b2e0 | 2011-01-28 10:56:16 -0800 | [diff] [blame] | 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 | |
David 'Digit' Turner | d4e803c | 2013-12-14 23:45:50 +0100 | [diff] [blame] | 18 | #include "android/user-events.h" |
Vladimir Chtchetkine | 250b2e0 | 2011-01-28 10:56:16 -0800 | [diff] [blame] | 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 |
| 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' Turner | f9e333a | 2011-03-17 14:57:51 +0100 | [diff] [blame] | 93 | status = asyncReader_read(&ueimpl->user_events_reader); |
Vladimir Chtchetkine | 250b2e0 | 2011-01-28 10:56:16 -0800 | [diff] [blame] | 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 |
| 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 |
| 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 | } |