/* Copyright (C) 2010 The Android Open Source Project ** ** This software is licensed under the terms of the GNU General Public ** License version 2, as published by the Free Software Foundation, and ** may be copied, distributed, and modified under those terms. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. */ /* * Contains the Core-side of the "user events" service. Here we receive and * handle user events sent from the UI. */ #include "user-events.h" #include "android/globals.h" #include "android/android.h" #include "android/looper.h" #include "android/async-utils.h" #include "android/sync-utils.h" #include "android/utils/system.h" #include "android/utils/debug.h" #include "android/protocol/user-events-protocol.h" #include "android/protocol/user-events-impl.h" /* Enumerates state values for the event reader in the UserEventsImpl descriptor. */ typedef enum UserEventsImplState { /* The reader is waiting on event header. */ EXPECTS_HEADER, /* The reader is waiting on event parameters. */ EXPECTS_PARAMETERS, } UserEventsImplState; /* Core user events service descriptor. */ typedef struct UserEventsImpl { /* Reader to receive user events. */ AsyncReader user_events_reader; /* I/O associated with this descriptor. */ LoopIo io; /* Looper used to communicate user events. */ Looper* looper; /* Socket for this service. */ int sock; /* State of the service (see UE_STATE_XXX for possible values). */ UserEventsImplState state; /* Current event header. */ UserEventHeader event_header; /* Current event parameters. */ union { UserEventGeneric generic_event; UserEventMouse mouse_event; UserEventKeycode keycode_event; }; } UserEventsImpl; /* Implemented in android/console.c */ extern void destroy_user_events_client(void); /* One and only one UserEventsImpl instance. */ static UserEventsImpl _UserEventsImpl; /* Asynchronous I/O callback reading user events. * Param: * opaque - UserEventsImpl instance. */ static void _userEventsImpl_io_func(void* opaque, int fd, unsigned events) { UserEventsImpl* ueimpl; AsyncStatus status; if (events & LOOP_IO_WRITE) { // We don't use async writer here, so we don't expect // any write callbacks. derror("Unexpected LOOP_IO_WRITE in _userEventsImpl_io_func\n"); return; } ueimpl = (UserEventsImpl*)opaque; // Read whatever is expected from the socket. status = asyncReader_read(&ueimpl->user_events_reader); switch (status) { case ASYNC_COMPLETE: switch (ueimpl->state) { case EXPECTS_HEADER: // We just read event header. Now we expect event parameters. ueimpl->state = EXPECTS_PARAMETERS; // Setup the reader depending on the event type. switch (ueimpl->event_header.event_type) { case AUSER_EVENT_MOUSE: asyncReader_init(&ueimpl->user_events_reader, &ueimpl->mouse_event, sizeof(ueimpl->mouse_event), &ueimpl->io); break; case AUSER_EVENT_KEYCODE: asyncReader_init(&ueimpl->user_events_reader, &ueimpl->keycode_event, sizeof(ueimpl->keycode_event), &ueimpl->io); break; case AUSER_EVENT_GENERIC: asyncReader_init(&ueimpl->user_events_reader, &ueimpl->generic_event, sizeof(ueimpl->generic_event), &ueimpl->io); break; default: derror("Unexpected user event type %d\n", ueimpl->event_header.event_type); break; } break; case EXPECTS_PARAMETERS: // We just read event parameters. Lets fire the event. switch (ueimpl->event_header.event_type) { case AUSER_EVENT_MOUSE: user_event_mouse(ueimpl->mouse_event.dx, ueimpl->mouse_event.dy, ueimpl->mouse_event.dz, ueimpl->mouse_event.buttons_state); break; case AUSER_EVENT_KEYCODE: user_event_keycode(ueimpl->keycode_event.keycode); break; case AUSER_EVENT_GENERIC: user_event_generic(ueimpl->generic_event.type, ueimpl->generic_event.code, ueimpl->generic_event.value); break; default: derror("Unexpected user event type %d\n", ueimpl->event_header.event_type); break; } // Prepare to receive the next event header. ueimpl->event_header.event_type = -1; ueimpl->state = EXPECTS_HEADER; asyncReader_init(&ueimpl->user_events_reader, &ueimpl->event_header, sizeof(ueimpl->event_header), &ueimpl->io); break; } break; case ASYNC_ERROR: loopIo_dontWantRead(&ueimpl->io); if (errno == ECONNRESET) { // UI has exited. We need to destroy user event service. destroy_user_events_client(); } else { derror("User event read error %d -> %s\n", errno, errno_str); } break; case ASYNC_NEED_MORE: // Transfer will eventually come back into this routine. return; } } int userEventsImpl_create(int fd) { _UserEventsImpl.sock = fd; _UserEventsImpl.event_header.event_type = -1; _UserEventsImpl.state = EXPECTS_HEADER; _UserEventsImpl.looper = looper_newCore(); loopIo_init(&_UserEventsImpl.io, _UserEventsImpl.looper, _UserEventsImpl.sock, _userEventsImpl_io_func, &_UserEventsImpl); asyncReader_init(&_UserEventsImpl.user_events_reader, &_UserEventsImpl.event_header, sizeof(_UserEventsImpl.event_header), &_UserEventsImpl.io); return 0; } void userEventsImpl_destroy(void) { if (_UserEventsImpl.looper != NULL) { // Stop all I/O that may still be going on. loopIo_done(&_UserEventsImpl.io); looper_free(_UserEventsImpl.looper); _UserEventsImpl.looper = NULL; } }