summaryrefslogtreecommitdiffstats
path: root/libs/ui
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2011-01-02 16:37:43 -0800
committerJeff Brown <jeffbrown@google.com>2011-01-04 17:31:24 -0800
commit41250361577ce85d30b29ef530cfb7bea7d0604d (patch)
treeb0e3b03f4c7a311ec7a5747da70b7071815c68fb /libs/ui
parentd95aaf398224fb547d00231836583cfb4c5cebc1 (diff)
downloadframeworks_native-41250361577ce85d30b29ef530cfb7bea7d0604d.zip
frameworks_native-41250361577ce85d30b29ef530cfb7bea7d0604d.tar.gz
frameworks_native-41250361577ce85d30b29ef530cfb7bea7d0604d.tar.bz2
Mouse pointer integration.
Added support for loading the pointer icon from a resource. Moved the system server related bits of the input manager out of libui and into libinput since they do not need to be linked into applications. Change-Id: Iec11e0725b3add2b905c51f8ea2c3b4b0d1a2d67
Diffstat (limited to 'libs/ui')
-rw-r--r--libs/ui/Android.mk4
-rw-r--r--libs/ui/EventHub.cpp1092
-rw-r--r--libs/ui/InputDispatcher.cpp3710
-rw-r--r--libs/ui/InputManager.cpp83
-rw-r--r--libs/ui/InputReader.cpp3608
-rw-r--r--libs/ui/tests/Android.mk2
-rw-r--r--libs/ui/tests/InputDispatcher_test.cpp229
-rw-r--r--libs/ui/tests/InputReader_test.cpp3637
8 files changed, 0 insertions, 12365 deletions
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 4ba8b5b..0d55f08 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -43,16 +43,12 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
$(commonSources) \
EGLUtils.cpp \
- EventHub.cpp \
EventRecurrence.cpp \
FramebufferNativeWindow.cpp \
GraphicBuffer.cpp \
GraphicBufferAllocator.cpp \
GraphicBufferMapper.cpp \
GraphicLog.cpp \
- InputDispatcher.cpp \
- InputManager.cpp \
- InputReader.cpp \
InputTransport.cpp \
PixelFormat.cpp \
Rect.cpp \
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
deleted file mode 100644
index 4e9fad0..0000000
--- a/libs/ui/EventHub.cpp
+++ /dev/null
@@ -1,1092 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-// Handle events, like key input and vsync.
-//
-// The goal is to provide an optimized solution for Linux, not an
-// implementation that works well across all platforms. We expect
-// events to arrive on file descriptors, so that we can use a select()
-// select() call to sleep.
-//
-// We can't select() on anything but network sockets in Windows, so we
-// provide an alternative implementation of waitEvent for that platform.
-//
-#define LOG_TAG "EventHub"
-
-//#define LOG_NDEBUG 0
-
-#include <ui/EventHub.h>
-#include <hardware_legacy/power.h>
-
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <utils/threads.h>
-#include <utils/Errors.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <memory.h>
-#include <errno.h>
-#include <assert.h>
-
-#include <ui/KeyLayoutMap.h>
-#include <ui/KeyCharacterMap.h>
-#include <ui/VirtualKeyMap.h>
-
-#include <string.h>
-#include <stdint.h>
-#include <dirent.h>
-#ifdef HAVE_INOTIFY
-# include <sys/inotify.h>
-#endif
-#ifdef HAVE_ANDROID_OS
-# include <sys/limits.h> /* not part of Linux */
-#endif
-#include <sys/poll.h>
-#include <sys/ioctl.h>
-
-/* this macro is used to tell if "bit" is set in "array"
- * it selects a byte from the array, and does a boolean AND
- * operation with a byte that only has the relevant bit set.
- * eg. to check for the 12th bit, we do (array[1] & 1<<4)
- */
-#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
-
-/* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits) ((bits + 7) / 8)
-
-#ifndef ABS_MT_TOUCH_MAJOR
-#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
-#endif
-
-#ifndef ABS_MT_POSITION_X
-#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
-#endif
-
-#ifndef ABS_MT_POSITION_Y
-#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
-#endif
-
-// Fd at index 0 is always reserved for inotify
-#define FIRST_ACTUAL_DEVICE_INDEX 1
-
-#define INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-
-namespace android {
-
-static const char *WAKE_LOCK_ID = "KeyEvents";
-static const char *DEVICE_PATH = "/dev/input";
-
-/* return the larger integer */
-static inline int max(int v1, int v2)
-{
- return (v1 > v2) ? v1 : v2;
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-// --- EventHub::Device ---
-
-EventHub::Device::Device(int fd, int32_t id, const String8& path,
- const InputDeviceIdentifier& identifier) :
- next(NULL),
- fd(fd), id(id), path(path), identifier(identifier),
- classes(0), keyBitmask(NULL), configuration(NULL), virtualKeyMap(NULL) {
-}
-
-EventHub::Device::~Device() {
- close();
- delete[] keyBitmask;
- delete configuration;
- delete virtualKeyMap;
-}
-
-void EventHub::Device::close() {
- if (fd >= 0) {
- ::close(fd);
- fd = -1;
- }
-}
-
-
-// --- EventHub ---
-
-EventHub::EventHub(void) :
- mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
- mOpeningDevices(0), mClosingDevices(0),
- mOpened(false), mNeedToSendFinishedDeviceScan(false),
- mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-#ifdef EV_SW
- memset(mSwitches, 0, sizeof(mSwitches));
-#endif
-}
-
-EventHub::~EventHub(void) {
- release_wake_lock(WAKE_LOCK_ID);
- // we should free stuff here...
-}
-
-status_t EventHub::errorCheck() const {
- return mError;
-}
-
-String8 EventHub::getDeviceName(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return String8();
- return device->identifier.name;
-}
-
-uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return 0;
- return device->classes;
-}
-
-void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && device->configuration) {
- *outConfiguration = *device->configuration;
- } else {
- outConfiguration->clear();
- }
-}
-
-status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const {
- outAxisInfo->clear();
-
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return -1;
-
- struct input_absinfo info;
-
- if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
- LOGW("Error reading absolute controller %d for device %s fd %d\n",
- axis, device->identifier.name.string(), device->fd);
- return -errno;
- }
-
- if (info.minimum != info.maximum) {
- outAxisInfo->valid = true;
- outAxisInfo->minValue = info.minimum;
- outAxisInfo->maxValue = info.maximum;
- outAxisInfo->flat = info.flat;
- outAxisInfo->fuzz = info.fuzz;
- }
- return OK;
-}
-
-int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
- if (scanCode >= 0 && scanCode <= KEY_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device != NULL) {
- return getScanCodeStateLocked(device, scanCode);
- }
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getScanCodeStateLocked(Device* device, int32_t scanCode) const {
- uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
- memset(key_bitmask, 0, sizeof(key_bitmask));
- if (ioctl(device->fd,
- EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
- return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device != NULL) {
- return getKeyCodeStateLocked(device, keyCode);
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getKeyCodeStateLocked(Device* device, int32_t keyCode) const {
- if (!device->keyMap.haveKeyLayout()) {
- return AKEY_STATE_UNKNOWN;
- }
-
- Vector<int32_t> scanCodes;
- device->keyMap.keyLayoutMap->findScanCodes(keyCode, &scanCodes);
-
- uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
- memset(key_bitmask, 0, sizeof(key_bitmask));
- if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
- #if 0
- for (size_t i=0; i<=KEY_MAX; i++) {
- LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
- }
- #endif
- const size_t N = scanCodes.size();
- for (size_t i=0; i<N && i<=KEY_MAX; i++) {
- int32_t sc = scanCodes.itemAt(i);
- //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
- if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
- return AKEY_STATE_DOWN;
- }
- }
- return AKEY_STATE_UP;
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
-#ifdef EV_SW
- if (sw >= 0 && sw <= SW_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device != NULL) {
- return getSwitchStateLocked(device, sw);
- }
- }
-#endif
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getSwitchStateLocked(Device* device, int32_t sw) const {
- uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
- memset(sw_bitmask, 0, sizeof(sw_bitmask));
- if (ioctl(device->fd,
- EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
- return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) const {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device != NULL) {
- return markSupportedKeyCodesLocked(device, numCodes, keyCodes, outFlags);
- }
- return false;
-}
-
-bool EventHub::markSupportedKeyCodesLocked(Device* device, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) const {
- if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
- return false;
- }
-
- Vector<int32_t> scanCodes;
- for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
- scanCodes.clear();
-
- status_t err = device->keyMap.keyLayoutMap->findScanCodes(keyCodes[codeIndex], &scanCodes);
- if (! err) {
- // check the possible scan codes identified by the layout map against the
- // map of codes actually emitted by the driver
- for (size_t sc = 0; sc < scanCodes.size(); sc++) {
- if (test_bit(scanCodes[sc], device->keyBitmask)) {
- outFlags[codeIndex] = 1;
- break;
- }
- }
- }
- }
- return true;
-}
-
-status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
- int32_t* outKeycode, uint32_t* outFlags) const
-{
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
-
- if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
- if (err == NO_ERROR) {
- return NO_ERROR;
- }
- }
-
- if (mBuiltInKeyboardId != -1) {
- device = getDeviceLocked(mBuiltInKeyboardId);
-
- if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
- if (err == NO_ERROR) {
- return NO_ERROR;
- }
- }
- }
-
- *outKeycode = 0;
- *outFlags = 0;
- return NAME_NOT_FOUND;
-}
-
-void EventHub::addExcludedDevice(const char* deviceName)
-{
- AutoMutex _l(mLock);
-
- String8 name(deviceName);
- mExcludedDevices.push_back(name);
-}
-
-bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- uint8_t bitmask[sizeof_bit_array(LED_MAX + 1)];
- memset(bitmask, 0, sizeof(bitmask));
- if (ioctl(device->fd, EVIOCGBIT(EV_LED, sizeof(bitmask)), bitmask) >= 0) {
- if (test_bit(led, bitmask)) {
- return true;
- }
- }
- }
- return false;
-}
-
-void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- struct input_event ev;
- ev.time.tv_sec = 0;
- ev.time.tv_usec = 0;
- ev.type = EV_LED;
- ev.code = led;
- ev.value = on ? 1 : 0;
-
- ssize_t nWrite;
- do {
- nWrite = write(device->fd, &ev, sizeof(struct input_event));
- } while (nWrite == -1 && errno == EINTR);
- }
-}
-
-void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
- Vector<VirtualKeyDefinition>& outVirtualKeys) const {
- outVirtualKeys.clear();
-
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && device->virtualKeyMap) {
- outVirtualKeys.appendVector(device->virtualKeyMap->getVirtualKeys());
- }
-}
-
-EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
- if (deviceId == 0) {
- deviceId = mBuiltInKeyboardId;
- }
-
- size_t numDevices = mDevices.size();
- for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < numDevices; i++) {
- Device* device = mDevices[i];
- if (device->id == deviceId) {
- return device;
- }
- }
- return NULL;
-}
-
-bool EventHub::getEvent(RawEvent* outEvent) {
- outEvent->deviceId = 0;
- outEvent->type = 0;
- outEvent->scanCode = 0;
- outEvent->keyCode = 0;
- outEvent->flags = 0;
- outEvent->value = 0;
- outEvent->when = 0;
-
- // Note that we only allow one caller to getEvent(), so don't need
- // to do locking here... only when adding/removing devices.
-
- if (!mOpened) {
- mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
- mOpened = true;
- mNeedToSendFinishedDeviceScan = true;
- }
-
- for (;;) {
- // Report any devices that had last been added/removed.
- if (mClosingDevices != NULL) {
- Device* device = mClosingDevices;
- LOGV("Reporting device closed: id=%d, name=%s\n",
- device->id, device->path.string());
- mClosingDevices = device->next;
- if (device->id == mBuiltInKeyboardId) {
- outEvent->deviceId = 0;
- } else {
- outEvent->deviceId = device->id;
- }
- outEvent->type = DEVICE_REMOVED;
- outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
- delete device;
- mNeedToSendFinishedDeviceScan = true;
- return true;
- }
-
- if (mOpeningDevices != NULL) {
- Device* device = mOpeningDevices;
- LOGV("Reporting device opened: id=%d, name=%s\n",
- device->id, device->path.string());
- mOpeningDevices = device->next;
- if (device->id == mBuiltInKeyboardId) {
- outEvent->deviceId = 0;
- } else {
- outEvent->deviceId = device->id;
- }
- outEvent->type = DEVICE_ADDED;
- outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
- mNeedToSendFinishedDeviceScan = true;
- return true;
- }
-
- if (mNeedToSendFinishedDeviceScan) {
- mNeedToSendFinishedDeviceScan = false;
- outEvent->type = FINISHED_DEVICE_SCAN;
- outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
- return true;
- }
-
- // Grab the next input event.
- for (;;) {
- // Consume buffered input events, if any.
- if (mInputBufferIndex < mInputBufferCount) {
- const struct input_event& iev = mInputBufferData[mInputBufferIndex++];
- const Device* device = mDevices[mInputFdIndex];
-
- LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(),
- (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value);
- if (device->id == mBuiltInKeyboardId) {
- outEvent->deviceId = 0;
- } else {
- outEvent->deviceId = device->id;
- }
- outEvent->type = iev.type;
- outEvent->scanCode = iev.code;
- outEvent->flags = 0;
- if (iev.type == EV_KEY) {
- outEvent->keyCode = AKEYCODE_UNKNOWN;
- if (device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->map(iev.code,
- &outEvent->keyCode, &outEvent->flags);
- LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
- iev.code, outEvent->keyCode, outEvent->flags, err);
- }
- } else {
- outEvent->keyCode = iev.code;
- }
- outEvent->value = iev.value;
-
- // Use an event timestamp in the same timebase as
- // java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis()
- // as expected by the rest of the system.
- outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
- return true;
- }
-
- // Finish reading all events from devices identified in previous poll().
- // This code assumes that mInputDeviceIndex is initially 0 and that the
- // revents member of pollfd is initialized to 0 when the device is first added.
- // Since mFds[0] is used for inotify, we process regular events starting at index 1.
- mInputFdIndex += 1;
- if (mInputFdIndex >= mFds.size()) {
- break;
- }
-
- const struct pollfd& pfd = mFds[mInputFdIndex];
- if (pfd.revents & POLLIN) {
- int32_t readSize = read(pfd.fd, mInputBufferData,
- sizeof(struct input_event) * INPUT_BUFFER_SIZE);
- if (readSize < 0) {
- if (errno != EAGAIN && errno != EINTR) {
- LOGW("could not get event (errno=%d)", errno);
- }
- } else if ((readSize % sizeof(struct input_event)) != 0) {
- LOGE("could not get event (wrong size: %d)", readSize);
- } else {
- mInputBufferCount = size_t(readSize) / sizeof(struct input_event);
- mInputBufferIndex = 0;
- }
- }
- }
-
-#if HAVE_INOTIFY
- // readNotify() will modify mFDs and mFDCount, so this must be done after
- // processing all other events.
- if(mFds[0].revents & POLLIN) {
- readNotify(mFds[0].fd);
- mFds.editItemAt(0).revents = 0;
- continue; // report added or removed devices immediately
- }
-#endif
-
- mInputFdIndex = 0;
-
- // Poll for events. Mind the wake lock dance!
- // We hold a wake lock at all times except during poll(). This works due to some
- // subtle choreography. When a device driver has pending (unread) events, it acquires
- // a kernel wake lock. However, once the last pending event has been read, the device
- // driver will release the kernel wake lock. To prevent the system from going to sleep
- // when this happens, the EventHub holds onto its own user wake lock while the client
- // is processing events. Thus the system can only sleep if there are no events
- // pending or currently being processed.
- release_wake_lock(WAKE_LOCK_ID);
-
- int pollResult = poll(mFds.editArray(), mFds.size(), -1);
-
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-
- if (pollResult <= 0) {
- if (errno != EINTR) {
- LOGW("poll failed (errno=%d)\n", errno);
- usleep(100000);
- }
- }
- }
-}
-
-/*
- * Open the platform-specific input device.
- */
-bool EventHub::openPlatformInput(void) {
- /*
- * Open platform-specific input device(s).
- */
- int res, fd;
-
-#ifdef HAVE_INOTIFY
- fd = inotify_init();
- res = inotify_add_watch(fd, DEVICE_PATH, IN_DELETE | IN_CREATE);
- if(res < 0) {
- LOGE("could not add watch for %s, %s\n", DEVICE_PATH, strerror(errno));
- }
-#else
- /*
- * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
- * We allocate space for it and set it to something invalid.
- */
- fd = -1;
-#endif
-
- // Reserve fd index 0 for inotify.
- struct pollfd pollfd;
- pollfd.fd = fd;
- pollfd.events = POLLIN;
- pollfd.revents = 0;
- mFds.push(pollfd);
- mDevices.push(NULL);
-
- res = scanDir(DEVICE_PATH);
- if(res < 0) {
- LOGE("scan dir failed for %s\n", DEVICE_PATH);
- }
-
- return true;
-}
-
-// ----------------------------------------------------------------------------
-
-static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
- const uint8_t* end = array + endIndex;
- array += startIndex;
- while (array != end) {
- if (*(array++) != 0) {
- return true;
- }
- }
- return false;
-}
-
-static const int32_t GAMEPAD_KEYCODES[] = {
- AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
- AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
- AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
- AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
- AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
- AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE
-};
-
-int EventHub::openDevice(const char *devicePath) {
- char buffer[80];
-
- LOGV("Opening device: %s", devicePath);
-
- AutoMutex _l(mLock);
-
- int fd = open(devicePath, O_RDWR);
- if(fd < 0) {
- LOGE("could not open %s, %s\n", devicePath, strerror(errno));
- return -1;
- }
-
- InputDeviceIdentifier identifier;
-
- // Get device name.
- if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
- //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.name.setTo(buffer);
- }
-
- // Check to see if the device is on our excluded list
- List<String8>::iterator iter = mExcludedDevices.begin();
- List<String8>::iterator end = mExcludedDevices.end();
- for ( ; iter != end; iter++) {
- const char* test = *iter;
- if (identifier.name == test) {
- LOGI("ignoring event id %s driver %s\n", devicePath, test);
- close(fd);
- return -1;
- }
- }
-
- // Get device driver version.
- int driverVersion;
- if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
- LOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
- close(fd);
- return -1;
- }
-
- // Get device identifier.
- struct input_id inputId;
- if(ioctl(fd, EVIOCGID, &inputId)) {
- LOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
- close(fd);
- return -1;
- }
- identifier.bus = inputId.bustype;
- identifier.product = inputId.product;
- identifier.vendor = inputId.vendor;
- identifier.version = inputId.version;
-
- // Get device physical location.
- if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
- //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.location.setTo(buffer);
- }
-
- // Get device unique id.
- if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
- //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.uniqueId.setTo(buffer);
- }
-
- // Make file descriptor non-blocking for use with poll().
- if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
- LOGE("Error %d making device file descriptor non-blocking.", errno);
- close(fd);
- return -1;
- }
-
- // Allocate device. (The device object takes ownership of the fd at this point.)
- int32_t deviceId = mNextDeviceId++;
- Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
-
-#if 0
- LOGI("add device %d: %s\n", deviceId, devicePath);
- LOGI(" bus: %04x\n"
- " vendor %04x\n"
- " product %04x\n"
- " version %04x\n",
- identifier.bus, identifier.vendor, identifier.product, identifier.version);
- LOGI(" name: \"%s\"\n", identifier.name.string());
- LOGI(" location: \"%s\"\n", identifier.location.string());
- LOGI(" unique id: \"%s\"\n", identifier.uniqueId.string());
- LOGI(" driver: v%d.%d.%d\n",
- driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
-#endif
-
- // Load the configuration file for the device.
- loadConfiguration(device);
-
- // Figure out the kinds of events the device reports.
-
- uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
- memset(key_bitmask, 0, sizeof(key_bitmask));
-
- LOGV("Getting keys...");
- if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
- //LOGI("MAP\n");
- //for (int i = 0; i < sizeof(key_bitmask); i++) {
- // LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
- //}
-
- // See if this is a keyboard. Ignore everything in the button range except for
- // gamepads which are also considered keyboards.
- if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
- || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
- sizeof_bit_array(BTN_DIGI))
- || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
- sizeof_bit_array(KEY_MAX + 1))) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
-
- device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
- if (device->keyBitmask != NULL) {
- memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
- } else {
- delete device;
- LOGE("out of memory allocating key bitmask");
- return -1;
- }
- }
- }
-
- // See if this is a cursor device such as a trackball or mouse.
- if (test_bit(BTN_MOUSE, key_bitmask)) {
- uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
- memset(rel_bitmask, 0, sizeof(rel_bitmask));
- LOGV("Getting relative controllers...");
- if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
- if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_CURSOR;
- }
- }
- }
-
- // See if this is a touch pad.
- uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
- memset(abs_bitmask, 0, sizeof(abs_bitmask));
- LOGV("Getting absolute controllers...");
- if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
- // Is this a new modern multi-touch driver?
- if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
- && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
-
- // Is this an old style single-touch driver?
- } else if (test_bit(BTN_TOUCH, key_bitmask)
- && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
- }
- }
-
-#ifdef EV_SW
- // figure out the switches this device reports
- uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
- memset(sw_bitmask, 0, sizeof(sw_bitmask));
- bool hasSwitches = false;
- if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
- for (int i=0; i<EV_SW; i++) {
- //LOGI("Device %d sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
- if (test_bit(i, sw_bitmask)) {
- hasSwitches = true;
- if (mSwitches[i] == 0) {
- mSwitches[i] = device->id;
- }
- }
- }
- }
- if (hasSwitches) {
- device->classes |= INPUT_DEVICE_CLASS_SWITCH;
- }
-#endif
-
- if ((device->classes & INPUT_DEVICE_CLASS_TOUCHSCREEN)) {
- // Load the virtual keys for the touch screen, if any.
- // We do this now so that we can make sure to load the keymap if necessary.
- status_t status = loadVirtualKeyMap(device);
- if (!status) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
- }
- }
-
- if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
- // Load the keymap for the device.
- status_t status = loadKeyMap(device);
-
- // Set system properties for the keyboard.
- setKeyboardProperties(device, false);
-
- // Register the keyboard as a built-in keyboard if it is eligible.
- if (!status
- && mBuiltInKeyboardId == -1
- && isEligibleBuiltInKeyboard(device->identifier,
- device->configuration, &device->keyMap)) {
- mBuiltInKeyboardId = device->id;
- setKeyboardProperties(device, true);
- }
-
- // 'Q' key support = cheap test of whether this is an alpha-capable kbd
- if (hasKeycodeLocked(device, AKEYCODE_Q)) {
- device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
- }
-
- // See if this device has a DPAD.
- if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
- device->classes |= INPUT_DEVICE_CLASS_DPAD;
- }
-
- // See if this device has a gamepad.
- for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
- if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
- device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
- break;
- }
- }
- }
-
- // If the device isn't recognized as something we handle, don't monitor it.
- if (device->classes == 0) {
- LOGV("Dropping device: id=%d, path='%s', name='%s'",
- deviceId, devicePath, device->identifier.name.string());
- delete device;
- return -1;
- }
-
- LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
- "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
- deviceId, fd, devicePath, device->identifier.name.string(),
- device->classes,
- device->configurationFile.string(),
- device->keyMap.keyLayoutFile.string(),
- device->keyMap.keyCharacterMapFile.string(),
- toString(mBuiltInKeyboardId == deviceId));
-
- struct pollfd pollfd;
- pollfd.fd = fd;
- pollfd.events = POLLIN;
- pollfd.revents = 0;
- mFds.push(pollfd);
- mDevices.push(device);
-
- device->next = mOpeningDevices;
- mOpeningDevices = device;
- return 0;
-}
-
-void EventHub::loadConfiguration(Device* device) {
- device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
- device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
- if (device->configurationFile.isEmpty()) {
- LOGD("No input device configuration file found for device '%s'.",
- device->identifier.name.string());
- } else {
- status_t status = PropertyMap::load(device->configurationFile,
- &device->configuration);
- if (status) {
- LOGE("Error loading input device configuration file for device '%s'. "
- "Using default configuration.",
- device->identifier.name.string());
- }
- }
-}
-
-status_t EventHub::loadVirtualKeyMap(Device* device) {
- // The virtual key map is supplied by the kernel as a system board property file.
- String8 path;
- path.append("/sys/board_properties/virtualkeys.");
- path.append(device->identifier.name);
- if (access(path.string(), R_OK)) {
- return NAME_NOT_FOUND;
- }
- return VirtualKeyMap::load(path, &device->virtualKeyMap);
-}
-
-status_t EventHub::loadKeyMap(Device* device) {
- return device->keyMap.load(device->identifier, device->configuration);
-}
-
-void EventHub::setKeyboardProperties(Device* device, bool builtInKeyboard) {
- int32_t id = builtInKeyboard ? 0 : device->id;
- android::setKeyboardProperties(id, device->identifier,
- device->keyMap.keyLayoutFile, device->keyMap.keyCharacterMapFile);
-}
-
-void EventHub::clearKeyboardProperties(Device* device, bool builtInKeyboard) {
- int32_t id = builtInKeyboard ? 0 : device->id;
- android::clearKeyboardProperties(id);
-}
-
-bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
- if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
- return false;
- }
-
- Vector<int32_t> scanCodes;
- device->keyMap.keyLayoutMap->findScanCodes(keycode, &scanCodes);
- const size_t N = scanCodes.size();
- for (size_t i=0; i<N && i<=KEY_MAX; i++) {
- int32_t sc = scanCodes.itemAt(i);
- if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
- return true;
- }
- }
-
- return false;
-}
-
-int EventHub::closeDevice(const char *devicePath) {
- AutoMutex _l(mLock);
-
- for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
- Device* device = mDevices[i];
- if (device->path == devicePath) {
- LOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
- device->path.string(), device->identifier.name.string(), device->id,
- device->fd, device->classes);
-
-#ifdef EV_SW
- for (int j=0; j<EV_SW; j++) {
- if (mSwitches[j] == device->id) {
- mSwitches[j] = 0;
- }
- }
-#endif
-
- if (device->id == mBuiltInKeyboardId) {
- LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
- device->path.string(), mBuiltInKeyboardId);
- mBuiltInKeyboardId = -1;
- clearKeyboardProperties(device, true);
- }
- clearKeyboardProperties(device, false);
-
- mFds.removeAt(i);
- mDevices.removeAt(i);
- device->close();
-
- device->next = mClosingDevices;
- mClosingDevices = device;
- return 0;
- }
- }
- LOGE("remove device: %s not found\n", devicePath);
- return -1;
-}
-
-int EventHub::readNotify(int nfd) {
-#ifdef HAVE_INOTIFY
- int res;
- char devname[PATH_MAX];
- char *filename;
- char event_buf[512];
- int event_size;
- int event_pos = 0;
- struct inotify_event *event;
-
- LOGV("EventHub::readNotify nfd: %d\n", nfd);
- res = read(nfd, event_buf, sizeof(event_buf));
- if(res < (int)sizeof(*event)) {
- if(errno == EINTR)
- return 0;
- LOGW("could not get event, %s\n", strerror(errno));
- return 1;
- }
- //printf("got %d bytes of event information\n", res);
-
- strcpy(devname, DEVICE_PATH);
- filename = devname + strlen(devname);
- *filename++ = '/';
-
- while(res >= (int)sizeof(*event)) {
- event = (struct inotify_event *)(event_buf + event_pos);
- //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
- if(event->len) {
- strcpy(filename, event->name);
- if(event->mask & IN_CREATE) {
- openDevice(devname);
- }
- else {
- closeDevice(devname);
- }
- }
- event_size = sizeof(*event) + event->len;
- res -= event_size;
- event_pos += event_size;
- }
-#endif
- return 0;
-}
-
-int EventHub::scanDir(const char *dirname)
-{
- char devname[PATH_MAX];
- char *filename;
- DIR *dir;
- struct dirent *de;
- dir = opendir(dirname);
- if(dir == NULL)
- return -1;
- strcpy(devname, dirname);
- filename = devname + strlen(devname);
- *filename++ = '/';
- while((de = readdir(dir))) {
- if(de->d_name[0] == '.' &&
- (de->d_name[1] == '\0' ||
- (de->d_name[1] == '.' && de->d_name[2] == '\0')))
- continue;
- strcpy(filename, de->d_name);
- openDevice(devname);
- }
- closedir(dir);
- return 0;
-}
-
-void EventHub::dump(String8& dump) {
- dump.append("Event Hub State:\n");
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- dump.appendFormat(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
-
- dump.append(INDENT "Devices:\n");
-
- for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
- const Device* device = mDevices[i];
- if (device) {
- if (mBuiltInKeyboardId == device->id) {
- dump.appendFormat(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
- device->id, device->identifier.name.string());
- } else {
- dump.appendFormat(INDENT2 "%d: %s\n", device->id,
- device->identifier.name.string());
- }
- dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
- dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
- dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
- dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
- dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
- "product=0x%04x, version=0x%04x\n",
- device->identifier.bus, device->identifier.vendor,
- device->identifier.product, device->identifier.version);
- dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n",
- device->keyMap.keyLayoutFile.string());
- dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n",
- device->keyMap.keyCharacterMapFile.string());
- dump.appendFormat(INDENT3 "ConfigurationFile: %s\n",
- device->configurationFile.string());
- }
- }
- } // release lock
-}
-
-}; // namespace android
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
deleted file mode 100644
index 0548e61..0000000
--- a/libs/ui/InputDispatcher.cpp
+++ /dev/null
@@ -1,3710 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input dispatcher.
-//
-#define LOG_TAG "InputDispatcher"
-
-//#define LOG_NDEBUG 0
-
-// Log detailed debug messages about each inbound event notification to the dispatcher.
-#define DEBUG_INBOUND_EVENT_DETAILS 0
-
-// Log detailed debug messages about each outbound event processed by the dispatcher.
-#define DEBUG_OUTBOUND_EVENT_DETAILS 0
-
-// Log debug messages about batching.
-#define DEBUG_BATCHING 0
-
-// Log debug messages about the dispatch cycle.
-#define DEBUG_DISPATCH_CYCLE 0
-
-// Log debug messages about registrations.
-#define DEBUG_REGISTRATION 0
-
-// Log debug messages about performance statistics.
-#define DEBUG_PERFORMANCE_STATISTICS 0
-
-// Log debug messages about input event injection.
-#define DEBUG_INJECTION 0
-
-// Log debug messages about input event throttling.
-#define DEBUG_THROTTLING 0
-
-// Log debug messages about input focus tracking.
-#define DEBUG_FOCUS 0
-
-// Log debug messages about the app switch latency optimization.
-#define DEBUG_APP_SWITCH 0
-
-#include <cutils/log.h>
-#include <ui/InputDispatcher.h>
-#include <ui/PowerManager.h>
-
-#include <stddef.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-
-#define INDENT " "
-#define INDENT2 " "
-
-namespace android {
-
-// Default input dispatching timeout if there is no focused application or paused window
-// from which to determine an appropriate dispatching timeout.
-const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
-
-// Amount of time to allow for all pending events to be processed when an app switch
-// key is on the way. This is used to preempt input dispatch and drop input events
-// when an application takes too long to respond and the user has pressed an app switch key.
-const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-
-static inline nsecs_t now() {
- return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
- return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
- >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-}
-
-static bool isValidKeyAction(int32_t action) {
- switch (action) {
- case AKEY_EVENT_ACTION_DOWN:
- case AKEY_EVENT_ACTION_UP:
- return true;
- default:
- return false;
- }
-}
-
-static bool validateKeyEvent(int32_t action) {
- if (! isValidKeyAction(action)) {
- LOGE("Key event has invalid action code 0x%x", action);
- return false;
- }
- return true;
-}
-
-static bool isValidMotionAction(int32_t action, size_t pointerCount) {
- switch (action & AMOTION_EVENT_ACTION_MASK) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
- case AMOTION_EVENT_ACTION_MOVE:
- case AMOTION_EVENT_ACTION_OUTSIDE:
- return true;
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- case AMOTION_EVENT_ACTION_POINTER_UP: {
- int32_t index = getMotionEventActionPointerIndex(action);
- return index >= 0 && size_t(index) < pointerCount;
- }
- default:
- return false;
- }
-}
-
-static bool validateMotionEvent(int32_t action, size_t pointerCount,
- const int32_t* pointerIds) {
- if (! isValidMotionAction(action, pointerCount)) {
- LOGE("Motion event has invalid action code 0x%x", action);
- return false;
- }
- if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
- LOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
- pointerCount, MAX_POINTERS);
- return false;
- }
- BitSet32 pointerIdBits;
- for (size_t i = 0; i < pointerCount; i++) {
- int32_t id = pointerIds[i];
- if (id < 0 || id > MAX_POINTER_ID) {
- LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
- id, MAX_POINTER_ID);
- return false;
- }
- if (pointerIdBits.hasBit(id)) {
- LOGE("Motion event has duplicate pointer id %d", id);
- return false;
- }
- pointerIdBits.markBit(id);
- }
- return true;
-}
-
-
-// --- InputWindow ---
-
-bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
- return x >= touchableAreaLeft && x <= touchableAreaRight
- && y >= touchableAreaTop && y <= touchableAreaBottom;
-}
-
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
- return x >= frameLeft && x <= frameRight
- && y >= frameTop && y <= frameBottom;
-}
-
-bool InputWindow::isTrustedOverlay() const {
- return layoutParamsType == TYPE_INPUT_METHOD
- || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
- || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
-}
-
-bool InputWindow::supportsSplitTouch() const {
- return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
-}
-
-
-// --- InputDispatcher ---
-
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
- mPolicy(policy),
- mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
- mDispatchEnabled(true), mDispatchFrozen(false),
- mFocusedWindow(NULL),
- mFocusedApplication(NULL),
- mCurrentInputTargetsValid(false),
- mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
- mLooper = new Looper(false);
-
- mInboundQueue.headSentinel.refCount = -1;
- mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
- mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
-
- mInboundQueue.tailSentinel.refCount = -1;
- mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
- mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
-
- mKeyRepeatState.lastKeyEntry = NULL;
-
- int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
- mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
- mThrottleState.lastDeviceId = -1;
-
-#if DEBUG_THROTTLING
- mThrottleState.originalSampleCount = 0;
- LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
-#endif
-}
-
-InputDispatcher::~InputDispatcher() {
- { // acquire lock
- AutoMutex _l(mLock);
-
- resetKeyRepeatLocked();
- releasePendingEventLocked();
- drainInboundQueueLocked();
- }
-
- while (mConnectionsByReceiveFd.size() != 0) {
- unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
- }
-}
-
-void InputDispatcher::dispatchOnce() {
- nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
- nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
-
- nsecs_t nextWakeupTime = LONG_LONG_MAX;
- { // acquire lock
- AutoMutex _l(mLock);
- dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
-
- if (runCommandsLockedInterruptible()) {
- nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
- }
- } // release lock
-
- // Wait for callback or timeout or wake. (make sure we round up, not down)
- nsecs_t currentTime = now();
- int32_t timeoutMillis;
- if (nextWakeupTime > currentTime) {
- uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
- timeout = (timeout + 999999LL) / 1000000LL;
- timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
- } else {
- timeoutMillis = 0;
- }
-
- mLooper->pollOnce(timeoutMillis);
-}
-
-void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
- nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
- nsecs_t currentTime = now();
-
- // Reset the key repeat timer whenever we disallow key events, even if the next event
- // is not a key. This is to ensure that we abort a key repeat if the device is just coming
- // out of sleep.
- if (keyRepeatTimeout < 0) {
- resetKeyRepeatLocked();
- }
-
- // If dispatching is frozen, do not process timeouts or try to deliver any new events.
- if (mDispatchFrozen) {
-#if DEBUG_FOCUS
- LOGD("Dispatch frozen. Waiting some more.");
-#endif
- return;
- }
-
- // Optimize latency of app switches.
- // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
- // been pressed. When it expires, we preempt dispatch and drop all other pending events.
- bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
- if (mAppSwitchDueTime < *nextWakeupTime) {
- *nextWakeupTime = mAppSwitchDueTime;
- }
-
- // Ready to start a new event.
- // If we don't already have a pending event, go grab one.
- if (! mPendingEvent) {
- if (mInboundQueue.isEmpty()) {
- if (isAppSwitchDue) {
- // The inbound queue is empty so the app switch key we were waiting
- // for will never arrive. Stop waiting for it.
- resetPendingAppSwitchLocked(false);
- isAppSwitchDue = false;
- }
-
- // Synthesize a key repeat if appropriate.
- if (mKeyRepeatState.lastKeyEntry) {
- if (currentTime >= mKeyRepeatState.nextRepeatTime) {
- mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
- } else {
- if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
- *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
- }
- }
- }
- if (! mPendingEvent) {
- return;
- }
- } else {
- // Inbound queue has at least one entry.
- EventEntry* entry = mInboundQueue.headSentinel.next;
-
- // Throttle the entry if it is a move event and there are no
- // other events behind it in the queue. Due to movement batching, additional
- // samples may be appended to this event by the time the throttling timeout
- // expires.
- // TODO Make this smarter and consider throttling per device independently.
- if (entry->type == EventEntry::TYPE_MOTION
- && !isAppSwitchDue
- && mDispatchEnabled
- && (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
- && !entry->isInjected()) {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
- int32_t deviceId = motionEntry->deviceId;
- uint32_t source = motionEntry->source;
- if (! isAppSwitchDue
- && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
- && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
- && deviceId == mThrottleState.lastDeviceId
- && source == mThrottleState.lastSource) {
- nsecs_t nextTime = mThrottleState.lastEventTime
- + mThrottleState.minTimeBetweenEvents;
- if (currentTime < nextTime) {
- // Throttle it!
-#if DEBUG_THROTTLING
- LOGD("Throttling - Delaying motion event for "
- "device %d, source 0x%08x by up to %0.3fms.",
- deviceId, source, (nextTime - currentTime) * 0.000001);
-#endif
- if (nextTime < *nextWakeupTime) {
- *nextWakeupTime = nextTime;
- }
- if (mThrottleState.originalSampleCount == 0) {
- mThrottleState.originalSampleCount =
- motionEntry->countSamples();
- }
- return;
- }
- }
-
-#if DEBUG_THROTTLING
- if (mThrottleState.originalSampleCount != 0) {
- uint32_t count = motionEntry->countSamples();
- LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
- count - mThrottleState.originalSampleCount,
- mThrottleState.originalSampleCount, count);
- mThrottleState.originalSampleCount = 0;
- }
-#endif
-
- mThrottleState.lastEventTime = entry->eventTime < currentTime
- ? entry->eventTime : currentTime;
- mThrottleState.lastDeviceId = deviceId;
- mThrottleState.lastSource = source;
- }
-
- mInboundQueue.dequeue(entry);
- mPendingEvent = entry;
- }
-
- // Poke user activity for this event.
- if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
- pokeUserActivityLocked(mPendingEvent);
- }
- }
-
- // Now we have an event to dispatch.
- assert(mPendingEvent != NULL);
- bool done = false;
- DropReason dropReason = DROP_REASON_NOT_DROPPED;
- if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
- dropReason = DROP_REASON_POLICY;
- } else if (!mDispatchEnabled) {
- dropReason = DROP_REASON_DISABLED;
- }
- switch (mPendingEvent->type) {
- case EventEntry::TYPE_CONFIGURATION_CHANGED: {
- ConfigurationChangedEntry* typedEntry =
- static_cast<ConfigurationChangedEntry*>(mPendingEvent);
- done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
- dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
- break;
- }
-
- case EventEntry::TYPE_KEY: {
- KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
- if (isAppSwitchDue) {
- if (isAppSwitchKeyEventLocked(typedEntry)) {
- resetPendingAppSwitchLocked(true);
- isAppSwitchDue = false;
- } else if (dropReason == DROP_REASON_NOT_DROPPED) {
- dropReason = DROP_REASON_APP_SWITCH;
- }
- }
- done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
- &dropReason, nextWakeupTime);
- break;
- }
-
- case EventEntry::TYPE_MOTION: {
- MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
- if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
- dropReason = DROP_REASON_APP_SWITCH;
- }
- done = dispatchMotionLocked(currentTime, typedEntry,
- &dropReason, nextWakeupTime);
- break;
- }
-
- default:
- assert(false);
- break;
- }
-
- if (done) {
- if (dropReason != DROP_REASON_NOT_DROPPED) {
- dropInboundEventLocked(mPendingEvent, dropReason);
- }
-
- releasePendingEventLocked();
- *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
- }
-}
-
-bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
- bool needWake = mInboundQueue.isEmpty();
- mInboundQueue.enqueueAtTail(entry);
-
- switch (entry->type) {
- case EventEntry::TYPE_KEY: {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
- if (isAppSwitchKeyEventLocked(keyEntry)) {
- if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
- mAppSwitchSawKeyDown = true;
- } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
- if (mAppSwitchSawKeyDown) {
-#if DEBUG_APP_SWITCH
- LOGD("App switch is pending!");
-#endif
- mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
- mAppSwitchSawKeyDown = false;
- needWake = true;
- }
- }
- }
- break;
- }
- }
-
- return needWake;
-}
-
-void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
- const char* reason;
- switch (dropReason) {
- case DROP_REASON_POLICY:
-#if DEBUG_INBOUND_EVENT_DETAILS
- LOGD("Dropped event because policy consumed it.");
-#endif
- reason = "inbound event was dropped because the policy consumed it";
- break;
- case DROP_REASON_DISABLED:
- LOGI("Dropped event because input dispatch is disabled.");
- reason = "inbound event was dropped because input dispatch is disabled";
- break;
- case DROP_REASON_APP_SWITCH:
- LOGI("Dropped event because of pending overdue app switch.");
- reason = "inbound event was dropped because of pending overdue app switch";
- break;
- default:
- assert(false);
- return;
- }
-
- switch (entry->type) {
- case EventEntry::TYPE_KEY:
- synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CANCEL_NON_POINTER_EVENTS, reason);
- break;
- case EventEntry::TYPE_MOTION: {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
- if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
- synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CANCEL_POINTER_EVENTS, reason);
- } else {
- synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CANCEL_NON_POINTER_EVENTS, reason);
- }
- break;
- }
- }
-}
-
-bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
- return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
-}
-
-bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
- return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
- && isAppSwitchKeyCode(keyEntry->keyCode)
- && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
- && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
-}
-
-bool InputDispatcher::isAppSwitchPendingLocked() {
- return mAppSwitchDueTime != LONG_LONG_MAX;
-}
-
-void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
- mAppSwitchDueTime = LONG_LONG_MAX;
-
-#if DEBUG_APP_SWITCH
- if (handled) {
- LOGD("App switch has arrived.");
- } else {
- LOGD("App switch was abandoned.");
- }
-#endif
-}
-
-bool InputDispatcher::runCommandsLockedInterruptible() {
- if (mCommandQueue.isEmpty()) {
- return false;
- }
-
- do {
- CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
-
- Command command = commandEntry->command;
- (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
-
- commandEntry->connection.clear();
- mAllocator.releaseCommandEntry(commandEntry);
- } while (! mCommandQueue.isEmpty());
- return true;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
- CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
- mCommandQueue.enqueueAtTail(commandEntry);
- return commandEntry;
-}
-
-void InputDispatcher::drainInboundQueueLocked() {
- while (! mInboundQueue.isEmpty()) {
- EventEntry* entry = mInboundQueue.dequeueAtHead();
- releaseInboundEventLocked(entry);
- }
-}
-
-void InputDispatcher::releasePendingEventLocked() {
- if (mPendingEvent) {
- releaseInboundEventLocked(mPendingEvent);
- mPendingEvent = NULL;
- }
-}
-
-void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("Injected inbound event was dropped.");
-#endif
- setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
- }
- mAllocator.releaseEventEntry(entry);
-}
-
-void InputDispatcher::resetKeyRepeatLocked() {
- if (mKeyRepeatState.lastKeyEntry) {
- mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
- mKeyRepeatState.lastKeyEntry = NULL;
- }
-}
-
-InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
- nsecs_t currentTime, nsecs_t keyRepeatDelay) {
- KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
-
- // Reuse the repeated key entry if it is otherwise unreferenced.
- uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
- | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
- if (entry->refCount == 1) {
- mAllocator.recycleKeyEntry(entry);
- entry->eventTime = currentTime;
- entry->policyFlags = policyFlags;
- entry->repeatCount += 1;
- } else {
- KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
- entry->deviceId, entry->source, policyFlags,
- entry->action, entry->flags, entry->keyCode, entry->scanCode,
- entry->metaState, entry->repeatCount + 1, entry->downTime);
-
- mKeyRepeatState.lastKeyEntry = newEntry;
- mAllocator.releaseKeyEntry(entry);
-
- entry = newEntry;
- }
- entry->syntheticRepeat = true;
-
- // Increment reference count since we keep a reference to the event in
- // mKeyRepeatState.lastKeyEntry in addition to the one we return.
- entry->refCount += 1;
-
- if (entry->repeatCount == 1) {
- entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
- }
-
- mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
- return entry;
-}
-
-bool InputDispatcher::dispatchConfigurationChangedLocked(
- nsecs_t currentTime, ConfigurationChangedEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
-#endif
-
- // Reset key repeating in case a keyboard device was added or removed or something.
- resetKeyRepeatLocked();
-
- // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyConfigurationChangedInterruptible);
- commandEntry->eventTime = entry->eventTime;
- return true;
-}
-
-bool InputDispatcher::dispatchKeyLocked(
- nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
- DropReason* dropReason, nsecs_t* nextWakeupTime) {
- // Preprocessing.
- if (! entry->dispatchInProgress) {
- if (entry->repeatCount == 0
- && entry->action == AKEY_EVENT_ACTION_DOWN
- && (entry->policyFlags & POLICY_FLAG_TRUSTED)
- && !entry->isInjected()) {
- if (mKeyRepeatState.lastKeyEntry
- && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
- // We have seen two identical key downs in a row which indicates that the device
- // driver is automatically generating key repeats itself. We take note of the
- // repeat here, but we disable our own next key repeat timer since it is clear that
- // we will not need to synthesize key repeats ourselves.
- entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
- resetKeyRepeatLocked();
- mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
- } else {
- // Not a repeat. Save key down state in case we do see a repeat later.
- resetKeyRepeatLocked();
- mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
- }
- mKeyRepeatState.lastKeyEntry = entry;
- entry->refCount += 1;
- } else if (! entry->syntheticRepeat) {
- resetKeyRepeatLocked();
- }
-
- entry->dispatchInProgress = true;
- resetTargetsLocked();
-
- logOutboundKeyDetailsLocked("dispatchKey - ", entry);
- }
-
- // Give the policy a chance to intercept the key.
- if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
- if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
- if (mFocusedWindow) {
- commandEntry->inputChannel = mFocusedWindow->inputChannel;
- }
- commandEntry->keyEntry = entry;
- entry->refCount += 1;
- return false; // wait for the command to run
- } else {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- }
- } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
- if (*dropReason == DROP_REASON_NOT_DROPPED) {
- *dropReason = DROP_REASON_POLICY;
- }
- }
-
- // Clean up if dropping the event.
- if (*dropReason != DROP_REASON_NOT_DROPPED) {
- resetTargetsLocked();
- setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
- ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
- return true;
- }
-
- // Identify targets.
- if (! mCurrentInputTargetsValid) {
- int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
- entry, nextWakeupTime);
- if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
- return false;
- }
-
- setInjectionResultLocked(entry, injectionResult);
- if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
- return true;
- }
-
- addMonitoringTargetsLocked();
- commitTargetsLocked();
- }
-
- // Dispatch the key.
- dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
- return true;
-}
-
-void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
- "repeatCount=%d, downTime=%lld",
- prefix,
- entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
- entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
- entry->repeatCount, entry->downTime);
-#endif
-}
-
-bool InputDispatcher::dispatchMotionLocked(
- nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
- // Preprocessing.
- if (! entry->dispatchInProgress) {
- entry->dispatchInProgress = true;
- resetTargetsLocked();
-
- logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
- }
-
- // Clean up if dropping the event.
- if (*dropReason != DROP_REASON_NOT_DROPPED) {
- resetTargetsLocked();
- setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
- ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
- return true;
- }
-
- bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
-
- // Identify targets.
- if (! mCurrentInputTargetsValid) {
- int32_t injectionResult;
- if (isPointerEvent) {
- // Pointer event. (eg. touchscreen)
- injectionResult = findTouchedWindowTargetsLocked(currentTime,
- entry, nextWakeupTime);
- } else {
- // Non touch event. (eg. trackball)
- injectionResult = findFocusedWindowTargetsLocked(currentTime,
- entry, nextWakeupTime);
- }
- if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
- return false;
- }
-
- setInjectionResultLocked(entry, injectionResult);
- if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
- return true;
- }
-
- addMonitoringTargetsLocked();
- commitTargetsLocked();
- }
-
- // Dispatch the motion.
- dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
- return true;
-}
-
-
-void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, "
- "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
- prefix,
- entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
- entry->action, entry->flags,
- entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
- entry->downTime);
-
- // Print the most recent sample that we have available, this may change due to batching.
- size_t sampleCount = 1;
- const MotionSample* sample = & entry->firstSample;
- for (; sample->next != NULL; sample = sample->next) {
- sampleCount += 1;
- }
- for (uint32_t i = 0; i < entry->pointerCount; i++) {
- LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
- "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
- "orientation=%f",
- i, entry->pointerIds[i],
- sample->pointerCoords[i].x, sample->pointerCoords[i].y,
- sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
- sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
- sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
- sample->pointerCoords[i].orientation);
- }
-
- // Keep in mind that due to batching, it is possible for the number of samples actually
- // dispatched to change before the application finally consumed them.
- if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
- LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
- }
-#endif
-}
-
-void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
- EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("dispatchEventToCurrentInputTargets - "
- "resumeWithAppendedMotionSample=%s",
- toString(resumeWithAppendedMotionSample));
-#endif
-
- assert(eventEntry->dispatchInProgress); // should already have been set to true
-
- pokeUserActivityLocked(eventEntry);
-
- for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
- const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
-
- ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
- resumeWithAppendedMotionSample);
- } else {
-#if DEBUG_FOCUS
- LOGD("Dropping event delivery to target with channel '%s' because it "
- "is no longer registered with the input dispatcher.",
- inputTarget.inputChannel->getName().string());
-#endif
- }
- }
-}
-
-void InputDispatcher::resetTargetsLocked() {
- mCurrentInputTargetsValid = false;
- mCurrentInputTargets.clear();
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-}
-
-void InputDispatcher::commitTargetsLocked() {
- mCurrentInputTargetsValid = true;
-}
-
-int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
- const EventEntry* entry, const InputApplication* application, const InputWindow* window,
- nsecs_t* nextWakeupTime) {
- if (application == NULL && window == NULL) {
- if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
-#if DEBUG_FOCUS
- LOGD("Waiting for system to become ready for input.");
-#endif
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
- mInputTargetWaitStartTime = currentTime;
- mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
- mInputTargetWaitTimeoutExpired = false;
- }
- } else {
- if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-#if DEBUG_FOCUS
- LOGD("Waiting for application to become ready for input: %s",
- getApplicationWindowLabelLocked(application, window).string());
-#endif
- nsecs_t timeout = window ? window->dispatchingTimeout :
- application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
-
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
- mInputTargetWaitStartTime = currentTime;
- mInputTargetWaitTimeoutTime = currentTime + timeout;
- mInputTargetWaitTimeoutExpired = false;
- }
- }
-
- if (mInputTargetWaitTimeoutExpired) {
- return INPUT_EVENT_INJECTION_TIMED_OUT;
- }
-
- if (currentTime >= mInputTargetWaitTimeoutTime) {
- onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
-
- // Force poll loop to wake up immediately on next iteration once we get the
- // ANR response back from the policy.
- *nextWakeupTime = LONG_LONG_MIN;
- return INPUT_EVENT_INJECTION_PENDING;
- } else {
- // Force poll loop to wake up when timeout is due.
- if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
- *nextWakeupTime = mInputTargetWaitTimeoutTime;
- }
- return INPUT_EVENT_INJECTION_PENDING;
- }
-}
-
-void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
- const sp<InputChannel>& inputChannel) {
- if (newTimeout > 0) {
- // Extend the timeout.
- mInputTargetWaitTimeoutTime = now() + newTimeout;
- } else {
- // Give up.
- mInputTargetWaitTimeoutExpired = true;
-
- // Release the touch targets.
- mTouchState.reset();
-
- // Input state will not be realistic. Mark it out of sync.
- if (inputChannel.get()) {
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- if (connection->status == Connection::STATUS_NORMAL) {
- synthesizeCancelationEventsForConnectionLocked(
- connection, InputState::CANCEL_ALL_EVENTS,
- "application not responding");
- }
- }
- }
- }
-}
-
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
- nsecs_t currentTime) {
- if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
- return currentTime - mInputTargetWaitStartTime;
- }
- return 0;
-}
-
-void InputDispatcher::resetANRTimeoutsLocked() {
-#if DEBUG_FOCUS
- LOGD("Resetting ANR timeouts.");
-#endif
-
- // Reset input target wait timeout.
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-}
-
-int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
- const EventEntry* entry, nsecs_t* nextWakeupTime) {
- mCurrentInputTargets.clear();
-
- int32_t injectionResult;
-
- // If there is no currently focused window and no focused application
- // then drop the event.
- if (! mFocusedWindow) {
- if (mFocusedApplication) {
-#if DEBUG_FOCUS
- LOGD("Waiting because there is no focused window but there is a "
- "focused application that may eventually add a window: %s.",
- getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
-#endif
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplication, NULL, nextWakeupTime);
- goto Unresponsive;
- }
-
- LOGI("Dropping event because there is no focused window or focused application.");
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
-
- // Check permissions.
- if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
- injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- goto Failed;
- }
-
- // If the currently focused window is paused then keep waiting.
- if (mFocusedWindow->paused) {
-#if DEBUG_FOCUS
- LOGD("Waiting because focused window is paused.");
-#endif
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplication, mFocusedWindow, nextWakeupTime);
- goto Unresponsive;
- }
-
- // If the currently focused window is still working on previous events then keep waiting.
- if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
-#if DEBUG_FOCUS
- LOGD("Waiting because focused window still processing previous input.");
-#endif
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplication, mFocusedWindow, nextWakeupTime);
- goto Unresponsive;
- }
-
- // Success! Output targets.
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND, BitSet32(0));
-
- // Done.
-Failed:
-Unresponsive:
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime, entry,
- injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
- LOGD("findFocusedWindow finished: injectionResult=%d, "
- "timeSpendWaitingForApplication=%0.1fms",
- injectionResult, timeSpentWaitingForApplication / 1000000.0);
-#endif
- return injectionResult;
-}
-
-int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
- const MotionEntry* entry, nsecs_t* nextWakeupTime) {
- enum InjectionPermission {
- INJECTION_PERMISSION_UNKNOWN,
- INJECTION_PERMISSION_GRANTED,
- INJECTION_PERMISSION_DENIED
- };
-
- mCurrentInputTargets.clear();
-
- nsecs_t startTime = now();
-
- // For security reasons, we defer updating the touch state until we are sure that
- // event injection will be allowed.
- //
- // FIXME In the original code, screenWasOff could never be set to true.
- // The reason is that the POLICY_FLAG_WOKE_HERE
- // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
- // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
- // actually enqueued using the policyFlags that appeared in the final EV_SYN
- // events upon which no preprocessing took place. So policyFlags was always 0.
- // In the new native input dispatcher we're a bit more careful about event
- // preprocessing so the touches we receive can actually have non-zero policyFlags.
- // Unfortunately we obtain undesirable behavior.
- //
- // Here's what happens:
- //
- // When the device dims in anticipation of going to sleep, touches
- // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
- // the device to brighten and reset the user activity timer.
- // Touches on other windows (such as the launcher window)
- // are dropped. Then after a moment, the device goes to sleep. Oops.
- //
- // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
- // instead of POLICY_FLAG_WOKE_HERE...
- //
- bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
-
- int32_t action = entry->action;
- int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-
- // Update the touch state as needed based on the properties of the touch event.
- int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
- InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- mTempTouchState.reset();
- mTempTouchState.down = true;
- } else {
- mTempTouchState.copyFrom(mTouchState);
- }
-
- bool isSplit = mTempTouchState.split && mTempTouchState.down;
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN
- || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
- /* Case 1: New splittable pointer going down. */
-
- int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex].x);
- int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex].y);
- const InputWindow* newTouchedWindow = NULL;
- const InputWindow* topErrorWindow = NULL;
-
- // Traverse windows from front to back to find touched window and outside targets.
- size_t numWindows = mWindows.size();
- for (size_t i = 0; i < numWindows; i++) {
- const InputWindow* window = & mWindows.editItemAt(i);
- int32_t flags = window->layoutParamsFlags;
-
- if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
- if (! topErrorWindow) {
- topErrorWindow = window;
- }
- }
-
- if (window->visible) {
- if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
- bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
- | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
- if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
- newTouchedWindow = window;
- }
- break; // found touched window, exit window loop
- }
- }
-
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN
- && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
- int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
- if (isWindowObscuredAtPointLocked(window, x, y)) {
- outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
-
- mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
- }
- }
- }
-
- // If there is an error window but it is not taking focus (typically because
- // it is invisible) then wait for it. Any other focused window may in
- // fact be in ANR state.
- if (topErrorWindow && newTouchedWindow != topErrorWindow) {
-#if DEBUG_FOCUS
- LOGD("Waiting because system error window is pending.");
-#endif
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, NULL, nextWakeupTime);
- injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- goto Unresponsive;
- }
-
- // Figure out whether splitting will be allowed for this window.
- if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
- // New window supports splitting.
- isSplit = true;
- } else if (isSplit) {
- // New window does not support splitting but we have already split events.
- // Assign the pointer to the first foreground window we find.
- // (May be NULL which is why we put this code block before the next check.)
- newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
- }
-
- // If we did not find a touched window then fail.
- if (! newTouchedWindow) {
- if (mFocusedApplication) {
-#if DEBUG_FOCUS
- LOGD("Waiting because there is no touched window but there is a "
- "focused application that may eventually add a new window: %s.",
- getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
-#endif
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplication, NULL, nextWakeupTime);
- goto Unresponsive;
- }
-
- LOGI("Dropping event because there is no touched window or focused application.");
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
-
- // Set target flags.
- int32_t targetFlags = InputTarget::FLAG_FOREGROUND;
- if (isSplit) {
- targetFlags |= InputTarget::FLAG_SPLIT;
- }
- if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
- targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
-
- // Update the temporary touch state.
- BitSet32 pointerIds;
- if (isSplit) {
- uint32_t pointerId = entry->pointerIds[pointerIndex];
- pointerIds.markBit(pointerId);
- }
- mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
- } else {
- /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
-
- // If the pointer is not currently down, then ignore the event.
- if (! mTempTouchState.down) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
- LOGD("Dropping event because the pointer is not down or we previously "
- "dropped the pointer down event.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
- }
-
- // Check permission to inject into all touched foreground windows and ensure there
- // is at least one touched foreground window.
- {
- bool haveForegroundWindow = false;
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
- haveForegroundWindow = true;
- if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
- injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- injectionPermission = INJECTION_PERMISSION_DENIED;
- goto Failed;
- }
- }
- }
- if (! haveForegroundWindow) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
- LOGD("Dropping event because there is no touched foreground window to receive it.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
-
- // Permission granted to injection into all touched foreground windows.
- injectionPermission = INJECTION_PERMISSION_GRANTED;
- }
-
- // Ensure all touched foreground windows are ready for new input.
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
- // If the touched window is paused then keep waiting.
- if (touchedWindow.window->paused) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
- LOGD("Waiting because touched window is paused.");
-#endif
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, touchedWindow.window, nextWakeupTime);
- goto Unresponsive;
- }
-
- // If the touched window is still working on previous events then keep waiting.
- if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
-#if DEBUG_FOCUS
- LOGD("Waiting because touched window still processing previous input.");
-#endif
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, touchedWindow.window, nextWakeupTime);
- goto Unresponsive;
- }
- }
- }
-
- // If this is the first pointer going down and the touched window has a wallpaper
- // then also add the touched wallpaper windows so they are locked in for the duration
- // of the touch gesture.
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
- if (foregroundWindow->hasWallpaper) {
- for (size_t i = 0; i < mWindows.size(); i++) {
- const InputWindow* window = & mWindows[i];
- if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
- mTempTouchState.addOrUpdateWindow(window,
- InputTarget::FLAG_WINDOW_IS_OBSCURED, BitSet32(0));
- }
- }
- }
- }
-
- // Success! Output targets.
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
- addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
- touchedWindow.pointerIds);
- }
-
- // Drop the outside touch window since we will not care about them in the next iteration.
- mTempTouchState.removeOutsideTouchWindows();
-
-Failed:
- // Check injection permission once and for all.
- if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
- if (checkInjectionPermission(NULL, entry->injectionState)) {
- injectionPermission = INJECTION_PERMISSION_GRANTED;
- } else {
- injectionPermission = INJECTION_PERMISSION_DENIED;
- }
- }
-
- // Update final pieces of touch state if the injector had permission.
- if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
- if (maskedAction == AMOTION_EVENT_ACTION_UP
- || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
- // All pointers up or canceled.
- mTempTouchState.reset();
- } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- // First pointer went down.
- if (mTouchState.down) {
-#if DEBUG_FOCUS
- LOGD("Pointer down received while already down.");
-#endif
- }
- } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
- // One pointer went up.
- if (isSplit) {
- int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- uint32_t pointerId = entry->pointerIds[pointerIndex];
-
- for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
- TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
- if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
- touchedWindow.pointerIds.clearBit(pointerId);
- if (touchedWindow.pointerIds.isEmpty()) {
- mTempTouchState.windows.removeAt(i);
- continue;
- }
- }
- i += 1;
- }
- }
- }
-
- // Save changes to touch state.
- mTouchState.copyFrom(mTempTouchState);
- } else {
-#if DEBUG_FOCUS
- LOGD("Not updating touch focus because injection was denied.");
-#endif
- }
-
-Unresponsive:
- // Reset temporary touch state to ensure we release unnecessary references to input channels.
- mTempTouchState.reset();
-
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime, entry,
- injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
- LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
-#endif
- return injectionResult;
-}
-
-void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
- BitSet32 pointerIds) {
- mCurrentInputTargets.push();
-
- InputTarget& target = mCurrentInputTargets.editTop();
- target.inputChannel = window->inputChannel;
- target.flags = targetFlags;
- target.xOffset = - window->frameLeft;
- target.yOffset = - window->frameTop;
- target.pointerIds = pointerIds;
-}
-
-void InputDispatcher::addMonitoringTargetsLocked() {
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- mCurrentInputTargets.push();
-
- InputTarget& target = mCurrentInputTargets.editTop();
- target.inputChannel = mMonitoringChannels[i];
- target.flags = 0;
- target.xOffset = 0;
- target.yOffset = 0;
- }
-}
-
-bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
- const InjectionState* injectionState) {
- if (injectionState
- && (window == NULL || window->ownerUid != injectionState->injectorUid)
- && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
- if (window) {
- LOGW("Permission denied: injecting event from pid %d uid %d to window "
- "with input channel %s owned by uid %d",
- injectionState->injectorPid, injectionState->injectorUid,
- window->inputChannel->getName().string(),
- window->ownerUid);
- } else {
- LOGW("Permission denied: injecting event from pid %d uid %d",
- injectionState->injectorPid, injectionState->injectorUid);
- }
- return false;
- }
- return true;
-}
-
-bool InputDispatcher::isWindowObscuredAtPointLocked(
- const InputWindow* window, int32_t x, int32_t y) const {
- size_t numWindows = mWindows.size();
- for (size_t i = 0; i < numWindows; i++) {
- const InputWindow* other = & mWindows.itemAt(i);
- if (other == window) {
- break;
- }
- if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
- return true;
- }
- }
- return false;
-}
-
-bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
- ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- return connection->outboundQueue.isEmpty();
- } else {
- return true;
- }
-}
-
-String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
- const InputWindow* window) {
- if (application) {
- if (window) {
- String8 label(application->name);
- label.append(" - ");
- label.append(window->name);
- return label;
- } else {
- return application->name;
- }
- } else if (window) {
- return window->name;
- } else {
- return String8("<unknown application or window>");
- }
-}
-
-void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
- int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
- switch (eventEntry->type) {
- case EventEntry::TYPE_MOTION: {
- const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
- if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
- return;
- }
-
- if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
- eventType = POWER_MANAGER_TOUCH_EVENT;
- }
- break;
- }
- case EventEntry::TYPE_KEY: {
- const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
- if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
- return;
- }
- break;
- }
- }
-
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doPokeUserActivityLockedInterruptible);
- commandEntry->eventTime = eventEntry->eventTime;
- commandEntry->userActivityEventType = eventType;
-}
-
-void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
- bool resumeWithAppendedMotionSample) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, "
- "xOffset=%f, yOffset=%f, "
- "pointerIds=0x%x, "
- "resumeWithAppendedMotionSample=%s",
- connection->getInputChannelName(), inputTarget->flags,
- inputTarget->xOffset, inputTarget->yOffset,
- inputTarget->pointerIds.value,
- toString(resumeWithAppendedMotionSample));
-#endif
-
- // Make sure we are never called for streaming when splitting across multiple windows.
- bool isSplit = inputTarget->flags & InputTarget::FLAG_SPLIT;
- assert(! (resumeWithAppendedMotionSample && isSplit));
-
- // Skip this event if the connection status is not normal.
- // We don't want to enqueue additional outbound events if the connection is broken.
- if (connection->status != Connection::STATUS_NORMAL) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("channel '%s' ~ Dropping event because the channel status is %s",
- connection->getInputChannelName(), connection->getStatusLabel());
-#endif
- return;
- }
-
- // Split a motion event if needed.
- if (isSplit) {
- assert(eventEntry->type == EventEntry::TYPE_MOTION);
-
- MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
- if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
- MotionEntry* splitMotionEntry = splitMotionEvent(
- originalMotionEntry, inputTarget->pointerIds);
-#if DEBUG_FOCUS
- LOGD("channel '%s' ~ Split motion event.",
- connection->getInputChannelName());
- logOutboundMotionDetailsLocked(" ", splitMotionEntry);
-#endif
- eventEntry = splitMotionEntry;
- }
- }
-
- // Resume the dispatch cycle with a freshly appended motion sample.
- // First we check that the last dispatch entry in the outbound queue is for the same
- // motion event to which we appended the motion sample. If we find such a dispatch
- // entry, and if it is currently in progress then we try to stream the new sample.
- bool wasEmpty = connection->outboundQueue.isEmpty();
-
- if (! wasEmpty && resumeWithAppendedMotionSample) {
- DispatchEntry* motionEventDispatchEntry =
- connection->findQueuedDispatchEntryForEvent(eventEntry);
- if (motionEventDispatchEntry) {
- // If the dispatch entry is not in progress, then we must be busy dispatching an
- // earlier event. Not a problem, the motion event is on the outbound queue and will
- // be dispatched later.
- if (! motionEventDispatchEntry->inProgress) {
-#if DEBUG_BATCHING
- LOGD("channel '%s' ~ Not streaming because the motion event has "
- "not yet been dispatched. "
- "(Waiting for earlier events to be consumed.)",
- connection->getInputChannelName());
-#endif
- return;
- }
-
- // If the dispatch entry is in progress but it already has a tail of pending
- // motion samples, then it must mean that the shared memory buffer filled up.
- // Not a problem, when this dispatch cycle is finished, we will eventually start
- // a new dispatch cycle to process the tail and that tail includes the newly
- // appended motion sample.
- if (motionEventDispatchEntry->tailMotionSample) {
-#if DEBUG_BATCHING
- LOGD("channel '%s' ~ Not streaming because no new samples can "
- "be appended to the motion event in this dispatch cycle. "
- "(Waiting for next dispatch cycle to start.)",
- connection->getInputChannelName());
-#endif
- return;
- }
-
- // The dispatch entry is in progress and is still potentially open for streaming.
- // Try to stream the new motion sample. This might fail if the consumer has already
- // consumed the motion event (or if the channel is broken).
- MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
- MotionSample* appendedMotionSample = motionEntry->lastSample;
- status_t status = connection->inputPublisher.appendMotionSample(
- appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
- if (status == OK) {
-#if DEBUG_BATCHING
- LOGD("channel '%s' ~ Successfully streamed new motion sample.",
- connection->getInputChannelName());
-#endif
- return;
- }
-
-#if DEBUG_BATCHING
- if (status == NO_MEMORY) {
- LOGD("channel '%s' ~ Could not append motion sample to currently "
- "dispatched move event because the shared memory buffer is full. "
- "(Waiting for next dispatch cycle to start.)",
- connection->getInputChannelName());
- } else if (status == status_t(FAILED_TRANSACTION)) {
- LOGD("channel '%s' ~ Could not append motion sample to currently "
- "dispatched move event because the event has already been consumed. "
- "(Waiting for next dispatch cycle to start.)",
- connection->getInputChannelName());
- } else {
- LOGD("channel '%s' ~ Could not append motion sample to currently "
- "dispatched move event due to an error, status=%d. "
- "(Waiting for next dispatch cycle to start.)",
- connection->getInputChannelName(), status);
- }
-#endif
- // Failed to stream. Start a new tail of pending motion samples to dispatch
- // in the next cycle.
- motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
- return;
- }
- }
-
- // This is a new event.
- // Enqueue a new dispatch entry onto the outbound queue for this connection.
- DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
- inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset);
- if (dispatchEntry->hasForegroundTarget()) {
- incrementPendingForegroundDispatchesLocked(eventEntry);
- }
-
- // Handle the case where we could not stream a new motion sample because the consumer has
- // already consumed the motion event (otherwise the corresponding dispatch entry would
- // still be in the outbound queue for this connection). We set the head motion sample
- // to the list starting with the newly appended motion sample.
- if (resumeWithAppendedMotionSample) {
-#if DEBUG_BATCHING
- LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
- "that cannot be streamed because the motion event has already been consumed.",
- connection->getInputChannelName());
-#endif
- MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
- dispatchEntry->headMotionSample = appendedMotionSample;
- }
-
- // Enqueue the dispatch entry.
- connection->outboundQueue.enqueueAtTail(dispatchEntry);
-
- // If the outbound queue was previously empty, start the dispatch cycle going.
- if (wasEmpty) {
- activateConnectionLocked(connection.get());
- startDispatchCycleLocked(currentTime, connection);
- }
-}
-
-void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("channel '%s' ~ startDispatchCycle",
- connection->getInputChannelName());
-#endif
-
- assert(connection->status == Connection::STATUS_NORMAL);
- assert(! connection->outboundQueue.isEmpty());
-
- DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
- assert(! dispatchEntry->inProgress);
-
- // Mark the dispatch entry as in progress.
- dispatchEntry->inProgress = true;
-
- // Update the connection's input state.
- EventEntry* eventEntry = dispatchEntry->eventEntry;
- InputState::Consistency consistency = connection->inputState.trackEvent(eventEntry);
-
-#if FILTER_INPUT_EVENTS
- // Filter out inconsistent sequences of input events.
- // The input system may drop or inject events in a way that could violate implicit
- // invariants on input state and potentially cause an application to crash
- // or think that a key or pointer is stuck down. Technically we make no guarantees
- // of consistency but it would be nice to improve on this where possible.
- // XXX: This code is a proof of concept only. Not ready for prime time.
- if (consistency == InputState::TOLERABLE) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's "
- "current input state but that is likely to be tolerated by the application.",
- connection->getInputChannelName());
-#endif
- } else if (consistency == InputState::BROKEN) {
- LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's "
- "current input state and that is likely to cause the application to crash.",
- connection->getInputChannelName());
- startNextDispatchCycleLocked(currentTime, connection);
- return;
- }
-#endif
-
- // Publish the event.
- status_t status;
- switch (eventEntry->type) {
- case EventEntry::TYPE_KEY: {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
-
- // Apply target flags.
- int32_t action = keyEntry->action;
- int32_t flags = keyEntry->flags;
-
- // Publish the key event.
- status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
- action, flags, keyEntry->keyCode, keyEntry->scanCode,
- keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
- keyEntry->eventTime);
-
- if (status) {
- LOGE("channel '%s' ~ Could not publish key event, "
- "status=%d", connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
- return;
- }
- break;
- }
-
- case EventEntry::TYPE_MOTION: {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-
- // Apply target flags.
- int32_t action = motionEntry->action;
- int32_t flags = motionEntry->flags;
- if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
- action = AMOTION_EVENT_ACTION_OUTSIDE;
- }
- if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
- flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
- }
-
- // If headMotionSample is non-NULL, then it points to the first new sample that we
- // were unable to dispatch during the previous cycle so we resume dispatching from
- // that point in the list of motion samples.
- // Otherwise, we just start from the first sample of the motion event.
- MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
- if (! firstMotionSample) {
- firstMotionSample = & motionEntry->firstSample;
- }
-
- // Set the X and Y offset depending on the input source.
- float xOffset, yOffset;
- if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
- xOffset = dispatchEntry->xOffset;
- yOffset = dispatchEntry->yOffset;
- } else {
- xOffset = 0.0f;
- yOffset = 0.0f;
- }
-
- // Publish the motion event and the first motion sample.
- status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
- motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
- xOffset, yOffset,
- motionEntry->xPrecision, motionEntry->yPrecision,
- motionEntry->downTime, firstMotionSample->eventTime,
- motionEntry->pointerCount, motionEntry->pointerIds,
- firstMotionSample->pointerCoords);
-
- if (status) {
- LOGE("channel '%s' ~ Could not publish motion event, "
- "status=%d", connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
- return;
- }
-
- // Append additional motion samples.
- MotionSample* nextMotionSample = firstMotionSample->next;
- for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
- status = connection->inputPublisher.appendMotionSample(
- nextMotionSample->eventTime, nextMotionSample->pointerCoords);
- if (status == NO_MEMORY) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
- "be sent in the next dispatch cycle.",
- connection->getInputChannelName());
-#endif
- break;
- }
- if (status != OK) {
- LOGE("channel '%s' ~ Could not append motion sample "
- "for a reason other than out of memory, status=%d",
- connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
- return;
- }
- }
-
- // Remember the next motion sample that we could not dispatch, in case we ran out
- // of space in the shared memory buffer.
- dispatchEntry->tailMotionSample = nextMotionSample;
- break;
- }
-
- default: {
- assert(false);
- }
- }
-
- // Send the dispatch signal.
- status = connection->inputPublisher.sendDispatchSignal();
- if (status) {
- LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
- connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
- return;
- }
-
- // Record information about the newly started dispatch cycle.
- connection->lastEventTime = eventEntry->eventTime;
- connection->lastDispatchTime = currentTime;
-
- // Notify other system components.
- onDispatchCycleStartedLocked(currentTime, connection);
-}
-
-void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, bool handled) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
- "%01.1fms since dispatch, handled=%s",
- connection->getInputChannelName(),
- connection->getEventLatencyMillis(currentTime),
- connection->getDispatchLatencyMillis(currentTime),
- toString(handled));
-#endif
-
- if (connection->status == Connection::STATUS_BROKEN
- || connection->status == Connection::STATUS_ZOMBIE) {
- return;
- }
-
- // Reset the publisher since the event has been consumed.
- // We do this now so that the publisher can release some of its internal resources
- // while waiting for the next dispatch cycle to begin.
- status_t status = connection->inputPublisher.reset();
- if (status) {
- LOGE("channel '%s' ~ Could not reset publisher, status=%d",
- connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
- return;
- }
-
- // Notify other system components and prepare to start the next dispatch cycle.
- onDispatchCycleFinishedLocked(currentTime, connection, handled);
-}
-
-void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
- // Start the next dispatch cycle for this connection.
- while (! connection->outboundQueue.isEmpty()) {
- DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
- if (dispatchEntry->inProgress) {
- // Finish or resume current event in progress.
- if (dispatchEntry->tailMotionSample) {
- // We have a tail of undispatched motion samples.
- // Reuse the same DispatchEntry and start a new cycle.
- dispatchEntry->inProgress = false;
- dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
- dispatchEntry->tailMotionSample = NULL;
- startDispatchCycleLocked(currentTime, connection);
- return;
- }
- // Finished.
- connection->outboundQueue.dequeueAtHead();
- if (dispatchEntry->hasForegroundTarget()) {
- decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
- }
- mAllocator.releaseDispatchEntry(dispatchEntry);
- } else {
- // If the head is not in progress, then we must have already dequeued the in
- // progress event, which means we actually aborted it.
- // So just start the next event for this connection.
- startDispatchCycleLocked(currentTime, connection);
- return;
- }
- }
-
- // Outbound queue is empty, deactivate the connection.
- deactivateConnectionLocked(connection.get());
-}
-
-void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
-#if DEBUG_DISPATCH_CYCLE
- LOGD("channel '%s' ~ abortBrokenDispatchCycle",
- connection->getInputChannelName());
-#endif
-
- // Clear the outbound queue.
- drainOutboundQueueLocked(connection.get());
-
- // The connection appears to be unrecoverably broken.
- // Ignore already broken or zombie connections.
- if (connection->status == Connection::STATUS_NORMAL) {
- connection->status = Connection::STATUS_BROKEN;
-
- // Notify other system components.
- onDispatchCycleBrokenLocked(currentTime, connection);
- }
-}
-
-void InputDispatcher::drainOutboundQueueLocked(Connection* connection) {
- while (! connection->outboundQueue.isEmpty()) {
- DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
- if (dispatchEntry->hasForegroundTarget()) {
- decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
- }
- mAllocator.releaseDispatchEntry(dispatchEntry);
- }
-
- deactivateConnectionLocked(connection);
-}
-
-int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
- InputDispatcher* d = static_cast<InputDispatcher*>(data);
-
- { // acquire lock
- AutoMutex _l(d->mLock);
-
- ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
- if (connectionIndex < 0) {
- LOGE("Received spurious receive callback for unknown input channel. "
- "fd=%d, events=0x%x", receiveFd, events);
- return 0; // remove the callback
- }
-
- nsecs_t currentTime = now();
-
- sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
- if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
- LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
- "events=0x%x", connection->getInputChannelName(), events);
- d->abortBrokenDispatchCycleLocked(currentTime, connection);
- d->runCommandsLockedInterruptible();
- return 0; // remove the callback
- }
-
- if (! (events & ALOOPER_EVENT_INPUT)) {
- LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
- "events=0x%x", connection->getInputChannelName(), events);
- return 1;
- }
-
- bool handled = false;
- status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
- if (status) {
- LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
- connection->getInputChannelName(), status);
- d->abortBrokenDispatchCycleLocked(currentTime, connection);
- d->runCommandsLockedInterruptible();
- return 0; // remove the callback
- }
-
- d->finishDispatchCycleLocked(currentTime, connection, handled);
- d->runCommandsLockedInterruptible();
- return 1;
- } // release lock
-}
-
-void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CancelationOptions options, const char* reason) {
- for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
- synthesizeCancelationEventsForConnectionLocked(
- mConnectionsByReceiveFd.valueAt(i), options, reason);
- }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
- const sp<InputChannel>& channel, InputState::CancelationOptions options,
- const char* reason) {
- ssize_t index = getConnectionIndexLocked(channel);
- if (index >= 0) {
- synthesizeCancelationEventsForConnectionLocked(
- mConnectionsByReceiveFd.valueAt(index), options, reason);
- }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
- const sp<Connection>& connection, InputState::CancelationOptions options,
- const char* reason) {
- nsecs_t currentTime = now();
-
- mTempCancelationEvents.clear();
- connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
- mTempCancelationEvents, options);
-
- if (! mTempCancelationEvents.isEmpty()
- && connection->status != Connection::STATUS_BROKEN) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
- "with reality: %s, options=%d.",
- connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
-#endif
- for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
- EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
- switch (cancelationEventEntry->type) {
- case EventEntry::TYPE_KEY:
- logOutboundKeyDetailsLocked("cancel - ",
- static_cast<KeyEntry*>(cancelationEventEntry));
- break;
- case EventEntry::TYPE_MOTION:
- logOutboundMotionDetailsLocked("cancel - ",
- static_cast<MotionEntry*>(cancelationEventEntry));
- break;
- }
-
- int32_t xOffset, yOffset;
- const InputWindow* window = getWindowLocked(connection->inputChannel);
- if (window) {
- xOffset = -window->frameLeft;
- yOffset = -window->frameTop;
- } else {
- xOffset = 0;
- yOffset = 0;
- }
-
- DispatchEntry* cancelationDispatchEntry =
- mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
- 0, xOffset, yOffset);
- connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
-
- mAllocator.releaseEventEntry(cancelationEventEntry);
- }
-
- if (!connection->outboundQueue.headSentinel.next->inProgress) {
- startDispatchCycleLocked(currentTime, connection);
- }
- }
-}
-
-InputDispatcher::MotionEntry*
-InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
- assert(pointerIds.value != 0);
-
- uint32_t splitPointerIndexMap[MAX_POINTERS];
- int32_t splitPointerIds[MAX_POINTERS];
- PointerCoords splitPointerCoords[MAX_POINTERS];
-
- uint32_t originalPointerCount = originalMotionEntry->pointerCount;
- uint32_t splitPointerCount = 0;
-
- for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
- originalPointerIndex++) {
- int32_t pointerId = uint32_t(originalMotionEntry->pointerIds[originalPointerIndex]);
- if (pointerIds.hasBit(pointerId)) {
- splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
- splitPointerIds[splitPointerCount] = pointerId;
- splitPointerCoords[splitPointerCount] =
- originalMotionEntry->firstSample.pointerCoords[originalPointerIndex];
- splitPointerCount += 1;
- }
- }
- assert(splitPointerCount == pointerIds.count());
-
- int32_t action = originalMotionEntry->action;
- int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
- if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
- || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
- int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
- int32_t pointerId = originalMotionEntry->pointerIds[originalPointerIndex];
- if (pointerIds.hasBit(pointerId)) {
- if (pointerIds.count() == 1) {
- // The first/last pointer went down/up.
- action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
- ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
- } else {
- // A secondary pointer went down/up.
- uint32_t splitPointerIndex = 0;
- while (pointerId != splitPointerIds[splitPointerIndex]) {
- splitPointerIndex += 1;
- }
- action = maskedAction | (splitPointerIndex
- << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- }
- } else {
- // An unrelated pointer changed.
- action = AMOTION_EVENT_ACTION_MOVE;
- }
- }
-
- MotionEntry* splitMotionEntry = mAllocator.obtainMotionEntry(
- originalMotionEntry->eventTime,
- originalMotionEntry->deviceId,
- originalMotionEntry->source,
- originalMotionEntry->policyFlags,
- action,
- originalMotionEntry->flags,
- originalMotionEntry->metaState,
- originalMotionEntry->edgeFlags,
- originalMotionEntry->xPrecision,
- originalMotionEntry->yPrecision,
- originalMotionEntry->downTime,
- splitPointerCount, splitPointerIds, splitPointerCoords);
-
- for (MotionSample* originalMotionSample = originalMotionEntry->firstSample.next;
- originalMotionSample != NULL; originalMotionSample = originalMotionSample->next) {
- for (uint32_t splitPointerIndex = 0; splitPointerIndex < splitPointerCount;
- splitPointerIndex++) {
- uint32_t originalPointerIndex = splitPointerIndexMap[splitPointerIndex];
- splitPointerCoords[splitPointerIndex] =
- originalMotionSample->pointerCoords[originalPointerIndex];
- }
-
- mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime,
- splitPointerCoords);
- }
-
- return splitMotionEntry;
-}
-
-void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
-#endif
-
- bool needWake;
- { // acquire lock
- AutoMutex _l(mLock);
-
- ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
- needWake = enqueueInboundEventLocked(newEntry);
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
- uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- LOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
- "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
- eventTime, deviceId, source, policyFlags, action, flags,
- keyCode, scanCode, metaState, downTime);
-#endif
- if (! validateKeyEvent(action)) {
- return;
- }
-
- if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
- policyFlags |= POLICY_FLAG_VIRTUAL;
- flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
- }
-
- policyFlags |= POLICY_FLAG_TRUSTED;
-
- KeyEvent event;
- event.initialize(deviceId, source, action, flags, keyCode, scanCode,
- metaState, 0, downTime, eventTime);
-
- mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
-
- if (policyFlags & POLICY_FLAG_WOKE_HERE) {
- flags |= AKEY_EVENT_FLAG_WOKE_HERE;
- }
-
- bool needWake;
- { // acquire lock
- AutoMutex _l(mLock);
-
- int32_t repeatCount = 0;
- KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
- deviceId, source, policyFlags, action, flags, keyCode, scanCode,
- metaState, repeatCount, downTime);
-
- needWake = enqueueInboundEventLocked(newEntry);
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
- uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
- uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
- float xPrecision, float yPrecision, nsecs_t downTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
- "xPrecision=%f, yPrecision=%f, downTime=%lld",
- eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
- xPrecision, yPrecision, downTime);
- for (uint32_t i = 0; i < pointerCount; i++) {
- LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
- "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
- "orientation=%f",
- i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
- pointerCoords[i].pressure, pointerCoords[i].size,
- pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
- pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
- pointerCoords[i].orientation);
- }
-#endif
- if (! validateMotionEvent(action, pointerCount, pointerIds)) {
- return;
- }
-
- policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
-
- bool needWake;
- { // acquire lock
- AutoMutex _l(mLock);
-
- // Attempt batching and streaming of move events.
- if (action == AMOTION_EVENT_ACTION_MOVE) {
- // BATCHING CASE
- //
- // Try to append a move sample to the tail of the inbound queue for this device.
- // Give up if we encounter a non-move motion event for this device since that
- // means we cannot append any new samples until a new motion event has started.
- for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
- entry != & mInboundQueue.headSentinel; entry = entry->prev) {
- if (entry->type != EventEntry::TYPE_MOTION) {
- // Keep looking for motion events.
- continue;
- }
-
- MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
- if (motionEntry->deviceId != deviceId) {
- // Keep looking for this device.
- continue;
- }
-
- if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
- || motionEntry->pointerCount != pointerCount
- || motionEntry->isInjected()) {
- // Last motion event in the queue for this device is not compatible for
- // appending new samples. Stop here.
- goto NoBatchingOrStreaming;
- }
-
- // The last motion event is a move and is compatible for appending.
- // Do the batching magic.
- mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
-#if DEBUG_BATCHING
- LOGD("Appended motion sample onto batch for most recent "
- "motion event for this device in the inbound queue.");
-#endif
- return; // done!
- }
-
- // STREAMING CASE
- //
- // There is no pending motion event (of any kind) for this device in the inbound queue.
- // Search the outbound queue for the current foreground targets to find a dispatched
- // motion event that is still in progress. If found, then, appen the new sample to
- // that event and push it out to all current targets. The logic in
- // prepareDispatchCycleLocked takes care of the case where some targets may
- // already have consumed the motion event by starting a new dispatch cycle if needed.
- if (mCurrentInputTargetsValid) {
- for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
- const InputTarget& inputTarget = mCurrentInputTargets[i];
- if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
- // Skip non-foreground targets. We only want to stream if there is at
- // least one foreground target whose dispatch is still in progress.
- continue;
- }
-
- ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
- if (connectionIndex < 0) {
- // Connection must no longer be valid.
- continue;
- }
-
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- if (connection->outboundQueue.isEmpty()) {
- // This foreground target has an empty outbound queue.
- continue;
- }
-
- DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
- if (! dispatchEntry->inProgress
- || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
- || dispatchEntry->isSplit()) {
- // No motion event is being dispatched, or it is being split across
- // windows in which case we cannot stream.
- continue;
- }
-
- MotionEntry* motionEntry = static_cast<MotionEntry*>(
- dispatchEntry->eventEntry);
- if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
- || motionEntry->deviceId != deviceId
- || motionEntry->pointerCount != pointerCount
- || motionEntry->isInjected()) {
- // The motion event is not compatible with this move.
- continue;
- }
-
- // Hurray! This foreground target is currently dispatching a move event
- // that we can stream onto. Append the motion sample and resume dispatch.
- mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
-#if DEBUG_BATCHING
- LOGD("Appended motion sample onto batch for most recently dispatched "
- "motion event for this device in the outbound queues. "
- "Attempting to stream the motion sample.");
-#endif
- nsecs_t currentTime = now();
- dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
- true /*resumeWithAppendedMotionSample*/);
-
- runCommandsLockedInterruptible();
- return; // done!
- }
- }
-
-NoBatchingOrStreaming:;
- }
-
- // Just enqueue a new motion event.
- MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
- deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
- xPrecision, yPrecision, downTime,
- pointerCount, pointerIds, pointerCoords);
-
- needWake = enqueueInboundEventLocked(newEntry);
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
- uint32_t policyFlags) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x",
- switchCode, switchValue, policyFlags);
-#endif
-
- policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
-}
-
-int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
- "syncMode=%d, timeoutMillis=%d",
- event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
-#endif
-
- nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
-
- uint32_t policyFlags = POLICY_FLAG_INJECTED;
- if (hasInjectionPermission(injectorPid, injectorUid)) {
- policyFlags |= POLICY_FLAG_TRUSTED;
- }
-
- EventEntry* injectedEntry;
- switch (event->getType()) {
- case AINPUT_EVENT_TYPE_KEY: {
- const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
- int32_t action = keyEvent->getAction();
- if (! validateKeyEvent(action)) {
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- int32_t flags = keyEvent->getFlags();
- if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
- policyFlags |= POLICY_FLAG_VIRTUAL;
- }
-
- mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
-
- if (policyFlags & POLICY_FLAG_WOKE_HERE) {
- flags |= AKEY_EVENT_FLAG_WOKE_HERE;
- }
-
- mLock.lock();
- injectedEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
- keyEvent->getDeviceId(), keyEvent->getSource(),
- policyFlags, action, flags,
- keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
- keyEvent->getRepeatCount(), keyEvent->getDownTime());
- break;
- }
-
- case AINPUT_EVENT_TYPE_MOTION: {
- const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
- int32_t action = motionEvent->getAction();
- size_t pointerCount = motionEvent->getPointerCount();
- const int32_t* pointerIds = motionEvent->getPointerIds();
- if (! validateMotionEvent(action, pointerCount, pointerIds)) {
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- nsecs_t eventTime = motionEvent->getEventTime();
- mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
-
- mLock.lock();
- const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
- const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
- MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
- action, motionEvent->getFlags(),
- motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
- motionEvent->getXPrecision(), motionEvent->getYPrecision(),
- motionEvent->getDownTime(), uint32_t(pointerCount),
- pointerIds, samplePointerCoords);
- for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
- sampleEventTimes += 1;
- samplePointerCoords += pointerCount;
- mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
- }
- injectedEntry = motionEntry;
- break;
- }
-
- default:
- LOGW("Cannot inject event of type %d", event->getType());
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
- if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
- injectionState->injectionIsAsync = true;
- }
-
- injectionState->refCount += 1;
- injectedEntry->injectionState = injectionState;
-
- bool needWake = enqueueInboundEventLocked(injectedEntry);
- mLock.unlock();
-
- if (needWake) {
- mLooper->wake();
- }
-
- int32_t injectionResult;
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- } else {
- for (;;) {
- injectionResult = injectionState->injectionResult;
- if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
- break;
- }
-
- nsecs_t remainingTimeout = endTime - now();
- if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
- LOGD("injectInputEvent - Timed out waiting for injection result "
- "to become available.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
- break;
- }
-
- mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
- }
-
- if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
- && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
- while (injectionState->pendingForegroundDispatches != 0) {
-#if DEBUG_INJECTION
- LOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
- injectionState->pendingForegroundDispatches);
-#endif
- nsecs_t remainingTimeout = endTime - now();
- if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
- LOGD("injectInputEvent - Timed out waiting for pending foreground "
- "dispatches to finish.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
- break;
- }
-
- mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
- }
- }
- }
-
- mAllocator.releaseInjectionState(injectionState);
- } // release lock
-
-#if DEBUG_INJECTION
- LOGD("injectInputEvent - Finished with result %d. "
- "injectorPid=%d, injectorUid=%d",
- injectionResult, injectorPid, injectorUid);
-#endif
-
- return injectionResult;
-}
-
-bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
- return injectorUid == 0
- || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
-}
-
-void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
-#if DEBUG_INJECTION
- LOGD("Setting input event injection result to %d. "
- "injectorPid=%d, injectorUid=%d",
- injectionResult, injectionState->injectorPid, injectionState->injectorUid);
-#endif
-
- if (injectionState->injectionIsAsync) {
- // Log the outcome since the injector did not wait for the injection result.
- switch (injectionResult) {
- case INPUT_EVENT_INJECTION_SUCCEEDED:
- LOGV("Asynchronous input event injection succeeded.");
- break;
- case INPUT_EVENT_INJECTION_FAILED:
- LOGW("Asynchronous input event injection failed.");
- break;
- case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
- LOGW("Asynchronous input event injection permission denied.");
- break;
- case INPUT_EVENT_INJECTION_TIMED_OUT:
- LOGW("Asynchronous input event injection timed out.");
- break;
- }
- }
-
- injectionState->injectionResult = injectionResult;
- mInjectionResultAvailableCondition.broadcast();
- }
-}
-
-void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
- injectionState->pendingForegroundDispatches += 1;
- }
-}
-
-void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
- injectionState->pendingForegroundDispatches -= 1;
-
- if (injectionState->pendingForegroundDispatches == 0) {
- mInjectionSyncFinishedCondition.broadcast();
- }
- }
-}
-
-const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
- for (size_t i = 0; i < mWindows.size(); i++) {
- const InputWindow* window = & mWindows[i];
- if (window->inputChannel == inputChannel) {
- return window;
- }
- }
- return NULL;
-}
-
-void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
-#if DEBUG_FOCUS
- LOGD("setInputWindows");
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- // Clear old window pointers.
- sp<InputChannel> oldFocusedWindowChannel;
- if (mFocusedWindow) {
- oldFocusedWindowChannel = mFocusedWindow->inputChannel;
- mFocusedWindow = NULL;
- }
-
- mWindows.clear();
-
- // Loop over new windows and rebuild the necessary window pointers for
- // tracking focus and touch.
- mWindows.appendVector(inputWindows);
-
- size_t numWindows = mWindows.size();
- for (size_t i = 0; i < numWindows; i++) {
- const InputWindow* window = & mWindows.itemAt(i);
- if (window->hasFocus) {
- mFocusedWindow = window;
- break;
- }
- }
-
- if (oldFocusedWindowChannel != NULL) {
- if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
-#if DEBUG_FOCUS
- LOGD("Focus left window: %s",
- oldFocusedWindowChannel->getName().string());
-#endif
- synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
- InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
- oldFocusedWindowChannel.clear();
- }
- }
- if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
-#if DEBUG_FOCUS
- LOGD("Focus entered window: %s",
- mFocusedWindow->inputChannel->getName().string());
-#endif
- }
-
- for (size_t i = 0; i < mTouchState.windows.size(); ) {
- TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
- const InputWindow* window = getWindowLocked(touchedWindow.channel);
- if (window) {
- touchedWindow.window = window;
- i += 1;
- } else {
-#if DEBUG_FOCUS
- LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
-#endif
- synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
- InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
- mTouchState.windows.removeAt(i);
- }
- }
-
-#if DEBUG_FOCUS
- //logDispatchStateLocked();
-#endif
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
-}
-
-void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
-#if DEBUG_FOCUS
- LOGD("setFocusedApplication");
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- releaseFocusedApplicationLocked();
-
- if (inputApplication) {
- mFocusedApplicationStorage = *inputApplication;
- mFocusedApplication = & mFocusedApplicationStorage;
- }
-
-#if DEBUG_FOCUS
- //logDispatchStateLocked();
-#endif
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
-}
-
-void InputDispatcher::releaseFocusedApplicationLocked() {
- if (mFocusedApplication) {
- mFocusedApplication = NULL;
- mFocusedApplicationStorage.handle.clear();
- }
-}
-
-void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
-#if DEBUG_FOCUS
- LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
-#endif
-
- bool changed;
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
- if (mDispatchFrozen && !frozen) {
- resetANRTimeoutsLocked();
- }
-
- if (mDispatchEnabled && !enabled) {
- resetAndDropEverythingLocked("dispatcher is being disabled");
- }
-
- mDispatchEnabled = enabled;
- mDispatchFrozen = frozen;
- changed = true;
- } else {
- changed = false;
- }
-
-#if DEBUG_FOCUS
- //logDispatchStateLocked();
-#endif
- } // release lock
-
- if (changed) {
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
- }
-}
-
-bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) {
-#if DEBUG_FOCUS
- LOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
- fromChannel->getName().string(), toChannel->getName().string());
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- const InputWindow* fromWindow = getWindowLocked(fromChannel);
- const InputWindow* toWindow = getWindowLocked(toChannel);
- if (! fromWindow || ! toWindow) {
-#if DEBUG_FOCUS
- LOGD("Cannot transfer focus because from or to window not found.");
-#endif
- return false;
- }
- if (fromWindow == toWindow) {
-#if DEBUG_FOCUS
- LOGD("Trivial transfer to same window.");
-#endif
- return true;
- }
-
- bool found = false;
- for (size_t i = 0; i < mTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTouchState.windows[i];
- if (touchedWindow.window == fromWindow) {
- int32_t oldTargetFlags = touchedWindow.targetFlags;
- BitSet32 pointerIds = touchedWindow.pointerIds;
-
- mTouchState.windows.removeAt(i);
-
- int32_t newTargetFlags = oldTargetFlags
- & (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT);
- mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
-
- found = true;
- break;
- }
- }
-
- if (! found) {
-#if DEBUG_FOCUS
- LOGD("Focus transfer failed because from window did not have focus.");
-#endif
- return false;
- }
-
- ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
- ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
- if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
- sp<Connection> fromConnection = mConnectionsByReceiveFd.valueAt(fromConnectionIndex);
- sp<Connection> toConnection = mConnectionsByReceiveFd.valueAt(toConnectionIndex);
-
- fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
- synthesizeCancelationEventsForConnectionLocked(fromConnection,
- InputState::CANCEL_POINTER_EVENTS,
- "transferring touch focus from this window to another window");
- }
-
-#if DEBUG_FOCUS
- logDispatchStateLocked();
-#endif
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
- return true;
-}
-
-void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
-#if DEBUG_FOCUS
- LOGD("Resetting and dropping all events (%s).", reason);
-#endif
-
- synthesizeCancelationEventsForAllConnectionsLocked(InputState::CANCEL_ALL_EVENTS, reason);
-
- resetKeyRepeatLocked();
- releasePendingEventLocked();
- drainInboundQueueLocked();
- resetTargetsLocked();
-
- mTouchState.reset();
-}
-
-void InputDispatcher::logDispatchStateLocked() {
- String8 dump;
- dumpDispatchStateLocked(dump);
-
- char* text = dump.lockBuffer(dump.size());
- char* start = text;
- while (*start != '\0') {
- char* end = strchr(start, '\n');
- if (*end == '\n') {
- *(end++) = '\0';
- }
- LOGD("%s", start);
- start = end;
- }
-}
-
-void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
- dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
- dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
-
- if (mFocusedApplication) {
- dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
- mFocusedApplication->name.string(),
- mFocusedApplication->dispatchingTimeout / 1000000.0);
- } else {
- dump.append(INDENT "FocusedApplication: <null>\n");
- }
- dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
- mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
-
- dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
- dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
- if (!mTouchState.windows.isEmpty()) {
- dump.append(INDENT "TouchedWindows:\n");
- for (size_t i = 0; i < mTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTouchState.windows[i];
- dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
- i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value,
- touchedWindow.targetFlags);
- }
- } else {
- dump.append(INDENT "TouchedWindows: <none>\n");
- }
-
- if (!mWindows.isEmpty()) {
- dump.append(INDENT "Windows:\n");
- for (size_t i = 0; i < mWindows.size(); i++) {
- const InputWindow& window = mWindows[i];
- dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
- "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
- "frame=[%d,%d][%d,%d], "
- "visibleFrame=[%d,%d][%d,%d], "
- "touchableArea=[%d,%d][%d,%d], "
- "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
- i, window.name.string(),
- toString(window.paused),
- toString(window.hasFocus),
- toString(window.hasWallpaper),
- toString(window.visible),
- toString(window.canReceiveKeys),
- window.layoutParamsFlags, window.layoutParamsType,
- window.layer,
- window.frameLeft, window.frameTop,
- window.frameRight, window.frameBottom,
- window.visibleFrameLeft, window.visibleFrameTop,
- window.visibleFrameRight, window.visibleFrameBottom,
- window.touchableAreaLeft, window.touchableAreaTop,
- window.touchableAreaRight, window.touchableAreaBottom,
- window.ownerPid, window.ownerUid,
- window.dispatchingTimeout / 1000000.0);
- }
- } else {
- dump.append(INDENT "Windows: <none>\n");
- }
-
- if (!mMonitoringChannels.isEmpty()) {
- dump.append(INDENT "MonitoringChannels:\n");
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- const sp<InputChannel>& channel = mMonitoringChannels[i];
- dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
- }
- } else {
- dump.append(INDENT "MonitoringChannels: <none>\n");
- }
-
- dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
-
- if (!mActiveConnections.isEmpty()) {
- dump.append(INDENT "ActiveConnections:\n");
- for (size_t i = 0; i < mActiveConnections.size(); i++) {
- const Connection* connection = mActiveConnections[i];
- dump.appendFormat(INDENT2 "%d: '%s', status=%s, outboundQueueLength=%u, "
- "inputState.isNeutral=%s\n",
- i, connection->getInputChannelName(), connection->getStatusLabel(),
- connection->outboundQueue.count(),
- toString(connection->inputState.isNeutral()));
- }
- } else {
- dump.append(INDENT "ActiveConnections: <none>\n");
- }
-
- if (isAppSwitchPendingLocked()) {
- dump.appendFormat(INDENT "AppSwitch: pending, due in %01.1fms\n",
- (mAppSwitchDueTime - now()) / 1000000.0);
- } else {
- dump.append(INDENT "AppSwitch: not pending\n");
- }
-}
-
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
-#if DEBUG_REGISTRATION
- LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
- toString(monitor));
-#endif
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (getConnectionIndexLocked(inputChannel) >= 0) {
- LOGW("Attempted to register already registered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
- }
-
- sp<Connection> connection = new Connection(inputChannel);
- status_t status = connection->initialize();
- if (status) {
- LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
- inputChannel->getName().string(), status);
- return status;
- }
-
- int32_t receiveFd = inputChannel->getReceivePipeFd();
- mConnectionsByReceiveFd.add(receiveFd, connection);
-
- if (monitor) {
- mMonitoringChannels.push(inputChannel);
- }
-
- mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
-
- runCommandsLockedInterruptible();
- } // release lock
- return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
-#if DEBUG_REGISTRATION
- LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
-#endif
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- if (connectionIndex < 0) {
- LOGW("Attempted to unregister already unregistered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
- }
-
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
-
- connection->status = Connection::STATUS_ZOMBIE;
-
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- if (mMonitoringChannels[i] == inputChannel) {
- mMonitoringChannels.removeAt(i);
- break;
- }
- }
-
- mLooper->removeFd(inputChannel->getReceivePipeFd());
-
- nsecs_t currentTime = now();
- abortBrokenDispatchCycleLocked(currentTime, connection);
-
- runCommandsLockedInterruptible();
- } // release lock
-
- // Wake the poll loop because removing the connection may have changed the current
- // synchronization state.
- mLooper->wake();
- return OK;
-}
-
-ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
- ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- if (connection->inputChannel.get() == inputChannel.get()) {
- return connectionIndex;
- }
- }
-
- return -1;
-}
-
-void InputDispatcher::activateConnectionLocked(Connection* connection) {
- for (size_t i = 0; i < mActiveConnections.size(); i++) {
- if (mActiveConnections.itemAt(i) == connection) {
- return;
- }
- }
- mActiveConnections.add(connection);
-}
-
-void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
- for (size_t i = 0; i < mActiveConnections.size(); i++) {
- if (mActiveConnections.itemAt(i) == connection) {
- mActiveConnections.removeAt(i);
- return;
- }
- }
-}
-
-void InputDispatcher::onDispatchCycleStartedLocked(
- nsecs_t currentTime, const sp<Connection>& connection) {
-}
-
-void InputDispatcher::onDispatchCycleFinishedLocked(
- nsecs_t currentTime, const sp<Connection>& connection, bool handled) {
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
- commandEntry->connection = connection;
- commandEntry->handled = handled;
-}
-
-void InputDispatcher::onDispatchCycleBrokenLocked(
- nsecs_t currentTime, const sp<Connection>& connection) {
- LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
- connection->getInputChannelName());
-
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
- commandEntry->connection = connection;
-}
-
-void InputDispatcher::onANRLocked(
- nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
- nsecs_t eventTime, nsecs_t waitStartTime) {
- LOGI("Application is not responding: %s. "
- "%01.1fms since event, %01.1fms since wait started",
- getApplicationWindowLabelLocked(application, window).string(),
- (currentTime - eventTime) / 1000000.0,
- (currentTime - waitStartTime) / 1000000.0);
-
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyANRLockedInterruptible);
- if (application) {
- commandEntry->inputApplicationHandle = application->handle;
- }
- if (window) {
- commandEntry->inputChannel = window->inputChannel;
- }
-}
-
-void InputDispatcher::doNotifyConfigurationChangedInterruptible(
- CommandEntry* commandEntry) {
- mLock.unlock();
-
- mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
-
- mLock.lock();
-}
-
-void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
- CommandEntry* commandEntry) {
- sp<Connection> connection = commandEntry->connection;
-
- if (connection->status != Connection::STATUS_ZOMBIE) {
- mLock.unlock();
-
- mPolicy->notifyInputChannelBroken(connection->inputChannel);
-
- mLock.lock();
- }
-}
-
-void InputDispatcher::doNotifyANRLockedInterruptible(
- CommandEntry* commandEntry) {
- mLock.unlock();
-
- nsecs_t newTimeout = mPolicy->notifyANR(
- commandEntry->inputApplicationHandle, commandEntry->inputChannel);
-
- mLock.lock();
-
- resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
-}
-
-void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
- CommandEntry* commandEntry) {
- KeyEntry* entry = commandEntry->keyEntry;
-
- KeyEvent event;
- initializeKeyEvent(&event, entry);
-
- mLock.unlock();
-
- bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
- &event, entry->policyFlags);
-
- mLock.lock();
-
- entry->interceptKeyResult = consumed
- ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
- : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- mAllocator.releaseKeyEntry(entry);
-}
-
-void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
- CommandEntry* commandEntry) {
- sp<Connection> connection = commandEntry->connection;
- bool handled = commandEntry->handled;
-
- if (!connection->outboundQueue.isEmpty()) {
- DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
- if (dispatchEntry->inProgress
- && dispatchEntry->hasForegroundTarget()
- && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
- if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
- if (handled) {
- // If the application handled a non-fallback key, then immediately
- // cancel all fallback keys previously dispatched to the application.
- // This behavior will prevent chording with fallback keys (so they cannot
- // be used as modifiers) but it will ensure that fallback keys do not
- // get stuck. This takes care of the case where the application does not handle
- // the original DOWN so we generate a fallback DOWN but it does handle
- // the original UP in which case we would not generate the fallback UP.
- synthesizeCancelationEventsForConnectionLocked(connection,
- InputState::CANCEL_FALLBACK_EVENTS,
- "application handled a non-fallback event, canceling all fallback events");
- } else {
- // If the application did not handle a non-fallback key, then ask
- // the policy what to do with it. We might generate a fallback key
- // event here.
- KeyEvent event;
- initializeKeyEvent(&event, keyEntry);
-
- mLock.unlock();
-
- bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
- &event, keyEntry->policyFlags, &event);
-
- mLock.lock();
-
- if (connection->status != Connection::STATUS_NORMAL) {
- return;
- }
-
- assert(connection->outboundQueue.headSentinel.next == dispatchEntry);
-
- if (fallback) {
- // Restart the dispatch cycle using the fallback key.
- keyEntry->eventTime = event.getEventTime();
- keyEntry->deviceId = event.getDeviceId();
- keyEntry->source = event.getSource();
- keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
- keyEntry->keyCode = event.getKeyCode();
- keyEntry->scanCode = event.getScanCode();
- keyEntry->metaState = event.getMetaState();
- keyEntry->repeatCount = event.getRepeatCount();
- keyEntry->downTime = event.getDownTime();
- keyEntry->syntheticRepeat = false;
-
- dispatchEntry->inProgress = false;
- startDispatchCycleLocked(now(), connection);
- return;
- }
- }
- }
- }
- }
-
- startNextDispatchCycleLocked(now(), connection);
-}
-
-void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
- mLock.unlock();
-
- mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
-
- mLock.lock();
-}
-
-void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
- event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
- entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
- entry->downTime, entry->eventTime);
-}
-
-void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
- int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
- // TODO Write some statistics about how long we spend waiting.
-}
-
-void InputDispatcher::dump(String8& dump) {
- dump.append("Input Dispatcher State:\n");
- dumpDispatchStateLocked(dump);
-}
-
-
-// --- InputDispatcher::Queue ---
-
-template <typename T>
-uint32_t InputDispatcher::Queue<T>::count() const {
- uint32_t result = 0;
- for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
- result += 1;
- }
- return result;
-}
-
-
-// --- InputDispatcher::Allocator ---
-
-InputDispatcher::Allocator::Allocator() {
-}
-
-InputDispatcher::InjectionState*
-InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t injectorUid) {
- InjectionState* injectionState = mInjectionStatePool.alloc();
- injectionState->refCount = 1;
- injectionState->injectorPid = injectorPid;
- injectionState->injectorUid = injectorUid;
- injectionState->injectionIsAsync = false;
- injectionState->injectionResult = INPUT_EVENT_INJECTION_PENDING;
- injectionState->pendingForegroundDispatches = 0;
- return injectionState;
-}
-
-void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
- nsecs_t eventTime, uint32_t policyFlags) {
- entry->type = type;
- entry->refCount = 1;
- entry->dispatchInProgress = false;
- entry->eventTime = eventTime;
- entry->policyFlags = policyFlags;
- entry->injectionState = NULL;
-}
-
-void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* entry) {
- if (entry->injectionState) {
- releaseInjectionState(entry->injectionState);
- entry->injectionState = NULL;
- }
-}
-
-InputDispatcher::ConfigurationChangedEntry*
-InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
- ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
- initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
- return entry;
-}
-
-InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
- int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
- int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
- int32_t repeatCount, nsecs_t downTime) {
- KeyEntry* entry = mKeyEntryPool.alloc();
- initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
-
- entry->deviceId = deviceId;
- entry->source = source;
- entry->action = action;
- entry->flags = flags;
- entry->keyCode = keyCode;
- entry->scanCode = scanCode;
- entry->metaState = metaState;
- entry->repeatCount = repeatCount;
- entry->downTime = downTime;
- entry->syntheticRepeat = false;
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
- return entry;
-}
-
-InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
- int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
- nsecs_t downTime, uint32_t pointerCount,
- const int32_t* pointerIds, const PointerCoords* pointerCoords) {
- MotionEntry* entry = mMotionEntryPool.alloc();
- initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
-
- entry->eventTime = eventTime;
- entry->deviceId = deviceId;
- entry->source = source;
- entry->action = action;
- entry->flags = flags;
- entry->metaState = metaState;
- entry->edgeFlags = edgeFlags;
- entry->xPrecision = xPrecision;
- entry->yPrecision = yPrecision;
- entry->downTime = downTime;
- entry->pointerCount = pointerCount;
- entry->firstSample.eventTime = eventTime;
- entry->firstSample.next = NULL;
- entry->lastSample = & entry->firstSample;
- for (uint32_t i = 0; i < pointerCount; i++) {
- entry->pointerIds[i] = pointerIds[i];
- entry->firstSample.pointerCoords[i] = pointerCoords[i];
- }
- return entry;
-}
-
-InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
- EventEntry* eventEntry,
- int32_t targetFlags, float xOffset, float yOffset) {
- DispatchEntry* entry = mDispatchEntryPool.alloc();
- entry->eventEntry = eventEntry;
- eventEntry->refCount += 1;
- entry->targetFlags = targetFlags;
- entry->xOffset = xOffset;
- entry->yOffset = yOffset;
- entry->inProgress = false;
- entry->headMotionSample = NULL;
- entry->tailMotionSample = NULL;
- return entry;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
- CommandEntry* entry = mCommandEntryPool.alloc();
- entry->command = command;
- return entry;
-}
-
-void InputDispatcher::Allocator::releaseInjectionState(InjectionState* injectionState) {
- injectionState->refCount -= 1;
- if (injectionState->refCount == 0) {
- mInjectionStatePool.free(injectionState);
- } else {
- assert(injectionState->refCount > 0);
- }
-}
-
-void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
- switch (entry->type) {
- case EventEntry::TYPE_CONFIGURATION_CHANGED:
- releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
- break;
- case EventEntry::TYPE_KEY:
- releaseKeyEntry(static_cast<KeyEntry*>(entry));
- break;
- case EventEntry::TYPE_MOTION:
- releaseMotionEntry(static_cast<MotionEntry*>(entry));
- break;
- default:
- assert(false);
- break;
- }
-}
-
-void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
- ConfigurationChangedEntry* entry) {
- entry->refCount -= 1;
- if (entry->refCount == 0) {
- releaseEventEntryInjectionState(entry);
- mConfigurationChangeEntryPool.free(entry);
- } else {
- assert(entry->refCount > 0);
- }
-}
-
-void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
- entry->refCount -= 1;
- if (entry->refCount == 0) {
- releaseEventEntryInjectionState(entry);
- mKeyEntryPool.free(entry);
- } else {
- assert(entry->refCount > 0);
- }
-}
-
-void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
- entry->refCount -= 1;
- if (entry->refCount == 0) {
- releaseEventEntryInjectionState(entry);
- for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
- MotionSample* next = sample->next;
- mMotionSamplePool.free(sample);
- sample = next;
- }
- mMotionEntryPool.free(entry);
- } else {
- assert(entry->refCount > 0);
- }
-}
-
-void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
- releaseEventEntry(entry->eventEntry);
- mDispatchEntryPool.free(entry);
-}
-
-void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
- mCommandEntryPool.free(entry);
-}
-
-void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
- nsecs_t eventTime, const PointerCoords* pointerCoords) {
- MotionSample* sample = mMotionSamplePool.alloc();
- sample->eventTime = eventTime;
- uint32_t pointerCount = motionEntry->pointerCount;
- for (uint32_t i = 0; i < pointerCount; i++) {
- sample->pointerCoords[i] = pointerCoords[i];
- }
-
- sample->next = NULL;
- motionEntry->lastSample->next = sample;
- motionEntry->lastSample = sample;
-}
-
-void InputDispatcher::Allocator::recycleKeyEntry(KeyEntry* keyEntry) {
- releaseEventEntryInjectionState(keyEntry);
-
- keyEntry->dispatchInProgress = false;
- keyEntry->syntheticRepeat = false;
- keyEntry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
-}
-
-
-// --- InputDispatcher::MotionEntry ---
-
-uint32_t InputDispatcher::MotionEntry::countSamples() const {
- uint32_t count = 1;
- for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
- count += 1;
- }
- return count;
-}
-
-
-// --- InputDispatcher::InputState ---
-
-InputDispatcher::InputState::InputState() {
-}
-
-InputDispatcher::InputState::~InputState() {
-}
-
-bool InputDispatcher::InputState::isNeutral() const {
- return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
- const EventEntry* entry) {
- switch (entry->type) {
- case EventEntry::TYPE_KEY:
- return trackKey(static_cast<const KeyEntry*>(entry));
-
- case EventEntry::TYPE_MOTION:
- return trackMotion(static_cast<const MotionEntry*>(entry));
-
- default:
- return CONSISTENT;
- }
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
- const KeyEntry* entry) {
- int32_t action = entry->action;
- for (size_t i = 0; i < mKeyMementos.size(); i++) {
- KeyMemento& memento = mKeyMementos.editItemAt(i);
- if (memento.deviceId == entry->deviceId
- && memento.source == entry->source
- && memento.keyCode == entry->keyCode
- && memento.scanCode == entry->scanCode) {
- switch (action) {
- case AKEY_EVENT_ACTION_UP:
- mKeyMementos.removeAt(i);
- return CONSISTENT;
-
- case AKEY_EVENT_ACTION_DOWN:
- return TOLERABLE;
-
- default:
- return BROKEN;
- }
- }
- }
-
- switch (action) {
- case AKEY_EVENT_ACTION_DOWN: {
- mKeyMementos.push();
- KeyMemento& memento = mKeyMementos.editTop();
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.keyCode = entry->keyCode;
- memento.scanCode = entry->scanCode;
- memento.flags = entry->flags;
- memento.downTime = entry->downTime;
- return CONSISTENT;
- }
-
- default:
- return BROKEN;
- }
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
- const MotionEntry* entry) {
- int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- MotionMemento& memento = mMotionMementos.editItemAt(i);
- if (memento.deviceId == entry->deviceId
- && memento.source == entry->source) {
- switch (action) {
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
- mMotionMementos.removeAt(i);
- return CONSISTENT;
-
- case AMOTION_EVENT_ACTION_DOWN:
- return TOLERABLE;
-
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- if (entry->pointerCount == memento.pointerCount + 1) {
- memento.setPointers(entry);
- return CONSISTENT;
- }
- return BROKEN;
-
- case AMOTION_EVENT_ACTION_POINTER_UP:
- if (entry->pointerCount == memento.pointerCount - 1) {
- memento.setPointers(entry);
- return CONSISTENT;
- }
- return BROKEN;
-
- case AMOTION_EVENT_ACTION_MOVE:
- if (entry->pointerCount == memento.pointerCount) {
- return CONSISTENT;
- }
- return BROKEN;
-
- default:
- return BROKEN;
- }
- }
- }
-
- switch (action) {
- case AMOTION_EVENT_ACTION_DOWN: {
- mMotionMementos.push();
- MotionMemento& memento = mMotionMementos.editTop();
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.xPrecision = entry->xPrecision;
- memento.yPrecision = entry->yPrecision;
- memento.downTime = entry->downTime;
- memento.setPointers(entry);
- return CONSISTENT;
- }
-
- default:
- return BROKEN;
- }
-}
-
-void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
- pointerCount = entry->pointerCount;
- for (uint32_t i = 0; i < entry->pointerCount; i++) {
- pointerIds[i] = entry->pointerIds[i];
- pointerCoords[i] = entry->lastSample->pointerCoords[i];
- }
-}
-
-void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
- Allocator* allocator, Vector<EventEntry*>& outEvents,
- CancelationOptions options) {
- for (size_t i = 0; i < mKeyMementos.size(); ) {
- const KeyMemento& memento = mKeyMementos.itemAt(i);
- if (shouldCancelKey(memento, options)) {
- outEvents.push(allocator->obtainKeyEntry(currentTime,
- memento.deviceId, memento.source, 0,
- AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
- memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
- mKeyMementos.removeAt(i);
- } else {
- i += 1;
- }
- }
-
- for (size_t i = 0; i < mMotionMementos.size(); ) {
- const MotionMemento& memento = mMotionMementos.itemAt(i);
- if (shouldCancelMotion(memento, options)) {
- outEvents.push(allocator->obtainMotionEntry(currentTime,
- memento.deviceId, memento.source, 0,
- AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
- memento.xPrecision, memento.yPrecision, memento.downTime,
- memento.pointerCount, memento.pointerIds, memento.pointerCoords));
- mMotionMementos.removeAt(i);
- } else {
- i += 1;
- }
- }
-}
-
-void InputDispatcher::InputState::clear() {
- mKeyMementos.clear();
- mMotionMementos.clear();
-}
-
-void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos.itemAt(i);
- if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
- for (size_t j = 0; j < other.mMotionMementos.size(); ) {
- const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
- if (memento.deviceId == otherMemento.deviceId
- && memento.source == otherMemento.source) {
- other.mMotionMementos.removeAt(j);
- } else {
- j += 1;
- }
- }
- other.mMotionMementos.push(memento);
- }
- }
-}
-
-bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
- CancelationOptions options) {
- switch (options) {
- case CANCEL_ALL_EVENTS:
- case CANCEL_NON_POINTER_EVENTS:
- return true;
- case CANCEL_FALLBACK_EVENTS:
- return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
- default:
- return false;
- }
-}
-
-bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
- CancelationOptions options) {
- switch (options) {
- case CANCEL_ALL_EVENTS:
- return true;
- case CANCEL_POINTER_EVENTS:
- return memento.source & AINPUT_SOURCE_CLASS_POINTER;
- case CANCEL_NON_POINTER_EVENTS:
- return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
- default:
- return false;
- }
-}
-
-
-// --- InputDispatcher::Connection ---
-
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
- status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
- lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
-}
-
-InputDispatcher::Connection::~Connection() {
-}
-
-status_t InputDispatcher::Connection::initialize() {
- return inputPublisher.initialize();
-}
-
-const char* InputDispatcher::Connection::getStatusLabel() const {
- switch (status) {
- case STATUS_NORMAL:
- return "NORMAL";
-
- case STATUS_BROKEN:
- return "BROKEN";
-
- case STATUS_ZOMBIE:
- return "ZOMBIE";
-
- default:
- return "UNKNOWN";
- }
-}
-
-InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
- const EventEntry* eventEntry) const {
- for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
- dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
- if (dispatchEntry->eventEntry == eventEntry) {
- return dispatchEntry;
- }
- }
- return NULL;
-}
-
-
-// --- InputDispatcher::CommandEntry ---
-
-InputDispatcher::CommandEntry::CommandEntry() :
- keyEntry(NULL) {
-}
-
-InputDispatcher::CommandEntry::~CommandEntry() {
-}
-
-
-// --- InputDispatcher::TouchState ---
-
-InputDispatcher::TouchState::TouchState() :
- down(false), split(false) {
-}
-
-InputDispatcher::TouchState::~TouchState() {
-}
-
-void InputDispatcher::TouchState::reset() {
- down = false;
- split = false;
- windows.clear();
-}
-
-void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
- down = other.down;
- split = other.split;
- windows.clear();
- windows.appendVector(other.windows);
-}
-
-void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
- int32_t targetFlags, BitSet32 pointerIds) {
- if (targetFlags & InputTarget::FLAG_SPLIT) {
- split = true;
- }
-
- for (size_t i = 0; i < windows.size(); i++) {
- TouchedWindow& touchedWindow = windows.editItemAt(i);
- if (touchedWindow.window == window) {
- touchedWindow.targetFlags |= targetFlags;
- touchedWindow.pointerIds.value |= pointerIds.value;
- return;
- }
- }
-
- windows.push();
-
- TouchedWindow& touchedWindow = windows.editTop();
- touchedWindow.window = window;
- touchedWindow.targetFlags = targetFlags;
- touchedWindow.pointerIds = pointerIds;
- touchedWindow.channel = window->inputChannel;
-}
-
-void InputDispatcher::TouchState::removeOutsideTouchWindows() {
- for (size_t i = 0 ; i < windows.size(); ) {
- if (windows[i].targetFlags & InputTarget::FLAG_OUTSIDE) {
- windows.removeAt(i);
- } else {
- i += 1;
- }
- }
-}
-
-const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() {
- for (size_t i = 0; i < windows.size(); i++) {
- if (windows[i].targetFlags & InputTarget::FLAG_FOREGROUND) {
- return windows[i].window;
- }
- }
- return NULL;
-}
-
-
-// --- InputDispatcherThread ---
-
-InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
- Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
-}
-
-InputDispatcherThread::~InputDispatcherThread() {
-}
-
-bool InputDispatcherThread::threadLoop() {
- mDispatcher->dispatchOnce();
- return true;
-}
-
-} // namespace android
diff --git a/libs/ui/InputManager.cpp b/libs/ui/InputManager.cpp
deleted file mode 100644
index 09fce38..0000000
--- a/libs/ui/InputManager.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input manager.
-//
-#define LOG_TAG "InputManager"
-
-//#define LOG_NDEBUG 0
-
-#include <cutils/log.h>
-#include <ui/InputManager.h>
-#include <ui/InputReader.h>
-#include <ui/InputDispatcher.h>
-
-namespace android {
-
-InputManager::InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
- mDispatcher = new InputDispatcher(dispatcherPolicy);
- mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
- initialize();
-}
-
-InputManager::InputManager(
- const sp<InputReaderInterface>& reader,
- const sp<InputDispatcherInterface>& dispatcher) :
- mReader(reader),
- mDispatcher(dispatcher) {
- initialize();
-}
-
-InputManager::~InputManager() {
- stop();
-}
-
-void InputManager::initialize() {
- mReaderThread = new InputReaderThread(mReader);
- mDispatcherThread = new InputDispatcherThread(mDispatcher);
-}
-
-status_t InputManager::start() {
- status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
- if (result) {
- LOGE("Could not start InputDispatcher thread due to error %d.", result);
- return result;
- }
-
- result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
- if (result) {
- LOGE("Could not start InputReader thread due to error %d.", result);
-
- mDispatcherThread->requestExit();
- return result;
- }
-
- return OK;
-}
-
-status_t InputManager::stop() {
- status_t result = mReaderThread->requestExitAndWait();
- if (result) {
- LOGW("Could not stop InputReader thread due to error %d.", result);
- }
-
- result = mDispatcherThread->requestExitAndWait();
- if (result) {
- LOGW("Could not stop InputDispatcher thread due to error %d.", result);
- }
-
- return OK;
-}
-
-sp<InputReaderInterface> InputManager::getReader() {
- return mReader;
-}
-
-sp<InputDispatcherInterface> InputManager::getDispatcher() {
- return mDispatcher;
-}
-
-} // namespace android
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
deleted file mode 100644
index a11a010..0000000
--- a/libs/ui/InputReader.cpp
+++ /dev/null
@@ -1,3608 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input reader.
-//
-#define LOG_TAG "InputReader"
-
-//#define LOG_NDEBUG 0
-
-// Log debug messages for each raw event received from the EventHub.
-#define DEBUG_RAW_EVENTS 0
-
-// Log debug messages about touch screen filtering hacks.
-#define DEBUG_HACKS 0
-
-// Log debug messages about virtual key processing.
-#define DEBUG_VIRTUAL_KEYS 0
-
-// Log debug messages about pointers.
-#define DEBUG_POINTERS 0
-
-// Log debug messages about pointer assignment calculations.
-#define DEBUG_POINTER_ASSIGNMENT 0
-
-#include <cutils/log.h>
-#include <ui/InputReader.h>
-#include <ui/Keyboard.h>
-#include <ui/VirtualKeyMap.h>
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-
-#define INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-#define INDENT4 " "
-
-namespace android {
-
-// --- Static Functions ---
-
-template<typename T>
-inline static T abs(const T& value) {
- return value < 0 ? - value : value;
-}
-
-template<typename T>
-inline static T min(const T& a, const T& b) {
- return a < b ? a : b;
-}
-
-template<typename T>
-inline static void swap(T& a, T& b) {
- T temp = a;
- a = b;
- b = temp;
-}
-
-inline static float avg(float x, float y) {
- return (x + y) / 2;
-}
-
-inline static float pythag(float x, float y) {
- return sqrtf(x * x + y * y);
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-static const int32_t keyCodeRotationMap[][4] = {
- // key codes enumerated counter-clockwise with the original (unrotated) key first
- // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
- { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
- { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
- { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
- { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
-};
-static const int keyCodeRotationMapSize =
- sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
-
-int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
- if (orientation != InputReaderPolicyInterface::ROTATION_0) {
- for (int i = 0; i < keyCodeRotationMapSize; i++) {
- if (keyCode == keyCodeRotationMap[i][0]) {
- return keyCodeRotationMap[i][orientation];
- }
- }
- }
- return keyCode;
-}
-
-static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
- return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
-}
-
-
-// --- InputReader ---
-
-InputReader::InputReader(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputDispatcherInterface>& dispatcher) :
- mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
- mGlobalMetaState(0) {
- configureExcludedDevices();
- updateGlobalMetaState();
- updateInputConfiguration();
-}
-
-InputReader::~InputReader() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- delete mDevices.valueAt(i);
- }
-}
-
-void InputReader::loopOnce() {
- RawEvent rawEvent;
- mEventHub->getEvent(& rawEvent);
-
-#if DEBUG_RAW_EVENTS
- LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
- rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
- rawEvent.value);
-#endif
-
- process(& rawEvent);
-}
-
-void InputReader::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EventHubInterface::DEVICE_ADDED:
- addDevice(rawEvent->deviceId);
- break;
-
- case EventHubInterface::DEVICE_REMOVED:
- removeDevice(rawEvent->deviceId);
- break;
-
- case EventHubInterface::FINISHED_DEVICE_SCAN:
- handleConfigurationChanged(rawEvent->when);
- break;
-
- default:
- consumeEvent(rawEvent);
- break;
- }
-}
-
-void InputReader::addDevice(int32_t deviceId) {
- String8 name = mEventHub->getDeviceName(deviceId);
- uint32_t classes = mEventHub->getDeviceClasses(deviceId);
-
- InputDevice* device = createDevice(deviceId, name, classes);
- device->configure();
-
- if (device->isIgnored()) {
- LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
- } else {
- LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
- device->getSources());
- }
-
- bool added = false;
- { // acquire device registry writer lock
- RWLock::AutoWLock _wl(mDeviceRegistryLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- mDevices.add(deviceId, device);
- added = true;
- }
- } // release device registry writer lock
-
- if (! added) {
- LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
- delete device;
- return;
- }
-}
-
-void InputReader::removeDevice(int32_t deviceId) {
- bool removed = false;
- InputDevice* device = NULL;
- { // acquire device registry writer lock
- RWLock::AutoWLock _wl(mDeviceRegistryLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- device = mDevices.valueAt(deviceIndex);
- mDevices.removeItemsAt(deviceIndex, 1);
- removed = true;
- }
- } // release device registry writer lock
-
- if (! removed) {
- LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
- return;
- }
-
- if (device->isIgnored()) {
- LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
- device->getId(), device->getName().string());
- } else {
- LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
- device->getId(), device->getName().string(), device->getSources());
- }
-
- device->reset();
-
- delete device;
-}
-
-InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
- InputDevice* device = new InputDevice(this, deviceId, name);
-
- // Switch-like devices.
- if (classes & INPUT_DEVICE_CLASS_SWITCH) {
- device->addMapper(new SwitchInputMapper(device));
- }
-
- // Keyboard-like devices.
- uint32_t keyboardSources = 0;
- int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
- if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
- keyboardSources |= AINPUT_SOURCE_KEYBOARD;
- }
- if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
- keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
- }
- if (classes & INPUT_DEVICE_CLASS_DPAD) {
- keyboardSources |= AINPUT_SOURCE_DPAD;
- }
-
- if (keyboardSources != 0) {
- device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
- }
-
- // Cursor-like devices.
- if (classes & INPUT_DEVICE_CLASS_CURSOR) {
- device->addMapper(new CursorInputMapper(device));
- }
-
- // Touchscreen-like devices.
- if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
- device->addMapper(new MultiTouchInputMapper(device));
- } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
- device->addMapper(new SingleTouchInputMapper(device));
- }
-
- return device;
-}
-
-void InputReader::consumeEvent(const RawEvent* rawEvent) {
- int32_t deviceId = rawEvent->deviceId;
-
- { // acquire device registry reader lock
- RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- LOGW("Discarding event for unknown deviceId %d.", deviceId);
- return;
- }
-
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (device->isIgnored()) {
- //LOGD("Discarding event for ignored deviceId %d.", deviceId);
- return;
- }
-
- device->process(rawEvent);
- } // release device registry reader lock
-}
-
-void InputReader::handleConfigurationChanged(nsecs_t when) {
- // Reset global meta state because it depends on the list of all configured devices.
- updateGlobalMetaState();
-
- // Update input configuration.
- updateInputConfiguration();
-
- // Enqueue configuration changed.
- mDispatcher->notifyConfigurationChanged(when);
-}
-
-void InputReader::configureExcludedDevices() {
- Vector<String8> excludedDeviceNames;
- mPolicy->getExcludedDeviceNames(excludedDeviceNames);
-
- for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
- mEventHub->addExcludedDevice(excludedDeviceNames[i]);
- }
-}
-
-void InputReader::updateGlobalMetaState() {
- { // acquire state lock
- AutoMutex _l(mStateLock);
-
- mGlobalMetaState = 0;
-
- { // acquire device registry reader lock
- RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- mGlobalMetaState |= device->getMetaState();
- }
- } // release device registry reader lock
- } // release state lock
-}
-
-int32_t InputReader::getGlobalMetaState() {
- { // acquire state lock
- AutoMutex _l(mStateLock);
-
- return mGlobalMetaState;
- } // release state lock
-}
-
-void InputReader::updateInputConfiguration() {
- { // acquire state lock
- AutoMutex _l(mStateLock);
-
- int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
- int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
- int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
- { // acquire device registry reader lock
- RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
- InputDeviceInfo deviceInfo;
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- device->getDeviceInfo(& deviceInfo);
- uint32_t sources = deviceInfo.getSources();
-
- if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
- touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
- }
- if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
- navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
- } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
- navigationConfig = InputConfiguration::NAVIGATION_DPAD;
- }
- if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
- keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
- }
- }
- } // release device registry reader lock
-
- mInputConfiguration.touchScreen = touchScreenConfig;
- mInputConfiguration.keyboard = keyboardConfig;
- mInputConfiguration.navigation = navigationConfig;
- } // release state lock
-}
-
-void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
- { // acquire state lock
- AutoMutex _l(mStateLock);
-
- *outConfiguration = mInputConfiguration;
- } // release state lock
-}
-
-status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
- { // acquire device registry reader lock
- RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- return NAME_NOT_FOUND;
- }
-
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (device->isIgnored()) {
- return NAME_NOT_FOUND;
- }
-
- device->getDeviceInfo(outDeviceInfo);
- return OK;
- } // release device registy reader lock
-}
-
-void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
- outDeviceIds.clear();
-
- { // acquire device registry reader lock
- RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (! device->isIgnored()) {
- outDeviceIds.add(device->getId());
- }
- }
- } // release device registy reader lock
-}
-
-int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t keyCode) {
- return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
-}
-
-int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t scanCode) {
- return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
-}
-
-int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
- return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
-}
-
-int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
- GetStateFunc getStateFunc) {
- { // acquire device registry reader lock
- RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
- int32_t result = AKEY_STATE_UNKNOWN;
- if (deviceId >= 0) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = (device->*getStateFunc)(sourceMask, code);
- }
- }
- } else {
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = (device->*getStateFunc)(sourceMask, code);
- if (result >= AKEY_STATE_DOWN) {
- return result;
- }
- }
- }
- }
- return result;
- } // release device registy reader lock
-}
-
-bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
- memset(outFlags, 0, numCodes);
- return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
-}
-
-bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- { // acquire device registry reader lock
- RWLock::AutoRLock _rl(mDeviceRegistryLock);
- bool result = false;
- if (deviceId >= 0) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = device->markSupportedKeyCodes(sourceMask,
- numCodes, keyCodes, outFlags);
- }
- }
- } else {
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result |= device->markSupportedKeyCodes(sourceMask,
- numCodes, keyCodes, outFlags);
- }
- }
- }
- return result;
- } // release device registy reader lock
-}
-
-void InputReader::dump(String8& dump) {
- mEventHub->dump(dump);
- dump.append("\n");
-
- dump.append("Input Reader State:\n");
-
- { // acquire device registry reader lock
- RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- mDevices.valueAt(i)->dump(dump);
- }
- } // release device registy reader lock
-}
-
-
-// --- InputReaderThread ---
-
-InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
- Thread(/*canCallJava*/ true), mReader(reader) {
-}
-
-InputReaderThread::~InputReaderThread() {
-}
-
-bool InputReaderThread::threadLoop() {
- mReader->loopOnce();
- return true;
-}
-
-
-// --- InputDevice ---
-
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
- mContext(context), mId(id), mName(name), mSources(0) {
-}
-
-InputDevice::~InputDevice() {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- delete mMappers[i];
- }
- mMappers.clear();
-}
-
-static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
- int32_t rangeType, const char* name) {
- const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
- if (range) {
- dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
- name, range->min, range->max, range->flat, range->fuzz);
- }
-}
-
-void InputDevice::dump(String8& dump) {
- InputDeviceInfo deviceInfo;
- getDeviceInfo(& deviceInfo);
-
- dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
- deviceInfo.getName().string());
- dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
- dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
- if (!deviceInfo.getMotionRanges().isEmpty()) {
- dump.append(INDENT2 "Motion Ranges:\n");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
- }
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->dump(dump);
- }
-}
-
-void InputDevice::addMapper(InputMapper* mapper) {
- mMappers.add(mapper);
-}
-
-void InputDevice::configure() {
- if (! isIgnored()) {
- mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
- }
-
- mSources = 0;
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->configure();
- mSources |= mapper->getSources();
- }
-}
-
-void InputDevice::reset() {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->reset();
- }
-}
-
-void InputDevice::process(const RawEvent* rawEvent) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->process(rawEvent);
- }
-}
-
-void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
- outDeviceInfo->initialize(mId, mName);
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->populateDeviceInfo(outDeviceInfo);
- }
-}
-
-int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
-}
-
-int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
-}
-
-int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
-}
-
-int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
- int32_t result = AKEY_STATE_UNKNOWN;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
- result = (mapper->*getStateFunc)(sourceMask, code);
- if (result >= AKEY_STATE_DOWN) {
- return result;
- }
- }
- }
- return result;
-}
-
-bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- bool result = false;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
- result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
- }
- }
- return result;
-}
-
-int32_t InputDevice::getMetaState() {
- int32_t result = 0;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- result |= mapper->getMetaState();
- }
- return result;
-}
-
-
-// --- InputMapper ---
-
-InputMapper::InputMapper(InputDevice* device) :
- mDevice(device), mContext(device->getContext()) {
-}
-
-InputMapper::~InputMapper() {
-}
-
-void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- info->addSource(getSources());
-}
-
-void InputMapper::dump(String8& dump) {
-}
-
-void InputMapper::configure() {
-}
-
-void InputMapper::reset() {
-}
-
-int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- return false;
-}
-
-int32_t InputMapper::getMetaState() {
- return 0;
-}
-
-
-// --- SwitchInputMapper ---
-
-SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
- InputMapper(device) {
-}
-
-SwitchInputMapper::~SwitchInputMapper() {
-}
-
-uint32_t SwitchInputMapper::getSources() {
- return 0;
-}
-
-void SwitchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_SW:
- processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
- break;
- }
-}
-
-void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
- getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
-}
-
-int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return getEventHub()->getSwitchState(getDeviceId(), switchCode);
-}
-
-
-// --- KeyboardInputMapper ---
-
-KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
- uint32_t sources, int32_t keyboardType) :
- InputMapper(device), mSources(sources),
- mKeyboardType(keyboardType) {
- initializeLocked();
-}
-
-KeyboardInputMapper::~KeyboardInputMapper() {
-}
-
-void KeyboardInputMapper::initializeLocked() {
- mLocked.metaState = AMETA_NONE;
- mLocked.downTime = 0;
-}
-
-uint32_t KeyboardInputMapper::getSources() {
- return mSources;
-}
-
-void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- info->setKeyboardType(mKeyboardType);
-}
-
-void KeyboardInputMapper::dump(String8& dump) {
- { // acquire lock
- AutoMutex _l(mLock);
- dump.append(INDENT2 "Keyboard Input Mapper:\n");
- dumpParameters(dump);
- dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
- dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
- dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
- dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
- } // release lock
-}
-
-
-void KeyboardInputMapper::configure() {
- InputMapper::configure();
-
- // Configure basic parameters.
- configureParameters();
-
- // Reset LEDs.
- {
- AutoMutex _l(mLock);
- resetLedStateLocked();
- }
-}
-
-void KeyboardInputMapper::configureParameters() {
- mParameters.orientationAware = false;
- getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
-}
-
-void KeyboardInputMapper::dumpParameters(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
- dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
- mParameters.associatedDisplayId);
- dump.appendFormat(INDENT4 "OrientationAware: %s\n",
- toString(mParameters.orientationAware));
-}
-
-void KeyboardInputMapper::reset() {
- for (;;) {
- int32_t keyCode, scanCode;
- { // acquire lock
- AutoMutex _l(mLock);
-
- // Synthesize key up event on reset if keys are currently down.
- if (mLocked.keyDowns.isEmpty()) {
- initializeLocked();
- resetLedStateLocked();
- break; // done
- }
-
- const KeyDown& keyDown = mLocked.keyDowns.top();
- keyCode = keyDown.keyCode;
- scanCode = keyDown.scanCode;
- } // release lock
-
- nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- processKey(when, false, keyCode, scanCode, 0);
- }
-
- InputMapper::reset();
- getContext()->updateGlobalMetaState();
-}
-
-void KeyboardInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY: {
- int32_t scanCode = rawEvent->scanCode;
- if (isKeyboardOrGamepadKey(scanCode)) {
- processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
- rawEvent->flags);
- }
- break;
- }
- }
-}
-
-bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
- return scanCode < BTN_MOUSE
- || scanCode >= KEY_OK
- || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
-}
-
-void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
- int32_t scanCode, uint32_t policyFlags) {
- int32_t newMetaState;
- nsecs_t downTime;
- bool metaStateChanged = false;
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (down) {
- // Rotate key codes according to orientation if needed.
- // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
- if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
- int32_t orientation;
- if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
- NULL, NULL, & orientation)) {
- orientation = InputReaderPolicyInterface::ROTATION_0;
- }
-
- keyCode = rotateKeyCode(keyCode, orientation);
- }
-
- // Add key down.
- ssize_t keyDownIndex = findKeyDownLocked(scanCode);
- if (keyDownIndex >= 0) {
- // key repeat, be sure to use same keycode as before in case of rotation
- keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
- } else {
- // key down
- mLocked.keyDowns.push();
- KeyDown& keyDown = mLocked.keyDowns.editTop();
- keyDown.keyCode = keyCode;
- keyDown.scanCode = scanCode;
- }
-
- mLocked.downTime = when;
- } else {
- // Remove key down.
- ssize_t keyDownIndex = findKeyDownLocked(scanCode);
- if (keyDownIndex >= 0) {
- // key up, be sure to use same keycode as before in case of rotation
- keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
- mLocked.keyDowns.removeAt(size_t(keyDownIndex));
- } else {
- // key was not actually down
- LOGI("Dropping key up from device %s because the key was not down. "
- "keyCode=%d, scanCode=%d",
- getDeviceName().string(), keyCode, scanCode);
- return;
- }
- }
-
- int32_t oldMetaState = mLocked.metaState;
- newMetaState = updateMetaState(keyCode, down, oldMetaState);
- if (oldMetaState != newMetaState) {
- mLocked.metaState = newMetaState;
- metaStateChanged = true;
- updateLedStateLocked(false);
- }
-
- downTime = mLocked.downTime;
- } // release lock
-
- if (metaStateChanged) {
- getContext()->updateGlobalMetaState();
- }
-
- if (policyFlags & POLICY_FLAG_FUNCTION) {
- newMetaState |= AMETA_FUNCTION_ON;
- }
- getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
- down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
-}
-
-ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
- size_t n = mLocked.keyDowns.size();
- for (size_t i = 0; i < n; i++) {
- if (mLocked.keyDowns[i].scanCode == scanCode) {
- return i;
- }
- }
- return -1;
-}
-
-int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
-}
-
-int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-}
-
-bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
-}
-
-int32_t KeyboardInputMapper::getMetaState() {
- { // acquire lock
- AutoMutex _l(mLock);
- return mLocked.metaState;
- } // release lock
-}
-
-void KeyboardInputMapper::resetLedStateLocked() {
- initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
- initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
- initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
-
- updateLedStateLocked(true);
-}
-
-void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
- ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
- ledState.on = false;
-}
-
-void KeyboardInputMapper::updateLedStateLocked(bool reset) {
- updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
- AMETA_CAPS_LOCK_ON, reset);
- updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
- AMETA_NUM_LOCK_ON, reset);
- updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
- AMETA_SCROLL_LOCK_ON, reset);
-}
-
-void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
- int32_t led, int32_t modifier, bool reset) {
- if (ledState.avail) {
- bool desiredState = (mLocked.metaState & modifier) != 0;
- if (reset || ledState.on != desiredState) {
- getEventHub()->setLedState(getDeviceId(), led, desiredState);
- ledState.on = desiredState;
- }
- }
-}
-
-
-// --- CursorInputMapper ---
-
-CursorInputMapper::CursorInputMapper(InputDevice* device) :
- InputMapper(device) {
- initializeLocked();
-}
-
-CursorInputMapper::~CursorInputMapper() {
-}
-
-uint32_t CursorInputMapper::getSources() {
- return mSources;
-}
-
-void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- if (mParameters.mode == Parameters::MODE_POINTER) {
- float minX, minY, maxX, maxY;
- if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
- info->addMotionRange(AINPUT_MOTION_RANGE_X, minX, maxX, 0.0f, 0.0f);
- info->addMotionRange(AINPUT_MOTION_RANGE_Y, minY, maxY, 0.0f, 0.0f);
- }
- } else {
- info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
- info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
- }
- info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
-}
-
-void CursorInputMapper::dump(String8& dump) {
- { // acquire lock
- AutoMutex _l(mLock);
- dump.append(INDENT2 "Cursor Input Mapper:\n");
- dumpParameters(dump);
- dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
- dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
- dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
- dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
- } // release lock
-}
-
-void CursorInputMapper::configure() {
- InputMapper::configure();
-
- // Configure basic parameters.
- configureParameters();
-
- // Configure device mode.
- switch (mParameters.mode) {
- case Parameters::MODE_POINTER:
- mSources = AINPUT_SOURCE_MOUSE;
- mXPrecision = 1.0f;
- mYPrecision = 1.0f;
- mXScale = 1.0f;
- mYScale = 1.0f;
- mPointerController = getPolicy()->obtainPointerController(getDeviceId());
- break;
- case Parameters::MODE_NAVIGATION:
- mSources = AINPUT_SOURCE_TRACKBALL;
- mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
- mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
- mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
- mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
- break;
- }
-}
-
-void CursorInputMapper::configureParameters() {
- mParameters.mode = Parameters::MODE_POINTER;
- String8 cursorModeString;
- if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
- if (cursorModeString == "navigation") {
- mParameters.mode = Parameters::MODE_NAVIGATION;
- } else if (cursorModeString != "pointer" && cursorModeString != "default") {
- LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
- }
- }
-
- mParameters.orientationAware = false;
- getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
- || mParameters.orientationAware ? 0 : -1;
-}
-
-void CursorInputMapper::dumpParameters(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
- dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
- mParameters.associatedDisplayId);
-
- switch (mParameters.mode) {
- case Parameters::MODE_POINTER:
- dump.append(INDENT4 "Mode: pointer\n");
- break;
- case Parameters::MODE_NAVIGATION:
- dump.append(INDENT4 "Mode: navigation\n");
- break;
- default:
- assert(false);
- }
-
- dump.appendFormat(INDENT4 "OrientationAware: %s\n",
- toString(mParameters.orientationAware));
-}
-
-void CursorInputMapper::initializeLocked() {
- mAccumulator.clear();
-
- mLocked.down = false;
- mLocked.downTime = 0;
-}
-
-void CursorInputMapper::reset() {
- for (;;) {
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (! mLocked.down) {
- initializeLocked();
- break; // done
- }
- } // release lock
-
- // Synthesize button up event on reset.
- nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
- mAccumulator.btnMouse = false;
- sync(when);
- }
-
- InputMapper::reset();
-}
-
-void CursorInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY:
- switch (rawEvent->scanCode) {
- case BTN_MOUSE:
- mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
- mAccumulator.btnMouse = rawEvent->value != 0;
- // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
- // we need to ensure that we report the up/down promptly.
- sync(rawEvent->when);
- break;
- }
- break;
-
- case EV_REL:
- switch (rawEvent->scanCode) {
- case REL_X:
- mAccumulator.fields |= Accumulator::FIELD_REL_X;
- mAccumulator.relX = rawEvent->value;
- break;
- case REL_Y:
- mAccumulator.fields |= Accumulator::FIELD_REL_Y;
- mAccumulator.relY = rawEvent->value;
- break;
- }
- break;
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
- }
-}
-
-void CursorInputMapper::sync(nsecs_t when) {
- uint32_t fields = mAccumulator.fields;
- if (fields == 0) {
- return; // no new state changes, so nothing to do
- }
-
- int motionEventAction;
- PointerCoords pointerCoords;
- nsecs_t downTime;
- { // acquire lock
- AutoMutex _l(mLock);
-
- bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
-
- if (downChanged) {
- if (mAccumulator.btnMouse) {
- mLocked.down = true;
- mLocked.downTime = when;
- } else {
- mLocked.down = false;
- }
- }
-
- downTime = mLocked.downTime;
- float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
- float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
-
- if (downChanged) {
- motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
- } else {
- motionEventAction = AMOTION_EVENT_ACTION_MOVE;
- }
-
- if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
- && (deltaX != 0.0f || deltaY != 0.0f)) {
- // Rotate motion based on display orientation if needed.
- // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
- int32_t orientation;
- if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
- NULL, NULL, & orientation)) {
- orientation = InputReaderPolicyInterface::ROTATION_0;
- }
-
- float temp;
- switch (orientation) {
- case InputReaderPolicyInterface::ROTATION_90:
- temp = deltaX;
- deltaX = deltaY;
- deltaY = -temp;
- break;
-
- case InputReaderPolicyInterface::ROTATION_180:
- deltaX = -deltaX;
- deltaY = -deltaY;
- break;
-
- case InputReaderPolicyInterface::ROTATION_270:
- temp = deltaX;
- deltaX = -deltaY;
- deltaY = temp;
- break;
- }
- }
-
- if (mPointerController != NULL) {
- mPointerController->move(deltaX, deltaY);
- if (downChanged) {
- mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
- }
- mPointerController->getPosition(&pointerCoords.x, &pointerCoords.y);
- } else {
- pointerCoords.x = deltaX;
- pointerCoords.y = deltaY;
- }
-
- pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
- pointerCoords.size = 0;
- pointerCoords.touchMajor = 0;
- pointerCoords.touchMinor = 0;
- pointerCoords.toolMajor = 0;
- pointerCoords.toolMinor = 0;
- pointerCoords.orientation = 0;
- } // release lock
-
- int32_t metaState = mContext->getGlobalMetaState();
- int32_t pointerId = 0;
- getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
- motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
- 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
-
- mAccumulator.clear();
-}
-
-int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
- return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
- } else {
- return AKEY_STATE_UNKNOWN;
- }
-}
-
-
-// --- TouchInputMapper ---
-
-TouchInputMapper::TouchInputMapper(InputDevice* device) :
- InputMapper(device) {
- mLocked.surfaceOrientation = -1;
- mLocked.surfaceWidth = -1;
- mLocked.surfaceHeight = -1;
-
- initializeLocked();
-}
-
-TouchInputMapper::~TouchInputMapper() {
-}
-
-uint32_t TouchInputMapper::getSources() {
- return mSources;
-}
-
-void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- // Ensure surface information is up to date so that orientation changes are
- // noticed immediately.
- configureSurfaceLocked();
-
- info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
- info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
-
- if (mLocked.orientedRanges.havePressure) {
- info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
- mLocked.orientedRanges.pressure);
- }
-
- if (mLocked.orientedRanges.haveSize) {
- info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
- mLocked.orientedRanges.size);
- }
-
- if (mLocked.orientedRanges.haveTouchSize) {
- info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
- mLocked.orientedRanges.touchMajor);
- info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
- mLocked.orientedRanges.touchMinor);
- }
-
- if (mLocked.orientedRanges.haveToolSize) {
- info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
- mLocked.orientedRanges.toolMajor);
- info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
- mLocked.orientedRanges.toolMinor);
- }
-
- if (mLocked.orientedRanges.haveOrientation) {
- info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
- mLocked.orientedRanges.orientation);
- }
- } // release lock
-}
-
-void TouchInputMapper::dump(String8& dump) {
- { // acquire lock
- AutoMutex _l(mLock);
- dump.append(INDENT2 "Touch Input Mapper:\n");
- dumpParameters(dump);
- dumpVirtualKeysLocked(dump);
- dumpRawAxes(dump);
- dumpCalibration(dump);
- dumpSurfaceLocked(dump);
- dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
- dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
- dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
- dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
- dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
- dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
- dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
- dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
- dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
- dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
- dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
- dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
- dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
- dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
- dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
- } // release lock
-}
-
-void TouchInputMapper::initializeLocked() {
- mCurrentTouch.clear();
- mLastTouch.clear();
- mDownTime = 0;
-
- for (uint32_t i = 0; i < MAX_POINTERS; i++) {
- mAveragingTouchFilter.historyStart[i] = 0;
- mAveragingTouchFilter.historyEnd[i] = 0;
- }
-
- mJumpyTouchFilter.jumpyPointsDropped = 0;
-
- mLocked.currentVirtualKey.down = false;
-
- mLocked.orientedRanges.havePressure = false;
- mLocked.orientedRanges.haveSize = false;
- mLocked.orientedRanges.haveTouchSize = false;
- mLocked.orientedRanges.haveToolSize = false;
- mLocked.orientedRanges.haveOrientation = false;
-}
-
-void TouchInputMapper::configure() {
- InputMapper::configure();
-
- // Configure basic parameters.
- configureParameters();
-
- // Configure sources.
- switch (mParameters.deviceType) {
- case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
- mSources = AINPUT_SOURCE_TOUCHSCREEN;
- break;
- case Parameters::DEVICE_TYPE_TOUCH_PAD:
- mSources = AINPUT_SOURCE_TOUCHPAD;
- break;
- default:
- assert(false);
- }
-
- // Configure absolute axis information.
- configureRawAxes();
-
- // Prepare input device calibration.
- parseCalibration();
- resolveCalibration();
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- // Configure surface dimensions and orientation.
- configureSurfaceLocked();
- } // release lock
-}
-
-void TouchInputMapper::configureParameters() {
- mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
- mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
- mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
-
- String8 deviceTypeString;
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
- if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
- deviceTypeString)) {
- if (deviceTypeString == "touchPad") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
- } else if (deviceTypeString != "touchScreen") {
- LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
- }
- }
- bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-
- mParameters.orientationAware = isTouchScreen;
- getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
-}
-
-void TouchInputMapper::dumpParameters(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
-
- switch (mParameters.deviceType) {
- case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
- dump.append(INDENT4 "DeviceType: touchScreen\n");
- break;
- case Parameters::DEVICE_TYPE_TOUCH_PAD:
- dump.append(INDENT4 "DeviceType: touchPad\n");
- break;
- default:
- assert(false);
- }
-
- dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
- mParameters.associatedDisplayId);
- dump.appendFormat(INDENT4 "OrientationAware: %s\n",
- toString(mParameters.orientationAware));
-
- dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
- toString(mParameters.useBadTouchFilter));
- dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
- toString(mParameters.useAveragingTouchFilter));
- dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
- toString(mParameters.useJumpyTouchFilter));
-}
-
-void TouchInputMapper::configureRawAxes() {
- mRawAxes.x.clear();
- mRawAxes.y.clear();
- mRawAxes.pressure.clear();
- mRawAxes.touchMajor.clear();
- mRawAxes.touchMinor.clear();
- mRawAxes.toolMajor.clear();
- mRawAxes.toolMinor.clear();
- mRawAxes.orientation.clear();
-}
-
-static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
- if (axis.valid) {
- dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
- name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
- } else {
- dump.appendFormat(INDENT4 "%s: unknown range\n", name);
- }
-}
-
-void TouchInputMapper::dumpRawAxes(String8& dump) {
- dump.append(INDENT3 "Raw Axes:\n");
- dumpAxisInfo(dump, mRawAxes.x, "X");
- dumpAxisInfo(dump, mRawAxes.y, "Y");
- dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
- dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
- dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
- dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
- dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
- dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
-}
-
-bool TouchInputMapper::configureSurfaceLocked() {
- // Update orientation and dimensions if needed.
- int32_t orientation = InputReaderPolicyInterface::ROTATION_0;
- int32_t width = mRawAxes.x.getRange();
- int32_t height = mRawAxes.y.getRange();
-
- if (mParameters.associatedDisplayId >= 0) {
- bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
- bool wantOrientation = mParameters.orientationAware;
-
- // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
- if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
- wantSize ? &width : NULL, wantSize ? &height : NULL,
- wantOrientation ? &orientation : NULL)) {
- return false;
- }
- }
-
- bool orientationChanged = mLocked.surfaceOrientation != orientation;
- if (orientationChanged) {
- mLocked.surfaceOrientation = orientation;
- }
-
- bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
- if (sizeChanged) {
- LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
- getDeviceId(), getDeviceName().string(), width, height);
-
- mLocked.surfaceWidth = width;
- mLocked.surfaceHeight = height;
-
- // Configure X and Y factors.
- if (mRawAxes.x.valid && mRawAxes.y.valid) {
- mLocked.xOrigin = mCalibration.haveXOrigin
- ? mCalibration.xOrigin
- : mRawAxes.x.minValue;
- mLocked.yOrigin = mCalibration.haveYOrigin
- ? mCalibration.yOrigin
- : mRawAxes.y.minValue;
- mLocked.xScale = mCalibration.haveXScale
- ? mCalibration.xScale
- : float(width) / mRawAxes.x.getRange();
- mLocked.yScale = mCalibration.haveYScale
- ? mCalibration.yScale
- : float(height) / mRawAxes.y.getRange();
- mLocked.xPrecision = 1.0f / mLocked.xScale;
- mLocked.yPrecision = 1.0f / mLocked.yScale;
-
- configureVirtualKeysLocked();
- } else {
- LOGW(INDENT "Touch device did not report support for X or Y axis!");
- mLocked.xOrigin = 0;
- mLocked.yOrigin = 0;
- mLocked.xScale = 1.0f;
- mLocked.yScale = 1.0f;
- mLocked.xPrecision = 1.0f;
- mLocked.yPrecision = 1.0f;
- }
-
- // Scale factor for terms that are not oriented in a particular axis.
- // If the pixels are square then xScale == yScale otherwise we fake it
- // by choosing an average.
- mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
-
- // Size of diagonal axis.
- float diagonalSize = pythag(width, height);
-
- // TouchMajor and TouchMinor factors.
- if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
- mLocked.orientedRanges.haveTouchSize = true;
- mLocked.orientedRanges.touchMajor.min = 0;
- mLocked.orientedRanges.touchMajor.max = diagonalSize;
- mLocked.orientedRanges.touchMajor.flat = 0;
- mLocked.orientedRanges.touchMajor.fuzz = 0;
- mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
- }
-
- // ToolMajor and ToolMinor factors.
- mLocked.toolSizeLinearScale = 0;
- mLocked.toolSizeLinearBias = 0;
- mLocked.toolSizeAreaScale = 0;
- mLocked.toolSizeAreaBias = 0;
- if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
- if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
- if (mCalibration.haveToolSizeLinearScale) {
- mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
- } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
- mLocked.toolSizeLinearScale = float(min(width, height))
- / mRawAxes.toolMajor.maxValue;
- }
-
- if (mCalibration.haveToolSizeLinearBias) {
- mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
- }
- } else if (mCalibration.toolSizeCalibration ==
- Calibration::TOOL_SIZE_CALIBRATION_AREA) {
- if (mCalibration.haveToolSizeLinearScale) {
- mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
- } else {
- mLocked.toolSizeLinearScale = min(width, height);
- }
-
- if (mCalibration.haveToolSizeLinearBias) {
- mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
- }
-
- if (mCalibration.haveToolSizeAreaScale) {
- mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
- } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
- mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
- }
-
- if (mCalibration.haveToolSizeAreaBias) {
- mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
- }
- }
-
- mLocked.orientedRanges.haveToolSize = true;
- mLocked.orientedRanges.toolMajor.min = 0;
- mLocked.orientedRanges.toolMajor.max = diagonalSize;
- mLocked.orientedRanges.toolMajor.flat = 0;
- mLocked.orientedRanges.toolMajor.fuzz = 0;
- mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
- }
-
- // Pressure factors.
- mLocked.pressureScale = 0;
- if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
- RawAbsoluteAxisInfo rawPressureAxis;
- switch (mCalibration.pressureSource) {
- case Calibration::PRESSURE_SOURCE_PRESSURE:
- rawPressureAxis = mRawAxes.pressure;
- break;
- case Calibration::PRESSURE_SOURCE_TOUCH:
- rawPressureAxis = mRawAxes.touchMajor;
- break;
- default:
- rawPressureAxis.clear();
- }
-
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
- || mCalibration.pressureCalibration
- == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
- if (mCalibration.havePressureScale) {
- mLocked.pressureScale = mCalibration.pressureScale;
- } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
- mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
- }
- }
-
- mLocked.orientedRanges.havePressure = true;
- mLocked.orientedRanges.pressure.min = 0;
- mLocked.orientedRanges.pressure.max = 1.0;
- mLocked.orientedRanges.pressure.flat = 0;
- mLocked.orientedRanges.pressure.fuzz = 0;
- }
-
- // Size factors.
- mLocked.sizeScale = 0;
- if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
- if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
- if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
- mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
- }
- }
-
- mLocked.orientedRanges.haveSize = true;
- mLocked.orientedRanges.size.min = 0;
- mLocked.orientedRanges.size.max = 1.0;
- mLocked.orientedRanges.size.flat = 0;
- mLocked.orientedRanges.size.fuzz = 0;
- }
-
- // Orientation
- mLocked.orientationScale = 0;
- if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
- if (mCalibration.orientationCalibration
- == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
- if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
- mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
- }
- }
-
- mLocked.orientedRanges.orientation.min = - M_PI_2;
- mLocked.orientedRanges.orientation.max = M_PI_2;
- mLocked.orientedRanges.orientation.flat = 0;
- mLocked.orientedRanges.orientation.fuzz = 0;
- }
- }
-
- if (orientationChanged || sizeChanged) {
- // Compute oriented surface dimensions, precision, and scales.
- float orientedXScale, orientedYScale;
- switch (mLocked.surfaceOrientation) {
- case InputReaderPolicyInterface::ROTATION_90:
- case InputReaderPolicyInterface::ROTATION_270:
- mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
- mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
- mLocked.orientedXPrecision = mLocked.yPrecision;
- mLocked.orientedYPrecision = mLocked.xPrecision;
- orientedXScale = mLocked.yScale;
- orientedYScale = mLocked.xScale;
- break;
- default:
- mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
- mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
- mLocked.orientedXPrecision = mLocked.xPrecision;
- mLocked.orientedYPrecision = mLocked.yPrecision;
- orientedXScale = mLocked.xScale;
- orientedYScale = mLocked.yScale;
- break;
- }
-
- // Configure position ranges.
- mLocked.orientedRanges.x.min = 0;
- mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
- mLocked.orientedRanges.x.flat = 0;
- mLocked.orientedRanges.x.fuzz = orientedXScale;
-
- mLocked.orientedRanges.y.min = 0;
- mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
- mLocked.orientedRanges.y.flat = 0;
- mLocked.orientedRanges.y.fuzz = orientedYScale;
- }
-
- return true;
-}
-
-void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
- dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
- dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
- dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
-}
-
-void TouchInputMapper::configureVirtualKeysLocked() {
- assert(mRawAxes.x.valid && mRawAxes.y.valid);
-
- Vector<VirtualKeyDefinition> virtualKeyDefinitions;
- getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
-
- mLocked.virtualKeys.clear();
-
- if (virtualKeyDefinitions.size() == 0) {
- return;
- }
-
- mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
-
- int32_t touchScreenLeft = mRawAxes.x.minValue;
- int32_t touchScreenTop = mRawAxes.y.minValue;
- int32_t touchScreenWidth = mRawAxes.x.getRange();
- int32_t touchScreenHeight = mRawAxes.y.getRange();
-
- for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
- const VirtualKeyDefinition& virtualKeyDefinition =
- virtualKeyDefinitions[i];
-
- mLocked.virtualKeys.add();
- VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
-
- virtualKey.scanCode = virtualKeyDefinition.scanCode;
- int32_t keyCode;
- uint32_t flags;
- if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
- & keyCode, & flags)) {
- LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
- virtualKey.scanCode);
- mLocked.virtualKeys.pop(); // drop the key
- continue;
- }
-
- virtualKey.keyCode = keyCode;
- virtualKey.flags = flags;
-
- // convert the key definition's display coordinates into touch coordinates for a hit box
- int32_t halfWidth = virtualKeyDefinition.width / 2;
- int32_t halfHeight = virtualKeyDefinition.height / 2;
-
- virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
- * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
- virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
- * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
- virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
- * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
- virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
- * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
-
- }
-}
-
-void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
- if (!mLocked.virtualKeys.isEmpty()) {
- dump.append(INDENT3 "Virtual Keys:\n");
-
- for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
- const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
- dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
- "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
- i, virtualKey.scanCode, virtualKey.keyCode,
- virtualKey.hitLeft, virtualKey.hitRight,
- virtualKey.hitTop, virtualKey.hitBottom);
- }
- }
-}
-
-void TouchInputMapper::parseCalibration() {
- const PropertyMap& in = getDevice()->getConfiguration();
- Calibration& out = mCalibration;
-
- // Position
- out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
- out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
- out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
- out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
-
- // Touch Size
- out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
- String8 touchSizeCalibrationString;
- if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
- if (touchSizeCalibrationString == "none") {
- out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
- } else if (touchSizeCalibrationString == "geometric") {
- out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
- } else if (touchSizeCalibrationString == "pressure") {
- out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
- } else if (touchSizeCalibrationString != "default") {
- LOGW("Invalid value for touch.touchSize.calibration: '%s'",
- touchSizeCalibrationString.string());
- }
- }
-
- // Tool Size
- out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
- String8 toolSizeCalibrationString;
- if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
- if (toolSizeCalibrationString == "none") {
- out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
- } else if (toolSizeCalibrationString == "geometric") {
- out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
- } else if (toolSizeCalibrationString == "linear") {
- out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
- } else if (toolSizeCalibrationString == "area") {
- out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
- } else if (toolSizeCalibrationString != "default") {
- LOGW("Invalid value for touch.toolSize.calibration: '%s'",
- toolSizeCalibrationString.string());
- }
- }
-
- out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
- out.toolSizeLinearScale);
- out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
- out.toolSizeLinearBias);
- out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
- out.toolSizeAreaScale);
- out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
- out.toolSizeAreaBias);
- out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
- out.toolSizeIsSummed);
-
- // Pressure
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
- String8 pressureCalibrationString;
- if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
- if (pressureCalibrationString == "none") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
- } else if (pressureCalibrationString == "physical") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
- } else if (pressureCalibrationString == "amplitude") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
- } else if (pressureCalibrationString != "default") {
- LOGW("Invalid value for touch.pressure.calibration: '%s'",
- pressureCalibrationString.string());
- }
- }
-
- out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
- String8 pressureSourceString;
- if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
- if (pressureSourceString == "pressure") {
- out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
- } else if (pressureSourceString == "touch") {
- out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
- } else if (pressureSourceString != "default") {
- LOGW("Invalid value for touch.pressure.source: '%s'",
- pressureSourceString.string());
- }
- }
-
- out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
- out.pressureScale);
-
- // Size
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
- String8 sizeCalibrationString;
- if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
- if (sizeCalibrationString == "none") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
- } else if (sizeCalibrationString == "normalized") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
- } else if (sizeCalibrationString != "default") {
- LOGW("Invalid value for touch.size.calibration: '%s'",
- sizeCalibrationString.string());
- }
- }
-
- // Orientation
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
- String8 orientationCalibrationString;
- if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
- if (orientationCalibrationString == "none") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
- } else if (orientationCalibrationString == "interpolated") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
- } else if (orientationCalibrationString != "default") {
- LOGW("Invalid value for touch.orientation.calibration: '%s'",
- orientationCalibrationString.string());
- }
- }
-}
-
-void TouchInputMapper::resolveCalibration() {
- // Pressure
- switch (mCalibration.pressureSource) {
- case Calibration::PRESSURE_SOURCE_DEFAULT:
- if (mRawAxes.pressure.valid) {
- mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
- } else if (mRawAxes.touchMajor.valid) {
- mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
- }
- break;
-
- case Calibration::PRESSURE_SOURCE_PRESSURE:
- if (! mRawAxes.pressure.valid) {
- LOGW("Calibration property touch.pressure.source is 'pressure' but "
- "the pressure axis is not available.");
- }
- break;
-
- case Calibration::PRESSURE_SOURCE_TOUCH:
- if (! mRawAxes.touchMajor.valid) {
- LOGW("Calibration property touch.pressure.source is 'touch' but "
- "the touchMajor axis is not available.");
- }
- break;
-
- default:
- break;
- }
-
- switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_DEFAULT:
- if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
- mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
- } else {
- mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
- }
- break;
-
- default:
- break;
- }
-
- // Tool Size
- switch (mCalibration.toolSizeCalibration) {
- case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
- if (mRawAxes.toolMajor.valid) {
- mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
- } else {
- mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
- }
- break;
-
- default:
- break;
- }
-
- // Touch Size
- switch (mCalibration.touchSizeCalibration) {
- case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
- if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
- && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
- mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
- } else {
- mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
- }
- break;
-
- default:
- break;
- }
-
- // Size
- switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_DEFAULT:
- if (mRawAxes.toolMajor.valid) {
- mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
- } else {
- mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
- }
- break;
-
- default:
- break;
- }
-
- // Orientation
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
- if (mRawAxes.orientation.valid) {
- mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
- } else {
- mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
- }
- break;
-
- default:
- break;
- }
-}
-
-void TouchInputMapper::dumpCalibration(String8& dump) {
- dump.append(INDENT3 "Calibration:\n");
-
- // Position
- if (mCalibration.haveXOrigin) {
- dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
- }
- if (mCalibration.haveYOrigin) {
- dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
- }
- if (mCalibration.haveXScale) {
- dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
- }
- if (mCalibration.haveYScale) {
- dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
- }
-
- // Touch Size
- switch (mCalibration.touchSizeCalibration) {
- case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.touchSize.calibration: none\n");
- break;
- case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
- dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
- break;
- case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
- dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
- break;
- default:
- assert(false);
- }
-
- // Tool Size
- switch (mCalibration.toolSizeCalibration) {
- case Calibration::TOOL_SIZE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.toolSize.calibration: none\n");
- break;
- case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
- dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
- break;
- case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
- dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
- break;
- case Calibration::TOOL_SIZE_CALIBRATION_AREA:
- dump.append(INDENT4 "touch.toolSize.calibration: area\n");
- break;
- default:
- assert(false);
- }
-
- if (mCalibration.haveToolSizeLinearScale) {
- dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
- mCalibration.toolSizeLinearScale);
- }
-
- if (mCalibration.haveToolSizeLinearBias) {
- dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
- mCalibration.toolSizeLinearBias);
- }
-
- if (mCalibration.haveToolSizeAreaScale) {
- dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
- mCalibration.toolSizeAreaScale);
- }
-
- if (mCalibration.haveToolSizeAreaBias) {
- dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
- mCalibration.toolSizeAreaBias);
- }
-
- if (mCalibration.haveToolSizeIsSummed) {
- dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
- toString(mCalibration.toolSizeIsSummed));
- }
-
- // Pressure
- switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.pressure.calibration: none\n");
- break;
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
- dump.append(INDENT4 "touch.pressure.calibration: physical\n");
- break;
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
- dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
- break;
- default:
- assert(false);
- }
-
- switch (mCalibration.pressureSource) {
- case Calibration::PRESSURE_SOURCE_PRESSURE:
- dump.append(INDENT4 "touch.pressure.source: pressure\n");
- break;
- case Calibration::PRESSURE_SOURCE_TOUCH:
- dump.append(INDENT4 "touch.pressure.source: touch\n");
- break;
- case Calibration::PRESSURE_SOURCE_DEFAULT:
- break;
- default:
- assert(false);
- }
-
- if (mCalibration.havePressureScale) {
- dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
- mCalibration.pressureScale);
- }
-
- // Size
- switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.size.calibration: none\n");
- break;
- case Calibration::SIZE_CALIBRATION_NORMALIZED:
- dump.append(INDENT4 "touch.size.calibration: normalized\n");
- break;
- default:
- assert(false);
- }
-
- // Orientation
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.orientation.calibration: none\n");
- break;
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
- dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
- break;
- default:
- assert(false);
- }
-}
-
-void TouchInputMapper::reset() {
- // Synthesize touch up event if touch is currently down.
- // This will also take care of finishing virtual key processing if needed.
- if (mLastTouch.pointerCount != 0) {
- nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- mCurrentTouch.clear();
- syncTouch(when, true);
- }
-
- { // acquire lock
- AutoMutex _l(mLock);
- initializeLocked();
- } // release lock
-
- InputMapper::reset();
-}
-
-void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
- uint32_t policyFlags = 0;
-
- // Preprocess pointer data.
-
- if (mParameters.useBadTouchFilter) {
- if (applyBadTouchFilter()) {
- havePointerIds = false;
- }
- }
-
- if (mParameters.useJumpyTouchFilter) {
- if (applyJumpyTouchFilter()) {
- havePointerIds = false;
- }
- }
-
- if (! havePointerIds) {
- calculatePointerIds();
- }
-
- TouchData temp;
- TouchData* savedTouch;
- if (mParameters.useAveragingTouchFilter) {
- temp.copyFrom(mCurrentTouch);
- savedTouch = & temp;
-
- applyAveragingTouchFilter();
- } else {
- savedTouch = & mCurrentTouch;
- }
-
- // Process touches and virtual keys.
-
- TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
- if (touchResult == DISPATCH_TOUCH) {
- dispatchTouches(when, policyFlags);
- }
-
- // Copy current touch to last touch in preparation for the next cycle.
-
- if (touchResult == DROP_STROKE) {
- mLastTouch.clear();
- } else {
- mLastTouch.copyFrom(*savedTouch);
- }
-}
-
-TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
- nsecs_t when, uint32_t policyFlags) {
- int32_t keyEventAction, keyEventFlags;
- int32_t keyCode, scanCode, downTime;
- TouchResult touchResult;
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- // Update surface size and orientation, including virtual key positions.
- if (! configureSurfaceLocked()) {
- return DROP_STROKE;
- }
-
- // Check for virtual key press.
- if (mLocked.currentVirtualKey.down) {
- if (mCurrentTouch.pointerCount == 0) {
- // Pointer went up while virtual key was down.
- mLocked.currentVirtualKey.down = false;
-#if DEBUG_VIRTUAL_KEYS
- LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
- mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
-#endif
- keyEventAction = AKEY_EVENT_ACTION_UP;
- keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
- touchResult = SKIP_TOUCH;
- goto DispatchVirtualKey;
- }
-
- if (mCurrentTouch.pointerCount == 1) {
- int32_t x = mCurrentTouch.pointers[0].x;
- int32_t y = mCurrentTouch.pointers[0].y;
- const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
- if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
- // Pointer is still within the space of the virtual key.
- return SKIP_TOUCH;
- }
- }
-
- // Pointer left virtual key area or another pointer also went down.
- // Send key cancellation and drop the stroke so subsequent motions will be
- // considered fresh downs. This is useful when the user swipes away from the
- // virtual key area into the main display surface.
- mLocked.currentVirtualKey.down = false;
-#if DEBUG_VIRTUAL_KEYS
- LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
- mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
-#endif
- keyEventAction = AKEY_EVENT_ACTION_UP;
- keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
- | AKEY_EVENT_FLAG_CANCELED;
-
- // Check whether the pointer moved inside the display area where we should
- // start a new stroke.
- int32_t x = mCurrentTouch.pointers[0].x;
- int32_t y = mCurrentTouch.pointers[0].y;
- if (isPointInsideSurfaceLocked(x, y)) {
- mLastTouch.clear();
- touchResult = DISPATCH_TOUCH;
- } else {
- touchResult = DROP_STROKE;
- }
- } else {
- if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
- // Pointer just went down. Handle off-screen touches, if needed.
- int32_t x = mCurrentTouch.pointers[0].x;
- int32_t y = mCurrentTouch.pointers[0].y;
- if (! isPointInsideSurfaceLocked(x, y)) {
- // If exactly one pointer went down, check for virtual key hit.
- // Otherwise we will drop the entire stroke.
- if (mCurrentTouch.pointerCount == 1) {
- const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
- if (virtualKey) {
- mLocked.currentVirtualKey.down = true;
- mLocked.currentVirtualKey.downTime = when;
- mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
- mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
-#if DEBUG_VIRTUAL_KEYS
- LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
- mLocked.currentVirtualKey.keyCode,
- mLocked.currentVirtualKey.scanCode);
-#endif
- keyEventAction = AKEY_EVENT_ACTION_DOWN;
- keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
- | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
- touchResult = SKIP_TOUCH;
- goto DispatchVirtualKey;
- }
- }
- return DROP_STROKE;
- }
- }
- return DISPATCH_TOUCH;
- }
-
- DispatchVirtualKey:
- // Collect remaining state needed to dispatch virtual key.
- keyCode = mLocked.currentVirtualKey.keyCode;
- scanCode = mLocked.currentVirtualKey.scanCode;
- downTime = mLocked.currentVirtualKey.downTime;
- } // release lock
-
- // Dispatch virtual key.
- int32_t metaState = mContext->getGlobalMetaState();
- policyFlags |= POLICY_FLAG_VIRTUAL;
- getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
- keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
- return touchResult;
-}
-
-void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
- uint32_t currentPointerCount = mCurrentTouch.pointerCount;
- uint32_t lastPointerCount = mLastTouch.pointerCount;
- if (currentPointerCount == 0 && lastPointerCount == 0) {
- return; // nothing to do!
- }
-
- BitSet32 currentIdBits = mCurrentTouch.idBits;
- BitSet32 lastIdBits = mLastTouch.idBits;
-
- if (currentIdBits == lastIdBits) {
- // No pointer id changes so this is a move event.
- // The dispatcher takes care of batching moves so we don't have to deal with that here.
- int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
- dispatchTouch(when, policyFlags, & mCurrentTouch,
- currentIdBits, -1, currentPointerCount, motionEventAction);
- } else {
- // There may be pointers going up and pointers going down and pointers moving
- // all at the same time.
- BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
- BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
- BitSet32 activeIdBits(lastIdBits.value);
- uint32_t pointerCount = lastPointerCount;
-
- // Produce an intermediate representation of the touch data that consists of the
- // old location of pointers that have just gone up and the new location of pointers that
- // have just moved but omits the location of pointers that have just gone down.
- TouchData interimTouch;
- interimTouch.copyFrom(mLastTouch);
-
- BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
- bool moveNeeded = false;
- while (!moveIdBits.isEmpty()) {
- uint32_t moveId = moveIdBits.firstMarkedBit();
- moveIdBits.clearBit(moveId);
-
- int32_t oldIndex = mLastTouch.idToIndex[moveId];
- int32_t newIndex = mCurrentTouch.idToIndex[moveId];
- if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
- interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
- moveNeeded = true;
- }
- }
-
- // Dispatch pointer up events using the interim pointer locations.
- while (!upIdBits.isEmpty()) {
- uint32_t upId = upIdBits.firstMarkedBit();
- upIdBits.clearBit(upId);
- BitSet32 oldActiveIdBits = activeIdBits;
- activeIdBits.clearBit(upId);
-
- int32_t motionEventAction;
- if (activeIdBits.isEmpty()) {
- motionEventAction = AMOTION_EVENT_ACTION_UP;
- } else {
- motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
- }
-
- dispatchTouch(when, policyFlags, &interimTouch,
- oldActiveIdBits, upId, pointerCount, motionEventAction);
- pointerCount -= 1;
- }
-
- // Dispatch move events if any of the remaining pointers moved from their old locations.
- // Although applications receive new locations as part of individual pointer up
- // events, they do not generally handle them except when presented in a move event.
- if (moveNeeded) {
- dispatchTouch(when, policyFlags, &mCurrentTouch,
- activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
- }
-
- // Dispatch pointer down events using the new pointer locations.
- while (!downIdBits.isEmpty()) {
- uint32_t downId = downIdBits.firstMarkedBit();
- downIdBits.clearBit(downId);
- BitSet32 oldActiveIdBits = activeIdBits;
- activeIdBits.markBit(downId);
-
- int32_t motionEventAction;
- if (oldActiveIdBits.isEmpty()) {
- motionEventAction = AMOTION_EVENT_ACTION_DOWN;
- mDownTime = when;
- } else {
- motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
- }
-
- pointerCount += 1;
- dispatchTouch(when, policyFlags, &mCurrentTouch,
- activeIdBits, downId, pointerCount, motionEventAction);
- }
- }
-}
-
-void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
- TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
- int32_t motionEventAction) {
- int32_t pointerIds[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- int32_t motionEventEdgeFlags = 0;
- float xPrecision, yPrecision;
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- // Walk through the the active pointers and map touch screen coordinates (TouchData) into
- // display coordinates (PointerCoords) and adjust for display orientation.
- for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
- uint32_t id = idBits.firstMarkedBit();
- idBits.clearBit(id);
- uint32_t inIndex = touch->idToIndex[id];
-
- const PointerData& in = touch->pointers[inIndex];
-
- // X and Y
- float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
- float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
-
- // ToolMajor and ToolMinor
- float toolMajor, toolMinor;
- switch (mCalibration.toolSizeCalibration) {
- case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
- toolMajor = in.toolMajor * mLocked.geometricScale;
- if (mRawAxes.toolMinor.valid) {
- toolMinor = in.toolMinor * mLocked.geometricScale;
- } else {
- toolMinor = toolMajor;
- }
- break;
- case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
- toolMajor = in.toolMajor != 0
- ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
- : 0;
- if (mRawAxes.toolMinor.valid) {
- toolMinor = in.toolMinor != 0
- ? in.toolMinor * mLocked.toolSizeLinearScale
- + mLocked.toolSizeLinearBias
- : 0;
- } else {
- toolMinor = toolMajor;
- }
- break;
- case Calibration::TOOL_SIZE_CALIBRATION_AREA:
- if (in.toolMajor != 0) {
- float diameter = sqrtf(in.toolMajor
- * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
- toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
- } else {
- toolMajor = 0;
- }
- toolMinor = toolMajor;
- break;
- default:
- toolMajor = 0;
- toolMinor = 0;
- break;
- }
-
- if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
- toolMajor /= pointerCount;
- toolMinor /= pointerCount;
- }
-
- // Pressure
- float rawPressure;
- switch (mCalibration.pressureSource) {
- case Calibration::PRESSURE_SOURCE_PRESSURE:
- rawPressure = in.pressure;
- break;
- case Calibration::PRESSURE_SOURCE_TOUCH:
- rawPressure = in.touchMajor;
- break;
- default:
- rawPressure = 0;
- }
-
- float pressure;
- switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
- pressure = rawPressure * mLocked.pressureScale;
- break;
- default:
- pressure = 1;
- break;
- }
-
- // TouchMajor and TouchMinor
- float touchMajor, touchMinor;
- switch (mCalibration.touchSizeCalibration) {
- case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
- touchMajor = in.touchMajor * mLocked.geometricScale;
- if (mRawAxes.touchMinor.valid) {
- touchMinor = in.touchMinor * mLocked.geometricScale;
- } else {
- touchMinor = touchMajor;
- }
- break;
- case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
- touchMajor = toolMajor * pressure;
- touchMinor = toolMinor * pressure;
- break;
- default:
- touchMajor = 0;
- touchMinor = 0;
- break;
- }
-
- if (touchMajor > toolMajor) {
- touchMajor = toolMajor;
- }
- if (touchMinor > toolMinor) {
- touchMinor = toolMinor;
- }
-
- // Size
- float size;
- switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_NORMALIZED: {
- float rawSize = mRawAxes.toolMinor.valid
- ? avg(in.toolMajor, in.toolMinor)
- : in.toolMajor;
- size = rawSize * mLocked.sizeScale;
- break;
- }
- default:
- size = 0;
- break;
- }
-
- // Orientation
- float orientation;
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
- orientation = in.orientation * mLocked.orientationScale;
- break;
- default:
- orientation = 0;
- }
-
- // Adjust coords for orientation.
- switch (mLocked.surfaceOrientation) {
- case InputReaderPolicyInterface::ROTATION_90: {
- float xTemp = x;
- x = y;
- y = mLocked.surfaceWidth - xTemp;
- orientation -= M_PI_2;
- if (orientation < - M_PI_2) {
- orientation += M_PI;
- }
- break;
- }
- case InputReaderPolicyInterface::ROTATION_180: {
- x = mLocked.surfaceWidth - x;
- y = mLocked.surfaceHeight - y;
- orientation = - orientation;
- break;
- }
- case InputReaderPolicyInterface::ROTATION_270: {
- float xTemp = x;
- x = mLocked.surfaceHeight - y;
- y = xTemp;
- orientation += M_PI_2;
- if (orientation > M_PI_2) {
- orientation -= M_PI;
- }
- break;
- }
- }
-
- // Write output coords.
- PointerCoords& out = pointerCoords[outIndex];
- out.x = x;
- out.y = y;
- out.pressure = pressure;
- out.size = size;
- out.touchMajor = touchMajor;
- out.touchMinor = touchMinor;
- out.toolMajor = toolMajor;
- out.toolMinor = toolMinor;
- out.orientation = orientation;
-
- pointerIds[outIndex] = int32_t(id);
-
- if (id == changedId) {
- motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- }
- }
-
- // Check edge flags by looking only at the first pointer since the flags are
- // global to the event.
- if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
- if (pointerCoords[0].x <= 0) {
- motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
- } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
- motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
- }
- if (pointerCoords[0].y <= 0) {
- motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
- } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
- motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
- }
- }
-
- xPrecision = mLocked.orientedXPrecision;
- yPrecision = mLocked.orientedYPrecision;
- } // release lock
-
- getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
- motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
- pointerCount, pointerIds, pointerCoords,
- xPrecision, yPrecision, mDownTime);
-}
-
-bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
- if (mRawAxes.x.valid && mRawAxes.y.valid) {
- return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
- && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
- }
- return true;
-}
-
-const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
- int32_t x, int32_t y) {
- size_t numVirtualKeys = mLocked.virtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-
-#if DEBUG_VIRTUAL_KEYS
- LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
- "left=%d, top=%d, right=%d, bottom=%d",
- x, y,
- virtualKey.keyCode, virtualKey.scanCode,
- virtualKey.hitLeft, virtualKey.hitTop,
- virtualKey.hitRight, virtualKey.hitBottom);
-#endif
-
- if (virtualKey.isHit(x, y)) {
- return & virtualKey;
- }
- }
-
- return NULL;
-}
-
-void TouchInputMapper::calculatePointerIds() {
- uint32_t currentPointerCount = mCurrentTouch.pointerCount;
- uint32_t lastPointerCount = mLastTouch.pointerCount;
-
- if (currentPointerCount == 0) {
- // No pointers to assign.
- mCurrentTouch.idBits.clear();
- } else if (lastPointerCount == 0) {
- // All pointers are new.
- mCurrentTouch.idBits.clear();
- for (uint32_t i = 0; i < currentPointerCount; i++) {
- mCurrentTouch.pointers[i].id = i;
- mCurrentTouch.idToIndex[i] = i;
- mCurrentTouch.idBits.markBit(i);
- }
- } else if (currentPointerCount == 1 && lastPointerCount == 1) {
- // Only one pointer and no change in count so it must have the same id as before.
- uint32_t id = mLastTouch.pointers[0].id;
- mCurrentTouch.pointers[0].id = id;
- mCurrentTouch.idToIndex[id] = 0;
- mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
- } else {
- // General case.
- // We build a heap of squared euclidean distances between current and last pointers
- // associated with the current and last pointer indices. Then, we find the best
- // match (by distance) for each current pointer.
- PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
-
- uint32_t heapSize = 0;
- for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
- currentPointerIndex++) {
- for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
- lastPointerIndex++) {
- int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
- - mLastTouch.pointers[lastPointerIndex].x;
- int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
- - mLastTouch.pointers[lastPointerIndex].y;
-
- uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
- // Insert new element into the heap (sift up).
- heap[heapSize].currentPointerIndex = currentPointerIndex;
- heap[heapSize].lastPointerIndex = lastPointerIndex;
- heap[heapSize].distance = distance;
- heapSize += 1;
- }
- }
-
- // Heapify
- for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
- startIndex -= 1;
- for (uint32_t parentIndex = startIndex; ;) {
- uint32_t childIndex = parentIndex * 2 + 1;
- if (childIndex >= heapSize) {
- break;
- }
-
- if (childIndex + 1 < heapSize
- && heap[childIndex + 1].distance < heap[childIndex].distance) {
- childIndex += 1;
- }
-
- if (heap[parentIndex].distance <= heap[childIndex].distance) {
- break;
- }
-
- swap(heap[parentIndex], heap[childIndex]);
- parentIndex = childIndex;
- }
- }
-
-#if DEBUG_POINTER_ASSIGNMENT
- LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
- i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
- heap[i].distance);
- }
-#endif
-
- // Pull matches out by increasing order of distance.
- // To avoid reassigning pointers that have already been matched, the loop keeps track
- // of which last and current pointers have been matched using the matchedXXXBits variables.
- // It also tracks the used pointer id bits.
- BitSet32 matchedLastBits(0);
- BitSet32 matchedCurrentBits(0);
- BitSet32 usedIdBits(0);
- bool first = true;
- for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
- for (;;) {
- if (first) {
- // The first time through the loop, we just consume the root element of
- // the heap (the one with smallest distance).
- first = false;
- } else {
- // Previous iterations consumed the root element of the heap.
- // Pop root element off of the heap (sift down).
- heapSize -= 1;
- assert(heapSize > 0);
-
- // Sift down.
- heap[0] = heap[heapSize];
- for (uint32_t parentIndex = 0; ;) {
- uint32_t childIndex = parentIndex * 2 + 1;
- if (childIndex >= heapSize) {
- break;
- }
-
- if (childIndex + 1 < heapSize
- && heap[childIndex + 1].distance < heap[childIndex].distance) {
- childIndex += 1;
- }
-
- if (heap[parentIndex].distance <= heap[childIndex].distance) {
- break;
- }
-
- swap(heap[parentIndex], heap[childIndex]);
- parentIndex = childIndex;
- }
-
-#if DEBUG_POINTER_ASSIGNMENT
- LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
- i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
- heap[i].distance);
- }
-#endif
- }
-
- uint32_t currentPointerIndex = heap[0].currentPointerIndex;
- if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
-
- uint32_t lastPointerIndex = heap[0].lastPointerIndex;
- if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
-
- matchedCurrentBits.markBit(currentPointerIndex);
- matchedLastBits.markBit(lastPointerIndex);
-
- uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
- mCurrentTouch.pointers[currentPointerIndex].id = id;
- mCurrentTouch.idToIndex[id] = currentPointerIndex;
- usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
- LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
- lastPointerIndex, currentPointerIndex, id, heap[0].distance);
-#endif
- break;
- }
- }
-
- // Assign fresh ids to new pointers.
- if (currentPointerCount > lastPointerCount) {
- for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
- uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
- uint32_t id = usedIdBits.firstUnmarkedBit();
-
- mCurrentTouch.pointers[currentPointerIndex].id = id;
- mCurrentTouch.idToIndex[id] = currentPointerIndex;
- usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
- LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
- currentPointerIndex, id);
-#endif
-
- if (--i == 0) break; // done
- matchedCurrentBits.markBit(currentPointerIndex);
- }
- }
-
- // Fix id bits.
- mCurrentTouch.idBits = usedIdBits;
- }
-}
-
-/* Special hack for devices that have bad screen data: if one of the
- * points has moved more than a screen height from the last position,
- * then drop it. */
-bool TouchInputMapper::applyBadTouchFilter() {
- // This hack requires valid axis parameters.
- if (! mRawAxes.y.valid) {
- return false;
- }
-
- uint32_t pointerCount = mCurrentTouch.pointerCount;
-
- // Nothing to do if there are no points.
- if (pointerCount == 0) {
- return false;
- }
-
- // Don't do anything if a finger is going down or up. We run
- // here before assigning pointer IDs, so there isn't a good
- // way to do per-finger matching.
- if (pointerCount != mLastTouch.pointerCount) {
- return false;
- }
-
- // We consider a single movement across more than a 7/16 of
- // the long size of the screen to be bad. This was a magic value
- // determined by looking at the maximum distance it is feasible
- // to actually move in one sample.
- int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
-
- // XXX The original code in InputDevice.java included commented out
- // code for testing the X axis. Note that when we drop a point
- // we don't actually restore the old X either. Strange.
- // The old code also tries to track when bad points were previously
- // detected but it turns out that due to the placement of a "break"
- // at the end of the loop, we never set mDroppedBadPoint to true
- // so it is effectively dead code.
- // Need to figure out if the old code is busted or just overcomplicated
- // but working as intended.
-
- // Look through all new points and see if any are farther than
- // acceptable from all previous points.
- for (uint32_t i = pointerCount; i-- > 0; ) {
- int32_t y = mCurrentTouch.pointers[i].y;
- int32_t closestY = INT_MAX;
- int32_t closestDeltaY = 0;
-
-#if DEBUG_HACKS
- LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
-#endif
-
- for (uint32_t j = pointerCount; j-- > 0; ) {
- int32_t lastY = mLastTouch.pointers[j].y;
- int32_t deltaY = abs(y - lastY);
-
-#if DEBUG_HACKS
- LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
- j, lastY, deltaY);
-#endif
-
- if (deltaY < maxDeltaY) {
- goto SkipSufficientlyClosePoint;
- }
- if (deltaY < closestDeltaY) {
- closestDeltaY = deltaY;
- closestY = lastY;
- }
- }
-
- // Must not have found a close enough match.
-#if DEBUG_HACKS
- LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
- i, y, closestY, closestDeltaY, maxDeltaY);
-#endif
-
- mCurrentTouch.pointers[i].y = closestY;
- return true; // XXX original code only corrects one point
-
- SkipSufficientlyClosePoint: ;
- }
-
- // No change.
- return false;
-}
-
-/* Special hack for devices that have bad screen data: drop points where
- * the coordinate value for one axis has jumped to the other pointer's location.
- */
-bool TouchInputMapper::applyJumpyTouchFilter() {
- // This hack requires valid axis parameters.
- if (! mRawAxes.y.valid) {
- return false;
- }
-
- uint32_t pointerCount = mCurrentTouch.pointerCount;
- if (mLastTouch.pointerCount != pointerCount) {
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
- mLastTouch.pointerCount, pointerCount);
- for (uint32_t i = 0; i < pointerCount; i++) {
- LOGD(" Pointer %d (%d, %d)", i,
- mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
- }
-#endif
-
- if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
- if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
- // Just drop the first few events going from 1 to 2 pointers.
- // They're bad often enough that they're not worth considering.
- mCurrentTouch.pointerCount = 1;
- mJumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Pointer 2 dropped");
-#endif
- return true;
- } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
- // The event when we go from 2 -> 1 tends to be messed up too
- mCurrentTouch.pointerCount = 2;
- mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
- mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
- mJumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
- for (int32_t i = 0; i < 2; i++) {
- LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
- mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
- }
-#endif
- return true;
- }
- }
- // Reset jumpy points dropped on other transitions or if limit exceeded.
- mJumpyTouchFilter.jumpyPointsDropped = 0;
-
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Transition - drop limit reset");
-#endif
- return false;
- }
-
- // We have the same number of pointers as last time.
- // A 'jumpy' point is one where the coordinate value for one axis
- // has jumped to the other pointer's location. No need to do anything
- // else if we only have one pointer.
- if (pointerCount < 2) {
- return false;
- }
-
- if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
- int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
-
- // We only replace the single worst jumpy point as characterized by pointer distance
- // in a single axis.
- int32_t badPointerIndex = -1;
- int32_t badPointerReplacementIndex = -1;
- int32_t badPointerDistance = INT_MIN; // distance to be corrected
-
- for (uint32_t i = pointerCount; i-- > 0; ) {
- int32_t x = mCurrentTouch.pointers[i].x;
- int32_t y = mCurrentTouch.pointers[i].y;
-
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
-#endif
-
- // Check if a touch point is too close to another's coordinates
- bool dropX = false, dropY = false;
- for (uint32_t j = 0; j < pointerCount; j++) {
- if (i == j) {
- continue;
- }
-
- if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
- dropX = true;
- break;
- }
-
- if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
- dropY = true;
- break;
- }
- }
- if (! dropX && ! dropY) {
- continue; // not jumpy
- }
-
- // Find a replacement candidate by comparing with older points on the
- // complementary (non-jumpy) axis.
- int32_t distance = INT_MIN; // distance to be corrected
- int32_t replacementIndex = -1;
-
- if (dropX) {
- // X looks too close. Find an older replacement point with a close Y.
- int32_t smallestDeltaY = INT_MAX;
- for (uint32_t j = 0; j < pointerCount; j++) {
- int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
- if (deltaY < smallestDeltaY) {
- smallestDeltaY = deltaY;
- replacementIndex = j;
- }
- }
- distance = abs(x - mLastTouch.pointers[replacementIndex].x);
- } else {
- // Y looks too close. Find an older replacement point with a close X.
- int32_t smallestDeltaX = INT_MAX;
- for (uint32_t j = 0; j < pointerCount; j++) {
- int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
- if (deltaX < smallestDeltaX) {
- smallestDeltaX = deltaX;
- replacementIndex = j;
- }
- }
- distance = abs(y - mLastTouch.pointers[replacementIndex].y);
- }
-
- // If replacing this pointer would correct a worse error than the previous ones
- // considered, then use this replacement instead.
- if (distance > badPointerDistance) {
- badPointerIndex = i;
- badPointerReplacementIndex = replacementIndex;
- badPointerDistance = distance;
- }
- }
-
- // Correct the jumpy pointer if one was found.
- if (badPointerIndex >= 0) {
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
- badPointerIndex,
- mLastTouch.pointers[badPointerReplacementIndex].x,
- mLastTouch.pointers[badPointerReplacementIndex].y);
-#endif
-
- mCurrentTouch.pointers[badPointerIndex].x =
- mLastTouch.pointers[badPointerReplacementIndex].x;
- mCurrentTouch.pointers[badPointerIndex].y =
- mLastTouch.pointers[badPointerReplacementIndex].y;
- mJumpyTouchFilter.jumpyPointsDropped += 1;
- return true;
- }
- }
-
- mJumpyTouchFilter.jumpyPointsDropped = 0;
- return false;
-}
-
-/* Special hack for devices that have bad screen data: aggregate and
- * compute averages of the coordinate data, to reduce the amount of
- * jitter seen by applications. */
-void TouchInputMapper::applyAveragingTouchFilter() {
- for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
- uint32_t id = mCurrentTouch.pointers[currentIndex].id;
- int32_t x = mCurrentTouch.pointers[currentIndex].x;
- int32_t y = mCurrentTouch.pointers[currentIndex].y;
- int32_t pressure;
- switch (mCalibration.pressureSource) {
- case Calibration::PRESSURE_SOURCE_PRESSURE:
- pressure = mCurrentTouch.pointers[currentIndex].pressure;
- break;
- case Calibration::PRESSURE_SOURCE_TOUCH:
- pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
- break;
- default:
- pressure = 1;
- break;
- }
-
- if (mLastTouch.idBits.hasBit(id)) {
- // Pointer was down before and is still down now.
- // Compute average over history trace.
- uint32_t start = mAveragingTouchFilter.historyStart[id];
- uint32_t end = mAveragingTouchFilter.historyEnd[id];
-
- int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
- int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
- uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
-#if DEBUG_HACKS
- LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
- id, distance);
-#endif
-
- if (distance < AVERAGING_DISTANCE_LIMIT) {
- // Increment end index in preparation for recording new historical data.
- end += 1;
- if (end > AVERAGING_HISTORY_SIZE) {
- end = 0;
- }
-
- // If the end index has looped back to the start index then we have filled
- // the historical trace up to the desired size so we drop the historical
- // data at the start of the trace.
- if (end == start) {
- start += 1;
- if (start > AVERAGING_HISTORY_SIZE) {
- start = 0;
- }
- }
-
- // Add the raw data to the historical trace.
- mAveragingTouchFilter.historyStart[id] = start;
- mAveragingTouchFilter.historyEnd[id] = end;
- mAveragingTouchFilter.historyData[end].pointers[id].x = x;
- mAveragingTouchFilter.historyData[end].pointers[id].y = y;
- mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
-
- // Average over all historical positions in the trace by total pressure.
- int32_t averagedX = 0;
- int32_t averagedY = 0;
- int32_t totalPressure = 0;
- for (;;) {
- int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
- int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
- int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
- .pointers[id].pressure;
-
- averagedX += historicalX * historicalPressure;
- averagedY += historicalY * historicalPressure;
- totalPressure += historicalPressure;
-
- if (start == end) {
- break;
- }
-
- start += 1;
- if (start > AVERAGING_HISTORY_SIZE) {
- start = 0;
- }
- }
-
- if (totalPressure != 0) {
- averagedX /= totalPressure;
- averagedY /= totalPressure;
-
-#if DEBUG_HACKS
- LOGD("AveragingTouchFilter: Pointer id %d - "
- "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
- averagedX, averagedY);
-#endif
-
- mCurrentTouch.pointers[currentIndex].x = averagedX;
- mCurrentTouch.pointers[currentIndex].y = averagedY;
- }
- } else {
-#if DEBUG_HACKS
- LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
-#endif
- }
- } else {
-#if DEBUG_HACKS
- LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
-#endif
- }
-
- // Reset pointer history.
- mAveragingTouchFilter.historyStart[id] = 0;
- mAveragingTouchFilter.historyEnd[id] = 0;
- mAveragingTouchFilter.historyData[0].pointers[id].x = x;
- mAveragingTouchFilter.historyData[0].pointers[id].y = y;
- mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
- }
-}
-
-int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
- return AKEY_STATE_VIRTUAL;
- }
-
- size_t numVirtualKeys = mLocked.virtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mLocked.virtualKeys[i];
- if (virtualKey.keyCode == keyCode) {
- return AKEY_STATE_UP;
- }
- }
- } // release lock
-
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
- return AKEY_STATE_VIRTUAL;
- }
-
- size_t numVirtualKeys = mLocked.virtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mLocked.virtualKeys[i];
- if (virtualKey.scanCode == scanCode) {
- return AKEY_STATE_UP;
- }
- }
- } // release lock
-
- return AKEY_STATE_UNKNOWN;
-}
-
-bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- { // acquire lock
- AutoMutex _l(mLock);
-
- size_t numVirtualKeys = mLocked.virtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-
- for (size_t i = 0; i < numCodes; i++) {
- if (virtualKey.keyCode == keyCodes[i]) {
- outFlags[i] = 1;
- }
- }
- }
- } // release lock
-
- return true;
-}
-
-
-// --- SingleTouchInputMapper ---
-
-SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
- TouchInputMapper(device) {
- initialize();
-}
-
-SingleTouchInputMapper::~SingleTouchInputMapper() {
-}
-
-void SingleTouchInputMapper::initialize() {
- mAccumulator.clear();
-
- mDown = false;
- mX = 0;
- mY = 0;
- mPressure = 0; // default to 0 for devices that don't report pressure
- mToolWidth = 0; // default to 0 for devices that don't report tool width
-}
-
-void SingleTouchInputMapper::reset() {
- TouchInputMapper::reset();
-
- initialize();
- }
-
-void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY:
- switch (rawEvent->scanCode) {
- case BTN_TOUCH:
- mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
- mAccumulator.btnTouch = rawEvent->value != 0;
- // Don't sync immediately. Wait until the next SYN_REPORT since we might
- // not have received valid position information yet. This logic assumes that
- // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
- break;
- }
- break;
-
- case EV_ABS:
- switch (rawEvent->scanCode) {
- case ABS_X:
- mAccumulator.fields |= Accumulator::FIELD_ABS_X;
- mAccumulator.absX = rawEvent->value;
- break;
- case ABS_Y:
- mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
- mAccumulator.absY = rawEvent->value;
- break;
- case ABS_PRESSURE:
- mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
- mAccumulator.absPressure = rawEvent->value;
- break;
- case ABS_TOOL_WIDTH:
- mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
- mAccumulator.absToolWidth = rawEvent->value;
- break;
- }
- break;
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
- }
-}
-
-void SingleTouchInputMapper::sync(nsecs_t when) {
- uint32_t fields = mAccumulator.fields;
- if (fields == 0) {
- return; // no new state changes, so nothing to do
- }
-
- if (fields & Accumulator::FIELD_BTN_TOUCH) {
- mDown = mAccumulator.btnTouch;
- }
-
- if (fields & Accumulator::FIELD_ABS_X) {
- mX = mAccumulator.absX;
- }
-
- if (fields & Accumulator::FIELD_ABS_Y) {
- mY = mAccumulator.absY;
- }
-
- if (fields & Accumulator::FIELD_ABS_PRESSURE) {
- mPressure = mAccumulator.absPressure;
- }
-
- if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
- mToolWidth = mAccumulator.absToolWidth;
- }
-
- mCurrentTouch.clear();
-
- if (mDown) {
- mCurrentTouch.pointerCount = 1;
- mCurrentTouch.pointers[0].id = 0;
- mCurrentTouch.pointers[0].x = mX;
- mCurrentTouch.pointers[0].y = mY;
- mCurrentTouch.pointers[0].pressure = mPressure;
- mCurrentTouch.pointers[0].touchMajor = 0;
- mCurrentTouch.pointers[0].touchMinor = 0;
- mCurrentTouch.pointers[0].toolMajor = mToolWidth;
- mCurrentTouch.pointers[0].toolMinor = mToolWidth;
- mCurrentTouch.pointers[0].orientation = 0;
- mCurrentTouch.idToIndex[0] = 0;
- mCurrentTouch.idBits.markBit(0);
- }
-
- syncTouch(when, true);
-
- mAccumulator.clear();
-}
-
-void SingleTouchInputMapper::configureRawAxes() {
- TouchInputMapper::configureRawAxes();
-
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
-}
-
-
-// --- MultiTouchInputMapper ---
-
-MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
- TouchInputMapper(device) {
- initialize();
-}
-
-MultiTouchInputMapper::~MultiTouchInputMapper() {
-}
-
-void MultiTouchInputMapper::initialize() {
- mAccumulator.clear();
-}
-
-void MultiTouchInputMapper::reset() {
- TouchInputMapper::reset();
-
- initialize();
-}
-
-void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_ABS: {
- uint32_t pointerIndex = mAccumulator.pointerCount;
- Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
-
- switch (rawEvent->scanCode) {
- case ABS_MT_POSITION_X:
- pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
- pointer->absMTPositionX = rawEvent->value;
- break;
- case ABS_MT_POSITION_Y:
- pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
- pointer->absMTPositionY = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MAJOR:
- pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
- pointer->absMTTouchMajor = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MINOR:
- pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
- pointer->absMTTouchMinor = rawEvent->value;
- break;
- case ABS_MT_WIDTH_MAJOR:
- pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
- pointer->absMTWidthMajor = rawEvent->value;
- break;
- case ABS_MT_WIDTH_MINOR:
- pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
- pointer->absMTWidthMinor = rawEvent->value;
- break;
- case ABS_MT_ORIENTATION:
- pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
- pointer->absMTOrientation = rawEvent->value;
- break;
- case ABS_MT_TRACKING_ID:
- pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
- pointer->absMTTrackingId = rawEvent->value;
- break;
- case ABS_MT_PRESSURE:
- pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
- pointer->absMTPressure = rawEvent->value;
- break;
- }
- break;
- }
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_MT_REPORT: {
- // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
- uint32_t pointerIndex = mAccumulator.pointerCount;
-
- if (mAccumulator.pointers[pointerIndex].fields) {
- if (pointerIndex == MAX_POINTERS) {
- LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
- MAX_POINTERS);
- } else {
- pointerIndex += 1;
- mAccumulator.pointerCount = pointerIndex;
- }
- }
-
- mAccumulator.pointers[pointerIndex].clear();
- break;
- }
-
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
- }
-}
-
-void MultiTouchInputMapper::sync(nsecs_t when) {
- static const uint32_t REQUIRED_FIELDS =
- Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
-
- uint32_t inCount = mAccumulator.pointerCount;
- uint32_t outCount = 0;
- bool havePointerIds = true;
-
- mCurrentTouch.clear();
-
- for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
- const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
- uint32_t fields = inPointer.fields;
-
- if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
- // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
- // Drop this finger.
- continue;
- }
-
- PointerData& outPointer = mCurrentTouch.pointers[outCount];
- outPointer.x = inPointer.absMTPositionX;
- outPointer.y = inPointer.absMTPositionY;
-
- if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
- if (inPointer.absMTPressure <= 0) {
- // Some devices send sync packets with X / Y but with a 0 pressure to indicate
- // a pointer going up. Drop this finger.
- continue;
- }
- outPointer.pressure = inPointer.absMTPressure;
- } else {
- // Default pressure to 0 if absent.
- outPointer.pressure = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
- if (inPointer.absMTTouchMajor <= 0) {
- // Some devices send sync packets with X / Y but with a 0 touch major to indicate
- // a pointer going up. Drop this finger.
- continue;
- }
- outPointer.touchMajor = inPointer.absMTTouchMajor;
- } else {
- // Default touch area to 0 if absent.
- outPointer.touchMajor = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
- outPointer.touchMinor = inPointer.absMTTouchMinor;
- } else {
- // Assume touch area is circular.
- outPointer.touchMinor = outPointer.touchMajor;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
- outPointer.toolMajor = inPointer.absMTWidthMajor;
- } else {
- // Default tool area to 0 if absent.
- outPointer.toolMajor = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
- outPointer.toolMinor = inPointer.absMTWidthMinor;
- } else {
- // Assume tool area is circular.
- outPointer.toolMinor = outPointer.toolMajor;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
- outPointer.orientation = inPointer.absMTOrientation;
- } else {
- // Default orientation to vertical if absent.
- outPointer.orientation = 0;
- }
-
- // Assign pointer id using tracking id if available.
- if (havePointerIds) {
- if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
- uint32_t id = uint32_t(inPointer.absMTTrackingId);
-
- if (id > MAX_POINTER_ID) {
-#if DEBUG_POINTERS
- LOGD("Pointers: Ignoring driver provided pointer id %d because "
- "it is larger than max supported id %d",
- id, MAX_POINTER_ID);
-#endif
- havePointerIds = false;
- }
- else {
- outPointer.id = id;
- mCurrentTouch.idToIndex[id] = outCount;
- mCurrentTouch.idBits.markBit(id);
- }
- } else {
- havePointerIds = false;
- }
- }
-
- outCount += 1;
- }
-
- mCurrentTouch.pointerCount = outCount;
-
- syncTouch(when, havePointerIds);
-
- mAccumulator.clear();
-}
-
-void MultiTouchInputMapper::configureRawAxes() {
- TouchInputMapper::configureRawAxes();
-
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
-}
-
-
-} // namespace android
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index aa017b9..580d73c 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -7,8 +7,6 @@ ifneq ($(TARGET_SIMULATOR),true)
# Build the unit tests.
test_src_files := \
InputChannel_test.cpp \
- InputReader_test.cpp \
- InputDispatcher_test.cpp \
InputPublisherAndConsumer_test.cpp
shared_libraries := \
diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp
deleted file mode 100644
index 7e17c57..0000000
--- a/libs/ui/tests/InputDispatcher_test.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-
-#include <ui/InputDispatcher.h>
-#include <gtest/gtest.h>
-#include <linux/input.h>
-
-namespace android {
-
-// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
-
-// An arbitrary device id.
-static const int32_t DEVICE_ID = 1;
-
-// An arbitrary injector pid / uid pair that has permission to inject events.
-static const int32_t INJECTOR_PID = 999;
-static const int32_t INJECTOR_UID = 1001;
-
-
-// --- FakeInputDispatcherPolicy ---
-
-class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
-protected:
- virtual ~FakeInputDispatcherPolicy() {
- }
-
-public:
- FakeInputDispatcherPolicy() {
- }
-
-private:
- virtual void notifyConfigurationChanged(nsecs_t when) {
- }
-
- virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel) {
- return 0;
- }
-
- virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
- }
-
- virtual nsecs_t getKeyRepeatTimeout() {
- return 500 * 1000000LL;
- }
-
- virtual nsecs_t getKeyRepeatDelay() {
- return 50 * 1000000LL;
- }
-
- virtual int32_t getMaxEventsPerSecond() {
- return 60;
- }
-
- virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
- }
-
- virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
- }
-
- virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
- const KeyEvent* keyEvent, uint32_t policyFlags) {
- return false;
- }
-
- virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
- const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
- return false;
- }
-
- virtual void notifySwitch(nsecs_t when,
- int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
- }
-
- virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
- }
-
- virtual bool checkInjectEventsPermissionNonReentrant(
- int32_t injectorPid, int32_t injectorUid) {
- return false;
- }
-};
-
-
-// --- InputDispatcherTest ---
-
-class InputDispatcherTest : public testing::Test {
-protected:
- sp<FakeInputDispatcherPolicy> mFakePolicy;
- sp<InputDispatcher> mDispatcher;
-
- virtual void SetUp() {
- mFakePolicy = new FakeInputDispatcherPolicy();
- mDispatcher = new InputDispatcher(mFakePolicy);
- }
-
- virtual void TearDown() {
- mFakePolicy.clear();
- mDispatcher.clear();
- }
-};
-
-
-TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
- KeyEvent event;
-
- // Rejects undefined key actions.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
- /*action*/ -1, 0,
- AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject key events with undefined action.";
-
- // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
- AKEY_EVENT_ACTION_MULTIPLE, 0,
- AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject key events with ACTION_MULTIPLE.";
-}
-
-TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
- MotionEvent event;
- int32_t pointerIds[MAX_POINTERS + 1];
- PointerCoords pointerCoords[MAX_POINTERS + 1];
- for (int i = 0; i <= MAX_POINTERS; i++) {
- pointerIds[i] = i;
- }
-
- // Rejects undefined motion actions.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with undefined action.";
-
- // Rejects pointer down with invalid index.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with pointer down index too large.";
-
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with pointer down index too small.";
-
- // Rejects pointer up with invalid index.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with pointer up index too large.";
-
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with pointer up index too small.";
-
- // Rejects motion events with invalid number of pointers.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 0, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with 0 pointers.";
-
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with more than MAX_POINTERS pointers.";
-
- // Rejects motion events with invalid pointer ids.
- pointerIds[0] = -1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with pointer ids less than 0.";
-
- pointerIds[0] = MAX_POINTER_ID + 1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
-
- // Rejects motion events with duplicate pointer ids.
- pointerIds[0] = 1;
- pointerIds[1] = 1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 2, pointerIds, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
- << "Should reject motion events with duplicate pointer ids.";
-}
-
-} // namespace android
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
deleted file mode 100644
index 50d3383..0000000
--- a/libs/ui/tests/InputReader_test.cpp
+++ /dev/null
@@ -1,3637 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-
-#include <ui/InputReader.h>
-#include <utils/List.h>
-#include <gtest/gtest.h>
-#include <math.h>
-
-namespace android {
-
-// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
-
-// Arbitrary display properties.
-static const int32_t DISPLAY_ID = 0;
-static const int32_t DISPLAY_WIDTH = 480;
-static const int32_t DISPLAY_HEIGHT = 800;
-
-// Error tolerance for floating point assertions.
-static const float EPSILON = 0.001f;
-
-template<typename T>
-static inline T min(T a, T b) {
- return a < b ? a : b;
-}
-
-static inline float avg(float x, float y) {
- return (x + y) / 2;
-}
-
-
-// --- FakePointerController ---
-
-class FakePointerController : public PointerControllerInterface {
- bool mHaveBounds;
- float mMinX, mMinY, mMaxX, mMaxY;
-
-protected:
- virtual ~FakePointerController() { }
-
-public:
- FakePointerController() {
- }
-
- void setBounds(float minX, float minY, float maxX, float maxY) {
- mHaveBounds = true;
- mMinX = minX;
- mMinY = minY;
- mMaxX = maxX;
- mMaxY = maxY;
- }
-
-private:
- virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const {
- *outMinX = mMinX;
- *outMaxX = mMinX;
- *outMinY = mMinY;
- *outMaxY = mMaxY;
- return mHaveBounds;
- }
-
- virtual void move(float deltaX, float deltaY) {
- }
-
- virtual void setButtonState(uint32_t buttonState) {
- }
-
- virtual uint32_t getButtonState() const {
- return 0;
- }
-
- virtual void setPosition(float x, float y) {
- }
-
- virtual void getPosition(float* outX, float* outY) const {
- *outX = 0;
- *outY = 0;
- }
-};
-
-
-// --- FakeInputReaderPolicy ---
-
-class FakeInputReaderPolicy : public InputReaderPolicyInterface {
- struct DisplayInfo {
- int32_t width;
- int32_t height;
- int32_t orientation;
- };
-
- KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
- bool mFilterTouchEvents;
- bool mFilterJumpyTouchEvents;
- Vector<String8> mExcludedDeviceNames;
- KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
-
-protected:
- virtual ~FakeInputReaderPolicy() { }
-
-public:
- FakeInputReaderPolicy() :
- mFilterTouchEvents(false), mFilterJumpyTouchEvents(false) {
- }
-
- void removeDisplayInfo(int32_t displayId) {
- mDisplayInfos.removeItem(displayId);
- }
-
- void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
- removeDisplayInfo(displayId);
-
- DisplayInfo info;
- info.width = width;
- info.height = height;
- info.orientation = orientation;
- mDisplayInfos.add(displayId, info);
- }
-
- void setFilterTouchEvents(bool enabled) {
- mFilterTouchEvents = enabled;
- }
-
- void setFilterJumpyTouchEvents(bool enabled) {
- mFilterJumpyTouchEvents = enabled;
- }
-
- void addExcludedDeviceName(const String8& deviceName) {
- mExcludedDeviceNames.push(deviceName);
- }
-
- void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
- mPointerControllers.add(deviceId, controller);
- }
-
-private:
- virtual bool getDisplayInfo(int32_t displayId,
- int32_t* width, int32_t* height, int32_t* orientation) {
- ssize_t index = mDisplayInfos.indexOfKey(displayId);
- if (index >= 0) {
- const DisplayInfo& info = mDisplayInfos.valueAt(index);
- if (width) {
- *width = info.width;
- }
- if (height) {
- *height = info.height;
- }
- if (orientation) {
- *orientation = info.orientation;
- }
- return true;
- }
- return false;
- }
-
- virtual bool filterTouchEvents() {
- return mFilterTouchEvents;
- }
-
- virtual bool filterJumpyTouchEvents() {
- return mFilterJumpyTouchEvents;
- }
-
- virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
- outExcludedDeviceNames.appendVector(mExcludedDeviceNames);
- }
-
- virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
- return mPointerControllers.valueFor(deviceId);
- }
-};
-
-
-// --- FakeInputDispatcher ---
-
-class FakeInputDispatcher : public InputDispatcherInterface {
-public:
- struct NotifyConfigurationChangedArgs {
- nsecs_t eventTime;
- };
-
- struct NotifyKeyArgs {
- nsecs_t eventTime;
- int32_t deviceId;
- int32_t source;
- uint32_t policyFlags;
- int32_t action;
- int32_t flags;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- nsecs_t downTime;
- };
-
- struct NotifyMotionArgs {
- nsecs_t eventTime;
- int32_t deviceId;
- int32_t source;
- uint32_t policyFlags;
- int32_t action;
- int32_t flags;
- int32_t metaState;
- int32_t edgeFlags;
- uint32_t pointerCount;
- Vector<int32_t> pointerIds;
- Vector<PointerCoords> pointerCoords;
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
- };
-
- struct NotifySwitchArgs {
- nsecs_t when;
- int32_t switchCode;
- int32_t switchValue;
- uint32_t policyFlags;
- };
-
-private:
- List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgs;
- List<NotifyKeyArgs> mNotifyKeyArgs;
- List<NotifyMotionArgs> mNotifyMotionArgs;
- List<NotifySwitchArgs> mNotifySwitchArgs;
-
-protected:
- virtual ~FakeInputDispatcher() { }
-
-public:
- FakeInputDispatcher() {
- }
-
- void assertNotifyConfigurationChangedWasCalled(NotifyConfigurationChangedArgs* outArgs = NULL) {
- ASSERT_FALSE(mNotifyConfigurationChangedArgs.empty())
- << "Expected notifyConfigurationChanged() to have been called.";
- if (outArgs) {
- *outArgs = *mNotifyConfigurationChangedArgs.begin();
- }
- mNotifyConfigurationChangedArgs.erase(mNotifyConfigurationChangedArgs.begin());
- }
-
- void assertNotifyKeyWasCalled(NotifyKeyArgs* outArgs = NULL) {
- ASSERT_FALSE(mNotifyKeyArgs.empty())
- << "Expected notifyKey() to have been called.";
- if (outArgs) {
- *outArgs = *mNotifyKeyArgs.begin();
- }
- mNotifyKeyArgs.erase(mNotifyKeyArgs.begin());
- }
-
- void assertNotifyKeyWasNotCalled() {
- ASSERT_TRUE(mNotifyKeyArgs.empty())
- << "Expected notifyKey() to not have been called.";
- }
-
- void assertNotifyMotionWasCalled(NotifyMotionArgs* outArgs = NULL) {
- ASSERT_FALSE(mNotifyMotionArgs.empty())
- << "Expected notifyMotion() to have been called.";
- if (outArgs) {
- *outArgs = *mNotifyMotionArgs.begin();
- }
- mNotifyMotionArgs.erase(mNotifyMotionArgs.begin());
- }
-
- void assertNotifyMotionWasNotCalled() {
- ASSERT_TRUE(mNotifyMotionArgs.empty())
- << "Expected notifyMotion() to not have been called.";
- }
-
- void assertNotifySwitchWasCalled(NotifySwitchArgs* outArgs = NULL) {
- ASSERT_FALSE(mNotifySwitchArgs.empty())
- << "Expected notifySwitch() to have been called.";
- if (outArgs) {
- *outArgs = *mNotifySwitchArgs.begin();
- }
- mNotifySwitchArgs.erase(mNotifySwitchArgs.begin());
- }
-
-private:
- virtual void notifyConfigurationChanged(nsecs_t eventTime) {
- NotifyConfigurationChangedArgs args;
- args.eventTime = eventTime;
- mNotifyConfigurationChangedArgs.push_back(args);
- }
-
- virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
- uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
- int32_t scanCode, int32_t metaState, nsecs_t downTime) {
- NotifyKeyArgs args;
- args.eventTime = eventTime;
- args.deviceId = deviceId;
- args.source = source;
- args.policyFlags = policyFlags;
- args.action = action;
- args.flags = flags;
- args.keyCode = keyCode;
- args.scanCode = scanCode;
- args.metaState = metaState;
- args.downTime = downTime;
- mNotifyKeyArgs.push_back(args);
- }
-
- virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
- uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t edgeFlags,
- uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
- float xPrecision, float yPrecision, nsecs_t downTime) {
- NotifyMotionArgs args;
- args.eventTime = eventTime;
- args.deviceId = deviceId;
- args.source = source;
- args.policyFlags = policyFlags;
- args.action = action;
- args.flags = flags;
- args.metaState = metaState;
- args.edgeFlags = edgeFlags;
- args.pointerCount = pointerCount;
- args.pointerIds.clear();
- args.pointerIds.appendArray(pointerIds, pointerCount);
- args.pointerCoords.clear();
- args.pointerCoords.appendArray(pointerCoords, pointerCount);
- args.xPrecision = xPrecision;
- args.yPrecision = yPrecision;
- args.downTime = downTime;
- mNotifyMotionArgs.push_back(args);
- }
-
- virtual void notifySwitch(nsecs_t when,
- int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
- NotifySwitchArgs args;
- args.when = when;
- args.switchCode = switchCode;
- args.switchValue = switchValue;
- args.policyFlags = policyFlags;
- mNotifySwitchArgs.push_back(args);
- }
-
- virtual void dump(String8& dump) {
- ADD_FAILURE() << "Should never be called by input reader.";
- }
-
- virtual void dispatchOnce() {
- ADD_FAILURE() << "Should never be called by input reader.";
- }
-
- virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
- ADD_FAILURE() << "Should never be called by input reader.";
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- virtual void setInputWindows(const Vector<InputWindow>& inputWindows) {
- ADD_FAILURE() << "Should never be called by input reader.";
- }
-
- virtual void setFocusedApplication(const InputApplication* inputApplication) {
- ADD_FAILURE() << "Should never be called by input reader.";
- }
-
- virtual void setInputDispatchMode(bool enabled, bool frozen) {
- ADD_FAILURE() << "Should never be called by input reader.";
- }
-
- virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) {
- ADD_FAILURE() << "Should never be called by input reader.";
- return 0;
- }
-
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
- ADD_FAILURE() << "Should never be called by input reader.";
- return 0;
- }
-
- virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) {
- ADD_FAILURE() << "Should never be called by input reader.";
- return 0;
- }
-};
-
-
-// --- FakeEventHub ---
-
-class FakeEventHub : public EventHubInterface {
- struct KeyInfo {
- int32_t keyCode;
- uint32_t flags;
- };
-
- struct Device {
- String8 name;
- uint32_t classes;
- PropertyMap configuration;
- KeyedVector<int, RawAbsoluteAxisInfo> axes;
- KeyedVector<int32_t, int32_t> keyCodeStates;
- KeyedVector<int32_t, int32_t> scanCodeStates;
- KeyedVector<int32_t, int32_t> switchStates;
- KeyedVector<int32_t, KeyInfo> keys;
- KeyedVector<int32_t, bool> leds;
- Vector<VirtualKeyDefinition> virtualKeys;
-
- Device(const String8& name, uint32_t classes) :
- name(name), classes(classes) {
- }
- };
-
- KeyedVector<int32_t, Device*> mDevices;
- Vector<String8> mExcludedDevices;
- List<RawEvent> mEvents;
-
-protected:
- virtual ~FakeEventHub() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- delete mDevices.valueAt(i);
- }
- }
-
-public:
- FakeEventHub() { }
-
- void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
- Device* device = new Device(name, classes);
- mDevices.add(deviceId, device);
-
- enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0, 0, 0);
- }
-
- void removeDevice(int32_t deviceId) {
- delete mDevices.valueFor(deviceId);
- mDevices.removeItem(deviceId);
-
- enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0, 0, 0);
- }
-
- void finishDeviceScan() {
- enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0, 0, 0);
- }
-
- void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
- Device* device = getDevice(deviceId);
- device->configuration.addProperty(key, value);
- }
-
- void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration) {
- Device* device = getDevice(deviceId);
- device->configuration.addAll(configuration);
- }
-
- void addAxis(int32_t deviceId, int axis,
- int32_t minValue, int32_t maxValue, int flat, int fuzz) {
- Device* device = getDevice(deviceId);
-
- RawAbsoluteAxisInfo info;
- info.valid = true;
- info.minValue = minValue;
- info.maxValue = maxValue;
- info.flat = flat;
- info.fuzz = fuzz;
- device->axes.add(axis, info);
- }
-
- void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->keyCodeStates.replaceValueFor(keyCode, state);
- }
-
- void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->scanCodeStates.replaceValueFor(scanCode, state);
- }
-
- void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->switchStates.replaceValueFor(switchCode, state);
- }
-
- void addKey(int32_t deviceId, int32_t scanCode, int32_t keyCode, uint32_t flags) {
- Device* device = getDevice(deviceId);
- KeyInfo info;
- info.keyCode = keyCode;
- info.flags = flags;
- device->keys.add(scanCode, info);
- }
-
- void addLed(int32_t deviceId, int32_t led, bool initialState) {
- Device* device = getDevice(deviceId);
- device->leds.add(led, initialState);
- }
-
- bool getLedState(int32_t deviceId, int32_t led) {
- Device* device = getDevice(deviceId);
- return device->leds.valueFor(led);
- }
-
- Vector<String8>& getExcludedDevices() {
- return mExcludedDevices;
- }
-
- void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
- Device* device = getDevice(deviceId);
- device->virtualKeys.push(definition);
- }
-
- void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type,
- int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
- RawEvent event;
- event.when = when;
- event.deviceId = deviceId;
- event.type = type;
- event.scanCode = scanCode;
- event.keyCode = keyCode;
- event.value = value;
- event.flags = flags;
- mEvents.push_back(event);
- }
-
- void assertQueueIsEmpty() {
- ASSERT_EQ(size_t(0), mEvents.size())
- << "Expected the event queue to be empty (fully consumed).";
- }
-
-private:
- Device* getDevice(int32_t deviceId) const {
- ssize_t index = mDevices.indexOfKey(deviceId);
- return index >= 0 ? mDevices.valueAt(index) : NULL;
- }
-
- virtual uint32_t getDeviceClasses(int32_t deviceId) const {
- Device* device = getDevice(deviceId);
- return device ? device->classes : 0;
- }
-
- virtual String8 getDeviceName(int32_t deviceId) const {
- Device* device = getDevice(deviceId);
- return device ? device->name : String8("unknown");
- }
-
- virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
- Device* device = getDevice(deviceId);
- if (device) {
- *outConfiguration = device->configuration;
- }
- }
-
- virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->axes.indexOfKey(axis);
- if (index >= 0) {
- *outAxisInfo = device->axes.valueAt(index);
- return OK;
- }
- }
- return -1;
- }
-
- virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
- int32_t* outKeycode, uint32_t* outFlags) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->keys.indexOfKey(scancode);
- if (index >= 0) {
- if (outKeycode) {
- *outKeycode = device->keys.valueAt(index).keyCode;
- }
- if (outFlags) {
- *outFlags = device->keys.valueAt(index).flags;
- }
- return OK;
- }
- }
- return NAME_NOT_FOUND;
- }
-
- virtual void addExcludedDevice(const char* deviceName) {
- mExcludedDevices.add(String8(deviceName));
- }
-
- virtual bool getEvent(RawEvent* outEvent) {
- if (mEvents.empty()) {
- return false;
- }
-
- *outEvent = *mEvents.begin();
- mEvents.erase(mEvents.begin());
- return true;
- }
-
- virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
- if (index >= 0) {
- return device->scanCodeStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
- if (index >= 0) {
- return device->keyCodeStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->switchStates.indexOfKey(sw);
- if (index >= 0) {
- return device->switchStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const {
- bool result = false;
- Device* device = getDevice(deviceId);
- if (device) {
- for (size_t i = 0; i < numCodes; i++) {
- for (size_t j = 0; j < device->keys.size(); j++) {
- if (keyCodes[i] == device->keys.valueAt(j).keyCode) {
- outFlags[i] = 1;
- result = true;
- }
- }
- }
- }
- return result;
- }
-
- virtual bool hasLed(int32_t deviceId, int32_t led) const {
- Device* device = getDevice(deviceId);
- return device && device->leds.indexOfKey(led) >= 0;
- }
-
- virtual void setLedState(int32_t deviceId, int32_t led, bool on) {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->leds.indexOfKey(led);
- if (index >= 0) {
- device->leds.replaceValueAt(led, on);
- } else {
- ADD_FAILURE()
- << "Attempted to set the state of an LED that the EventHub declared "
- "was not present. led=" << led;
- }
- }
- }
-
- virtual void getVirtualKeyDefinitions(int32_t deviceId,
- Vector<VirtualKeyDefinition>& outVirtualKeys) const {
- outVirtualKeys.clear();
-
- Device* device = getDevice(deviceId);
- if (device) {
- outVirtualKeys.appendVector(device->virtualKeys);
- }
- }
-
- virtual void dump(String8& dump) {
- }
-};
-
-
-// --- FakeInputReaderContext ---
-
-class FakeInputReaderContext : public InputReaderContext {
- sp<EventHubInterface> mEventHub;
- sp<InputReaderPolicyInterface> mPolicy;
- sp<InputDispatcherInterface> mDispatcher;
- int32_t mGlobalMetaState;
- bool mUpdateGlobalMetaStateWasCalled;
-
-public:
- FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputDispatcherInterface>& dispatcher) :
- mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
- mGlobalMetaState(0) {
- }
-
- virtual ~FakeInputReaderContext() { }
-
- void assertUpdateGlobalMetaStateWasCalled() {
- ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
- << "Expected updateGlobalMetaState() to have been called.";
- mUpdateGlobalMetaStateWasCalled = false;
- }
-
- void setGlobalMetaState(int32_t state) {
- mGlobalMetaState = state;
- }
-
-private:
- virtual void updateGlobalMetaState() {
- mUpdateGlobalMetaStateWasCalled = true;
- }
-
- virtual int32_t getGlobalMetaState() {
- return mGlobalMetaState;
- }
-
- virtual EventHubInterface* getEventHub() {
- return mEventHub.get();
- }
-
- virtual InputReaderPolicyInterface* getPolicy() {
- return mPolicy.get();
- }
-
- virtual InputDispatcherInterface* getDispatcher() {
- return mDispatcher.get();
- }
-};
-
-
-// --- FakeInputMapper ---
-
-class FakeInputMapper : public InputMapper {
- uint32_t mSources;
- int32_t mKeyboardType;
- int32_t mMetaState;
- KeyedVector<int32_t, int32_t> mKeyCodeStates;
- KeyedVector<int32_t, int32_t> mScanCodeStates;
- KeyedVector<int32_t, int32_t> mSwitchStates;
- Vector<int32_t> mSupportedKeyCodes;
- RawEvent mLastEvent;
-
- bool mConfigureWasCalled;
- bool mResetWasCalled;
- bool mProcessWasCalled;
-
-public:
- FakeInputMapper(InputDevice* device, uint32_t sources) :
- InputMapper(device),
- mSources(sources), mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
- mMetaState(0),
- mConfigureWasCalled(false), mResetWasCalled(false), mProcessWasCalled(false) {
- }
-
- virtual ~FakeInputMapper() { }
-
- void setKeyboardType(int32_t keyboardType) {
- mKeyboardType = keyboardType;
- }
-
- void setMetaState(int32_t metaState) {
- mMetaState = metaState;
- }
-
- void assertConfigureWasCalled() {
- ASSERT_TRUE(mConfigureWasCalled)
- << "Expected configure() to have been called.";
- mConfigureWasCalled = false;
- }
-
- void assertResetWasCalled() {
- ASSERT_TRUE(mResetWasCalled)
- << "Expected reset() to have been called.";
- mResetWasCalled = false;
- }
-
- void assertProcessWasCalled(RawEvent* outLastEvent = NULL) {
- ASSERT_TRUE(mProcessWasCalled)
- << "Expected process() to have been called.";
- if (outLastEvent) {
- *outLastEvent = mLastEvent;
- }
- mProcessWasCalled = false;
- }
-
- void setKeyCodeState(int32_t keyCode, int32_t state) {
- mKeyCodeStates.replaceValueFor(keyCode, state);
- }
-
- void setScanCodeState(int32_t scanCode, int32_t state) {
- mScanCodeStates.replaceValueFor(scanCode, state);
- }
-
- void setSwitchState(int32_t switchCode, int32_t state) {
- mSwitchStates.replaceValueFor(switchCode, state);
- }
-
- void addSupportedKeyCode(int32_t keyCode) {
- mSupportedKeyCodes.add(keyCode);
- }
-
-private:
- virtual uint32_t getSources() {
- return mSources;
- }
-
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) {
- InputMapper::populateDeviceInfo(deviceInfo);
-
- if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
- deviceInfo->setKeyboardType(mKeyboardType);
- }
- }
-
- virtual void configure() {
- mConfigureWasCalled = true;
- }
-
- virtual void reset() {
- mResetWasCalled = true;
- }
-
- virtual void process(const RawEvent* rawEvent) {
- mLastEvent = *rawEvent;
- mProcessWasCalled = true;
- }
-
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
- return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- ssize_t index = mScanCodeStates.indexOfKey(scanCode);
- return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- ssize_t index = mSwitchStates.indexOfKey(switchCode);
- return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- bool result = false;
- for (size_t i = 0; i < numCodes; i++) {
- for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
- if (keyCodes[i] == mSupportedKeyCodes[j]) {
- outFlags[i] = 1;
- result = true;
- }
- }
- }
- return result;
- }
-
- virtual int32_t getMetaState() {
- return mMetaState;
- }
-};
-
-
-// --- InstrumentedInputReader ---
-
-class InstrumentedInputReader : public InputReader {
- InputDevice* mNextDevice;
-
-public:
- InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputDispatcherInterface>& dispatcher) :
- InputReader(eventHub, policy, dispatcher) {
- }
-
- virtual ~InstrumentedInputReader() {
- if (mNextDevice) {
- delete mNextDevice;
- }
- }
-
- void setNextDevice(InputDevice* device) {
- mNextDevice = device;
- }
-
-protected:
- virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
- if (mNextDevice) {
- InputDevice* device = mNextDevice;
- mNextDevice = NULL;
- return device;
- }
- return InputReader::createDevice(deviceId, name, classes);
- }
-
- friend class InputReaderTest;
-};
-
-
-// --- InputReaderTest ---
-
-class InputReaderTest : public testing::Test {
-protected:
- sp<FakeInputDispatcher> mFakeDispatcher;
- sp<FakeInputReaderPolicy> mFakePolicy;
- sp<FakeEventHub> mFakeEventHub;
- sp<InstrumentedInputReader> mReader;
-
- virtual void SetUp() {
- mFakeEventHub = new FakeEventHub();
- mFakePolicy = new FakeInputReaderPolicy();
- mFakeDispatcher = new FakeInputDispatcher();
-
- mReader = new InstrumentedInputReader(mFakeEventHub, mFakePolicy, mFakeDispatcher);
- }
-
- virtual void TearDown() {
- mReader.clear();
-
- mFakeDispatcher.clear();
- mFakePolicy.clear();
- mFakeEventHub.clear();
- }
-
- void addDevice(int32_t deviceId, const String8& name, uint32_t classes,
- const PropertyMap* configuration) {
- mFakeEventHub->addDevice(deviceId, name, classes);
- if (configuration) {
- mFakeEventHub->addConfigurationMap(deviceId, configuration);
- }
- mFakeEventHub->finishDeviceScan();
- mReader->loopOnce();
- mReader->loopOnce();
- mFakeEventHub->assertQueueIsEmpty();
- }
-
- FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId,
- const String8& name, uint32_t classes, uint32_t sources,
- const PropertyMap* configuration) {
- InputDevice* device = new InputDevice(mReader.get(), deviceId, name);
- FakeInputMapper* mapper = new FakeInputMapper(device, sources);
- device->addMapper(mapper);
- mReader->setNextDevice(device);
- addDevice(deviceId, name, classes, configuration);
- return mapper;
- }
-};
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenNoDevices_ReturnsDefaults) {
- InputConfiguration config;
- mReader->getInputConfiguration(&config);
-
- ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
- ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
- ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenAlphabeticKeyboardPresent_ReturnsQwertyKeyboard) {
- ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("keyboard"),
- INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY, NULL));
-
- InputConfiguration config;
- mReader->getInputConfiguration(&config);
-
- ASSERT_EQ(InputConfiguration::KEYBOARD_QWERTY, config.keyboard);
- ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
- ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenTouchScreenPresent_ReturnsFingerTouchScreen) {
- ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("touchscreen"),
- INPUT_DEVICE_CLASS_TOUCHSCREEN, NULL));
-
- InputConfiguration config;
- mReader->getInputConfiguration(&config);
-
- ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
- ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
- ASSERT_EQ(InputConfiguration::TOUCHSCREEN_FINGER, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenMousePresent_ReturnsNoNavigation) {
- PropertyMap configuration;
- configuration.addProperty(String8("cursor.mode"), String8("pointer"));
- ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("mouse"),
- INPUT_DEVICE_CLASS_CURSOR, &configuration));
-
- InputConfiguration config;
- mReader->getInputConfiguration(&config);
-
- ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
- ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
- ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenTrackballPresent_ReturnsTrackballNavigation) {
- PropertyMap configuration;
- configuration.addProperty(String8("cursor.mode"), String8("navigation"));
- ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("trackball"),
- INPUT_DEVICE_CLASS_CURSOR, &configuration));
-
- InputConfiguration config;
- mReader->getInputConfiguration(&config);
-
- ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
- ASSERT_EQ(InputConfiguration::NAVIGATION_TRACKBALL, config.navigation);
- ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenDPadPresent_ReturnsDPadNavigation) {
- ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("dpad"),
- INPUT_DEVICE_CLASS_DPAD, NULL));
-
- InputConfiguration config;
- mReader->getInputConfiguration(&config);
-
- ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
- ASSERT_EQ(InputConfiguration::NAVIGATION_DPAD, config.navigation);
- ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsValid) {
- ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
- INPUT_DEVICE_CLASS_KEYBOARD, NULL));
-
- InputDeviceInfo info;
- status_t result = mReader->getInputDeviceInfo(1, &info);
-
- ASSERT_EQ(OK, result);
- ASSERT_EQ(1, info.getId());
- ASSERT_STREQ("keyboard", info.getName().string());
- ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, info.getKeyboardType());
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, info.getSources());
- ASSERT_EQ(size_t(0), info.getMotionRanges().size());
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsInvalid) {
- InputDeviceInfo info;
- status_t result = mReader->getInputDeviceInfo(-1, &info);
-
- ASSERT_EQ(NAME_NOT_FOUND, result);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsIgnored) {
- addDevice(1, String8("ignored"), 0, NULL); // no classes so device will be ignored
-
- InputDeviceInfo info;
- status_t result = mReader->getInputDeviceInfo(1, &info);
-
- ASSERT_EQ(NAME_NOT_FOUND, result);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceIds) {
- ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
- INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY, NULL));
- ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("mouse"),
- INPUT_DEVICE_CLASS_CURSOR, NULL));
-
- Vector<int32_t> ids;
- mReader->getInputDeviceIds(ids);
-
- ASSERT_EQ(size_t(2), ids.size());
- ASSERT_EQ(1, ids[0]);
- ASSERT_EQ(2, ids[1]);
-}
-
-TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
- mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
- AINPUT_SOURCE_ANY, AKEYCODE_A))
- << "Should return unknown when the device id is >= 0 but unknown.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(1,
- AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
- AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
- mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN);
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
- AINPUT_SOURCE_ANY, KEY_A))
- << "Should return unknown when the device id is >= 0 but unknown.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(1,
- AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
- AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
- mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN);
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
- AINPUT_SOURCE_ANY, SW_LID))
- << "Should return unknown when the device id is >= 0 but unknown.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(1,
- AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
- AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
- mapper->addSupportedKeyCode(AKEYCODE_A);
- mapper->addSupportedKeyCode(AKEYCODE_B);
-
- const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
- uint8_t flags[4] = { 0, 0, 0, 1 };
-
- ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, 4, keyCodes, flags))
- << "Should return false when device id is >= 0 but unknown.";
- ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
- flags[3] = 1;
- ASSERT_FALSE(mReader->hasKeys(1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return false when device id is valid but the sources are not supported by the device.";
- ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
- flags[3] = 1;
- ASSERT_TRUE(mReader->hasKeys(1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
- ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
-
- flags[3] = 1;
- ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return false when the device id is < 0 but the sources are not supported by any device.";
- ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
- flags[3] = 1;
- ASSERT_TRUE(mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
- ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
-}
-
-TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
- addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, NULL);
-
- FakeInputDispatcher::NotifyConfigurationChangedArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyConfigurationChangedWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-}
-
-TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
-
- mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, AKEYCODE_A, 1, POLICY_FLAG_WAKE);
- mReader->loopOnce();
- ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
-
- RawEvent event;
- ASSERT_NO_FATAL_FAILURE(mapper->assertProcessWasCalled(&event));
- ASSERT_EQ(0, event.when);
- ASSERT_EQ(1, event.deviceId);
- ASSERT_EQ(EV_KEY, event.type);
- ASSERT_EQ(KEY_A, event.scanCode);
- ASSERT_EQ(AKEYCODE_A, event.keyCode);
- ASSERT_EQ(1, event.value);
- ASSERT_EQ(POLICY_FLAG_WAKE, event.flags);
-}
-
-
-// --- InputDeviceTest ---
-
-class InputDeviceTest : public testing::Test {
-protected:
- static const char* DEVICE_NAME;
- static const int32_t DEVICE_ID;
-
- sp<FakeEventHub> mFakeEventHub;
- sp<FakeInputReaderPolicy> mFakePolicy;
- sp<FakeInputDispatcher> mFakeDispatcher;
- FakeInputReaderContext* mFakeContext;
-
- InputDevice* mDevice;
-
- virtual void SetUp() {
- mFakeEventHub = new FakeEventHub();
- mFakePolicy = new FakeInputReaderPolicy();
- mFakeDispatcher = new FakeInputDispatcher();
- mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
-
- mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
- }
-
- virtual void TearDown() {
- delete mDevice;
-
- delete mFakeContext;
- mFakeDispatcher.clear();
- mFakePolicy.clear();
- mFakeEventHub.clear();
- }
-};
-
-const char* InputDeviceTest::DEVICE_NAME = "device";
-const int32_t InputDeviceTest::DEVICE_ID = 1;
-
-TEST_F(InputDeviceTest, ImmutableProperties) {
- ASSERT_EQ(DEVICE_ID, mDevice->getId());
- ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
-}
-
-TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
- // Configuration.
- mDevice->configure();
-
- // Metadata.
- ASSERT_TRUE(mDevice->isIgnored());
- ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
-
- InputDeviceInfo info;
- mDevice->getDeviceInfo(&info);
- ASSERT_EQ(DEVICE_ID, info.getId());
- ASSERT_STREQ(DEVICE_NAME, info.getName().string());
- ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
- ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
-
- // State queries.
- ASSERT_EQ(0, mDevice->getMetaState());
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
- << "Ignored device should return unknown key code state.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
- << "Ignored device should return unknown scan code state.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
- << "Ignored device should return unknown switch state.";
-
- const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
- uint8_t flags[2] = { 0, 1 };
- ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 2, keyCodes, flags))
- << "Ignored device should never mark any key codes.";
- ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
- ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
-
- // Reset.
- mDevice->reset();
-}
-
-TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
- // Configuration.
- mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8("key"), String8("value"));
-
- FakeInputMapper* mapper1 = new FakeInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD);
- mapper1->setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- mapper1->setMetaState(AMETA_ALT_ON);
- mapper1->addSupportedKeyCode(AKEYCODE_A);
- mapper1->addSupportedKeyCode(AKEYCODE_B);
- mapper1->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
- mapper1->setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
- mapper1->setScanCodeState(2, AKEY_STATE_DOWN);
- mapper1->setScanCodeState(3, AKEY_STATE_UP);
- mapper1->setSwitchState(4, AKEY_STATE_DOWN);
- mDevice->addMapper(mapper1);
-
- FakeInputMapper* mapper2 = new FakeInputMapper(mDevice, AINPUT_SOURCE_TOUCHSCREEN);
- mapper2->setMetaState(AMETA_SHIFT_ON);
- mDevice->addMapper(mapper2);
-
- mDevice->configure();
-
- String8 propertyValue;
- ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty(String8("key"), propertyValue))
- << "Device should have read configuration during configuration phase.";
- ASSERT_STREQ("value", propertyValue.string());
-
- ASSERT_NO_FATAL_FAILURE(mapper1->assertConfigureWasCalled());
- ASSERT_NO_FATAL_FAILURE(mapper2->assertConfigureWasCalled());
-
- // Metadata.
- ASSERT_FALSE(mDevice->isIgnored());
- ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
-
- InputDeviceInfo info;
- mDevice->getDeviceInfo(&info);
- ASSERT_EQ(DEVICE_ID, info.getId());
- ASSERT_STREQ(DEVICE_NAME, info.getName().string());
- ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
- ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
-
- // State queries.
- ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
- << "Should query mappers and combine meta states.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown key code state when source not supported.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown scan code state when source not supported.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown switch state when source not supported.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
- << "Should query mapper when source is supported.";
- ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
- << "Should query mapper when source is supported.";
- ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
- << "Should query mapper when source is supported.";
-
- const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
- uint8_t flags[4] = { 0, 0, 0, 1 };
- ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should do nothing when source is unsupported.";
- ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
- ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
- ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
- ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
-
- ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 4, keyCodes, flags))
- << "Should query mapper when source is supported.";
- ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
- ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
- ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
- ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
-
- // Event handling.
- RawEvent event;
- mDevice->process(&event);
-
- ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
- ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
-
- // Reset.
- mDevice->reset();
-
- ASSERT_NO_FATAL_FAILURE(mapper1->assertResetWasCalled());
- ASSERT_NO_FATAL_FAILURE(mapper2->assertResetWasCalled());
-}
-
-
-// --- InputMapperTest ---
-
-class InputMapperTest : public testing::Test {
-protected:
- static const char* DEVICE_NAME;
- static const int32_t DEVICE_ID;
-
- sp<FakeEventHub> mFakeEventHub;
- sp<FakeInputReaderPolicy> mFakePolicy;
- sp<FakeInputDispatcher> mFakeDispatcher;
- FakeInputReaderContext* mFakeContext;
- InputDevice* mDevice;
-
- virtual void SetUp() {
- mFakeEventHub = new FakeEventHub();
- mFakePolicy = new FakeInputReaderPolicy();
- mFakeDispatcher = new FakeInputDispatcher();
- mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
-
- mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
- }
-
- virtual void TearDown() {
- delete mDevice;
- delete mFakeContext;
- mFakeDispatcher.clear();
- mFakePolicy.clear();
- mFakeEventHub.clear();
- }
-
- void addConfigurationProperty(const char* key, const char* value) {
- mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8(key), String8(value));
- }
-
- void addMapperAndConfigure(InputMapper* mapper) {
- mDevice->addMapper(mapper);
- mDevice->configure();
- }
-
- static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type,
- int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
- RawEvent event;
- event.when = when;
- event.deviceId = deviceId;
- event.type = type;
- event.scanCode = scanCode;
- event.keyCode = keyCode;
- event.value = value;
- event.flags = flags;
- mapper->process(&event);
- }
-
- static void assertMotionRange(const InputDeviceInfo& info,
- int32_t rangeType, float min, float max, float flat, float fuzz) {
- const InputDeviceInfo::MotionRange* range = info.getMotionRange(rangeType);
- ASSERT_TRUE(range != NULL) << "Range: " << rangeType;
- ASSERT_NEAR(min, range->min, EPSILON) << "Range: " << rangeType;
- ASSERT_NEAR(max, range->max, EPSILON) << "Range: " << rangeType;
- ASSERT_NEAR(flat, range->flat, EPSILON) << "Range: " << rangeType;
- ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Range: " << rangeType;
- }
-
- static void assertPointerCoords(const PointerCoords& coords,
- float x, float y, float pressure, float size,
- float touchMajor, float touchMinor, float toolMajor, float toolMinor,
- float orientation) {
- ASSERT_NEAR(x, coords.x, 1);
- ASSERT_NEAR(y, coords.y, 1);
- ASSERT_NEAR(pressure, coords.pressure, EPSILON);
- ASSERT_NEAR(size, coords.size, EPSILON);
- ASSERT_NEAR(touchMajor, coords.touchMajor, 1);
- ASSERT_NEAR(touchMinor, coords.touchMinor, 1);
- ASSERT_NEAR(toolMajor, coords.toolMajor, 1);
- ASSERT_NEAR(toolMinor, coords.toolMinor, 1);
- ASSERT_NEAR(orientation, coords.orientation, EPSILON);
- }
-};
-
-const char* InputMapperTest::DEVICE_NAME = "device";
-const int32_t InputMapperTest::DEVICE_ID = 1;
-
-
-// --- SwitchInputMapperTest ---
-
-class SwitchInputMapperTest : public InputMapperTest {
-protected:
-};
-
-TEST_F(SwitchInputMapperTest, GetSources) {
- SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(uint32_t(0), mapper->getSources());
-}
-
-TEST_F(SwitchInputMapperTest, GetSwitchState) {
- SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
- addMapperAndConfigure(mapper);
-
- mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 1);
- ASSERT_EQ(1, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-
- mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 0);
- ASSERT_EQ(0, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-}
-
-TEST_F(SwitchInputMapperTest, Process) {
- SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
- addMapperAndConfigure(mapper);
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 0, 1, 0);
-
- FakeInputDispatcher::NotifySwitchArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifySwitchWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.when);
- ASSERT_EQ(SW_LID, args.switchCode);
- ASSERT_EQ(1, args.switchValue);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-}
-
-
-// --- KeyboardInputMapperTest ---
-
-class KeyboardInputMapperTest : public InputMapperTest {
-protected:
- void testDPadKeyRotation(KeyboardInputMapper* mapper,
- int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode);
-};
-
-void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper,
- int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) {
- FakeInputDispatcher::NotifyKeyArgs args;
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(originalScanCode, args.scanCode);
- ASSERT_EQ(rotatedKeyCode, args.keyCode);
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(originalScanCode, args.scanCode);
- ASSERT_EQ(rotatedKeyCode, args.keyCode);
-}
-
-
-TEST_F(KeyboardInputMapperTest, GetSources) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper->getSources());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Key down.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
- FakeInputDispatcher::NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key up.
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
- EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreNotDown_DoesNotSynthesizeKeyUp) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Key down.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- // Key up.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- // Reset. Since no keys still down, should not synthesize any key ups.
- mapper->reset();
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Metakey down.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- // Key down.
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
- EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- // Reset. Since two keys are still down, should synthesize two key ups in reverse order.
- mapper->reset();
-
- FakeInputDispatcher::NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_A, args.keyCode);
- ASSERT_EQ(KEY_A, args.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_SHIFT_LEFT, args.keyCode);
- ASSERT_EQ(KEY_LEFTSHIFT, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
-
- // And that's it.
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Initial metastate.
- ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-
- // Metakey down.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
- FakeInputDispatcher::NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
- ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
-
- // Key down.
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
- EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-
- // Key up.
- process(mapper, ARBITRARY_TIME + 2, DEVICE_ID,
- EV_KEY, KEY_A, AKEYCODE_A, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-
- // Metakey up.
- process(mapper, ARBITRARY_TIME + 3, DEVICE_ID,
- EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
- ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_90);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addConfigurationProperty("keyboard.orientationAware", "1");
- addMapperAndConfigure(mapper);
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_0);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_90);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN));
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_180);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_LEFT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT));
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_270);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_UP));
-
- // Special case: if orientation changes while key is down, we still emit the same keycode
- // in the key up as we did in the key down.
- FakeInputDispatcher::NotifyKeyArgs args;
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_270);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(KEY_UP, args.scanCode);
- ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_180);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(KEY_UP, args.scanCode);
- ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-}
-
-TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 1);
- ASSERT_EQ(1, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
- mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 0);
- ASSERT_EQ(0, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-}
-
-TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 1);
- ASSERT_EQ(1, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
- mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 0);
- ASSERT_EQ(0, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-}
-
-TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- mFakeEventHub->addKey(DEVICE_ID, KEY_A, AKEYCODE_A, 0);
-
- const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
- uint8_t flags[2] = { 0, 0 };
- ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 1, keyCodes, flags));
- ASSERT_TRUE(flags[0]);
- ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
- mFakeEventHub->addLed(DEVICE_ID, LED_CAPSL, true /*initially on*/);
- mFakeEventHub->addLed(DEVICE_ID, LED_NUML, false /*initially off*/);
- mFakeEventHub->addLed(DEVICE_ID, LED_SCROLLL, false /*initially off*/);
-
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Initialization should have turned all of the lights off.
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-
- // Toggle caps lock on.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper->getMetaState());
-
- // Toggle num lock on.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper->getMetaState());
-
- // Toggle caps lock off.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper->getMetaState());
-
- // Toggle scroll lock on.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
-
- // Toggle num lock off.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
-
- // Toggle scroll lock off.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-}
-
-
-// --- CursorInputMapperTest ---
-
-class CursorInputMapperTest : public InputMapperTest {
-protected:
- static const int32_t TRACKBALL_MOVEMENT_THRESHOLD;
-
- sp<FakePointerController> mFakePointerController;
-
- virtual void SetUp() {
- InputMapperTest::SetUp();
-
- mFakePointerController = new FakePointerController();
- mFakePolicy->setPointerController(DEVICE_ID, mFakePointerController);
- }
-
- void testMotionRotation(CursorInputMapper* mapper,
- int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY);
-};
-
-const int32_t CursorInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
-void CursorInputMapperTest::testMotionRotation(CursorInputMapper* mapper,
- int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) {
- FakeInputDispatcher::NotifyMotionArgs args;
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, originalX, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, originalY, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- float(rotatedX) / TRACKBALL_MOVEMENT_THRESHOLD,
- float(rotatedY) / TRACKBALL_MOVEMENT_THRESHOLD,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, WhenModeIsPointer_GetSources_ReturnsMouse) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "pointer");
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
-}
-
-TEST_F(CursorInputMapperTest, WhenModeIsNavigation_GetSources_ReturnsTrackball) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper->getSources());
-}
-
-TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeFromPointerController) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "pointer");
- addMapperAndConfigure(mapper);
-
- InputDeviceInfo info;
- mapper->populateDeviceInfo(&info);
-
- // Initially there may not be a valid motion range.
- ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X));
- ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE,
- 0.0f, 1.0f, 0.0f, 1.0f));
-
- // When the bounds are set, then there should be a valid motion range.
- mFakePointerController->setBounds(1, 2, 800, 480);
-
- InputDeviceInfo info2;
- mapper->populateDeviceInfo(&info2);
-
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_X,
- 1, 800, 0.0f, 1.0f));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_Y,
- 2, 480, 0.0f, 1.0f));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_PRESSURE,
- 0.0f, 1.0f, 0.0f, 1.0f));
-}
-
-TEST_F(CursorInputMapperTest, WhenModeIsNavigation_PopulateDeviceInfo_ReturnsScaledRange) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- InputDeviceInfo info;
- mapper->populateDeviceInfo(&info);
-
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_X,
- -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_Y,
- -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- FakeInputDispatcher::NotifyMotionArgs args;
-
- // Button press.
- // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(0, args.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(0, args.edgeFlags);
- ASSERT_EQ(uint32_t(1), args.pointerCount);
- ASSERT_EQ(0, args.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
- ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Button release. Should have same down time.
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(0, args.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(0, args.edgeFlags);
- ASSERT_EQ(uint32_t(1), args.pointerCount);
- ASSERT_EQ(0, args.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
- ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
-
- // Motion in X but not Y.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // Motion in Y but not X.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
- ASSERT_NEAR(0.0f, args.pointerCoords[0].x, EPSILON);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
-
- // Button press without following sync.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // Button release without following sync.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
-
- // Combined X, Y and Button.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD,
- 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // Move X, Y a bit while pressed.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 2, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD,
- 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // Release Button.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
-
- // Button press.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
- // Button release.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
- // Reset. Should not synthesize button up since button is not pressed.
- mapper->reset();
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(CursorInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
-
- // Button press.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
- // Reset. Should synthesize button up.
- mapper->reset();
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_90);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
-}
-
-TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addConfigurationProperty("cursor.orientationAware", "1");
- addMapperAndConfigure(mapper);
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_0);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_90);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1));
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_180);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1));
-
- mFakePolicy->setDisplayInfo(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- InputReaderPolicyInterface::ROTATION_270);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1));
-}
-
-
-// --- TouchInputMapperTest ---
-
-class TouchInputMapperTest : public InputMapperTest {
-protected:
- static const int32_t RAW_X_MIN;
- static const int32_t RAW_X_MAX;
- static const int32_t RAW_Y_MIN;
- static const int32_t RAW_Y_MAX;
- static const int32_t RAW_TOUCH_MIN;
- static const int32_t RAW_TOUCH_MAX;
- static const int32_t RAW_TOOL_MIN;
- static const int32_t RAW_TOOL_MAX;
- static const int32_t RAW_PRESSURE_MIN;
- static const int32_t RAW_PRESSURE_MAX;
- static const int32_t RAW_ORIENTATION_MIN;
- static const int32_t RAW_ORIENTATION_MAX;
- static const int32_t RAW_ID_MIN;
- static const int32_t RAW_ID_MAX;
- static const float X_PRECISION;
- static const float Y_PRECISION;
-
- static const VirtualKeyDefinition VIRTUAL_KEYS[2];
-
- enum Axes {
- POSITION = 1 << 0,
- TOUCH = 1 << 1,
- TOOL = 1 << 2,
- PRESSURE = 1 << 3,
- ORIENTATION = 1 << 4,
- MINOR = 1 << 5,
- ID = 1 << 6,
- };
-
- void prepareDisplay(int32_t orientation);
- void prepareVirtualKeys();
- int32_t toRawX(float displayX);
- int32_t toRawY(float displayY);
- float toDisplayX(int32_t rawX);
- float toDisplayY(int32_t rawY);
-};
-
-const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
-const int32_t TouchInputMapperTest::RAW_X_MAX = 1020;
-const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
-const int32_t TouchInputMapperTest::RAW_Y_MAX = 1010;
-const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
-const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
-const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = RAW_TOUCH_MIN;
-const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = RAW_TOUCH_MAX;
-const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
-const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
-const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
-const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH;
-const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT;
-
-const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
- { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
- { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
-};
-
-void TouchInputMapperTest::prepareDisplay(int32_t orientation) {
- mFakePolicy->setDisplayInfo(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
-}
-
-void TouchInputMapperTest::prepareVirtualKeys() {
- mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]);
- mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]);
- mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, AKEYCODE_MENU, POLICY_FLAG_WAKE);
-}
-
-int32_t TouchInputMapperTest::toRawX(float displayX) {
- return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH + RAW_X_MIN);
-}
-
-int32_t TouchInputMapperTest::toRawY(float displayY) {
- return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT + RAW_Y_MIN);
-}
-
-float TouchInputMapperTest::toDisplayX(int32_t rawX) {
- return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN);
-}
-
-float TouchInputMapperTest::toDisplayY(int32_t rawY) {
- return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN);
-}
-
-
-// --- SingleTouchInputMapperTest ---
-
-class SingleTouchInputMapperTest : public TouchInputMapperTest {
-protected:
- void prepareAxes(int axes);
-
- void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
- void processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
- void processUp(SingleTouchInputMapper* mappery);
- void processPressure(SingleTouchInputMapper* mapper, int32_t pressure);
- void processToolMajor(SingleTouchInputMapper* mapper, int32_t toolMajor);
- void processSync(SingleTouchInputMapper* mapper);
-};
-
-void SingleTouchInputMapperTest::prepareAxes(int axes) {
- if (axes & POSITION) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
- mFakeEventHub->addAxis(DEVICE_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
- }
- if (axes & PRESSURE) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
- }
- if (axes & TOOL) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
- }
-}
-
-void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 1, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
-}
-
-void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
-}
-
-void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper* mapper) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 0, 0);
-}
-
-void SingleTouchInputMapperTest::processPressure(
- SingleTouchInputMapper* mapper, int32_t pressure) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, 0, pressure, 0);
-}
-
-void SingleTouchInputMapperTest::processToolMajor(
- SingleTouchInputMapper* mapper, int32_t toolMajor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, 0, toolMajor, 0);
-}
-
-void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-}
-
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareAxes(POSITION);
- addConfigurationProperty("touch.deviceType", "touchPad");
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareAxes(POSITION);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- // Unknown key.
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
- // Virtual key is down.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
-
- // Virtual key is up.
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- ASSERT_EQ(AKEY_STATE_UP, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
-}
-
-TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- // Unknown key.
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
- // Virtual key is down.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
-
- // Virtual key is up.
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- ASSERT_EQ(AKEY_STATE_UP, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
-}
-
-TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- const int32_t keys[2] = { AKEYCODE_HOME, AKEYCODE_A };
- uint8_t flags[2] = { 0, 0 };
- ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 2, keys, flags));
- ASSERT_TRUE(flags[0]);
- ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(SingleTouchInputMapperTest, Reset_WhenVirtualKeysAreDown_SendsUp) {
- // Note: Ideally we should send cancels but the implementation is more straightforward
- // with up and this will only happen if a device is forcibly removed.
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- // Press virtual key.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- // Reset. Since key is down, synthesize key up.
- mapper->reset();
-
- FakeInputDispatcher::NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- //ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(SingleTouchInputMapperTest, Reset_WhenNothingIsPressed_NothingMuchHappens) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- // Press virtual key.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- // Release virtual key.
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
- // Reset. Since no key is down, nothing happens.
- mapper->reset();
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- FakeInputDispatcher::NotifyKeyArgs args;
-
- // Press virtual key.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Release virtual key.
- processUp(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Should not have sent any motions.
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- FakeInputDispatcher::NotifyKeyArgs keyArgs;
-
- // Press virtual key.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
- ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
- ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
- ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
-
- // Move out of bounds. This should generate a cancel and a pointer down since we moved
- // into the display area.
- y -= 100;
- processMove(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
- | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
- ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
- ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
- ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
-
- FakeInputDispatcher::NotifyMotionArgs motionArgs;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Keep moving out of bounds. Should generate a pointer move.
- y -= 50;
- processMove(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Release out of bounds. Should generate a pointer up.
- processUp(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
- // Initially go down out of bounds.
- int32_t x = -10;
- int32_t y = -10;
- processDown(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-
- // Move into the display area. Should generate a pointer down.
- x = 50;
- y = 75;
- processMove(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Release. Should generate a pointer up.
- processUp(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
- // Down.
- int32_t x = 100;
- int32_t y = 125;
- processDown(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Move.
- x += 50;
- y += 75;
- processMove(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Up.
- processUp(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareAxes(POSITION);
- addConfigurationProperty("touch.orientationAware", "0");
- addMapperAndConfigure(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
-
- // Rotation 90.
- prepareDisplay(InputReaderPolicyInterface::ROTATION_90);
- processDown(mapper, toRawX(50), toRawY(75));
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
- ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareAxes(POSITION);
- addMapperAndConfigure(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
-
- // Rotation 0.
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- processDown(mapper, toRawX(50), toRawY(75));
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
- ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
- // Rotation 90.
- prepareDisplay(InputReaderPolicyInterface::ROTATION_90);
- processDown(mapper, toRawX(50), toRawY(75));
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(75, args.pointerCoords[0].x, 1);
- ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].y, 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
- // Rotation 180.
- prepareDisplay(InputReaderPolicyInterface::ROTATION_180);
- processDown(mapper, toRawX(50), toRawY(75));
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].x, 1);
- ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].y, 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
- // Rotation 270.
- prepareDisplay(InputReaderPolicyInterface::ROTATION_270);
- processDown(mapper, toRawX(50), toRawY(75));
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].x, 1);
- ASSERT_NEAR(50, args.pointerCoords[0].y, 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION | PRESSURE | TOOL);
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawPressure = 10;
- int32_t rawToolMajor = 12;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
- float size = float(rawToolMajor) / RAW_TOOL_MAX;
- float tool = min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * size;
- float touch = min(tool * pressure, tool);
-
- processDown(mapper, rawX, rawY);
- processPressure(mapper, rawPressure);
- processToolMajor(mapper, rawToolMajor);
- processSync(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, size, touch, touch, tool, tool, 0));
-}
-
-
-// --- MultiTouchInputMapperTest ---
-
-class MultiTouchInputMapperTest : public TouchInputMapperTest {
-protected:
- void prepareAxes(int axes);
-
- void processPosition(MultiTouchInputMapper* mapper, int32_t x, int32_t y);
- void processTouchMajor(MultiTouchInputMapper* mapper, int32_t touchMajor);
- void processTouchMinor(MultiTouchInputMapper* mapper, int32_t touchMinor);
- void processToolMajor(MultiTouchInputMapper* mapper, int32_t toolMajor);
- void processToolMinor(MultiTouchInputMapper* mapper, int32_t toolMinor);
- void processOrientation(MultiTouchInputMapper* mapper, int32_t orientation);
- void processPressure(MultiTouchInputMapper* mapper, int32_t pressure);
- void processId(MultiTouchInputMapper* mapper, int32_t id);
- void processMTSync(MultiTouchInputMapper* mapper);
- void processSync(MultiTouchInputMapper* mapper);
-};
-
-void MultiTouchInputMapperTest::prepareAxes(int axes) {
- if (axes & POSITION) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
- }
- if (axes & TOUCH) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
- if (axes & MINOR) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR,
- RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
- }
- }
- if (axes & TOOL) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
- if (axes & MINOR) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR,
- RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0);
- }
- }
- if (axes & ORIENTATION) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_ORIENTATION,
- RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0);
- }
- if (axes & PRESSURE) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_PRESSURE,
- RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
- }
- if (axes & ID) {
- mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TRACKING_ID,
- RAW_ID_MIN, RAW_ID_MAX, 0, 0);
- }
-}
-
-void MultiTouchInputMapperTest::processPosition(
- MultiTouchInputMapper* mapper, int32_t x, int32_t y) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, 0, x, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, 0, y, 0);
-}
-
-void MultiTouchInputMapperTest::processTouchMajor(
- MultiTouchInputMapper* mapper, int32_t touchMajor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, 0, touchMajor, 0);
-}
-
-void MultiTouchInputMapperTest::processTouchMinor(
- MultiTouchInputMapper* mapper, int32_t touchMinor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, 0, touchMinor, 0);
-}
-
-void MultiTouchInputMapperTest::processToolMajor(
- MultiTouchInputMapper* mapper, int32_t toolMajor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, 0, toolMajor, 0);
-}
-
-void MultiTouchInputMapperTest::processToolMinor(
- MultiTouchInputMapper* mapper, int32_t toolMinor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, 0, toolMinor, 0);
-}
-
-void MultiTouchInputMapperTest::processOrientation(
- MultiTouchInputMapper* mapper, int32_t orientation) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, 0, orientation, 0);
-}
-
-void MultiTouchInputMapperTest::processPressure(
- MultiTouchInputMapper* mapper, int32_t pressure) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, 0, pressure, 0);
-}
-
-void MultiTouchInputMapperTest::processId(
- MultiTouchInputMapper* mapper, int32_t id) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, 0, id, 0);
-}
-
-void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0, 0, 0);
-}
-
-void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper* mapper) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-}
-
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
- // Two fingers down at once.
- int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
- processPosition(mapper, x1, y1);
- processMTSync(mapper);
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Move.
- x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
- processPosition(mapper, x1, y1);
- processMTSync(mapper);
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // First finger up.
- x2 += 15; y2 -= 20;
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Move.
- x2 += 20; y2 -= 25;
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // New finger down.
- int32_t x3 = 700, y3 = 300;
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processPosition(mapper, x3, y3);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Second finger up.
- x3 += 30; y3 -= 20;
- processPosition(mapper, x3, y3);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Last finger up.
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION | ID);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
- // Two fingers down at once.
- int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
- processPosition(mapper, x1, y1);
- processId(mapper, 1);
- processMTSync(mapper);
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_EQ(2, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
- // Move.
- x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
- processPosition(mapper, x1, y1);
- processId(mapper, 1);
- processMTSync(mapper);
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_EQ(2, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
- // First finger up.
- x2 += 15; y2 -= 20;
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_EQ(2, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(2, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
- // Move.
- x2 += 20; y2 -= 25;
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(2, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
- // New finger down.
- int32_t x3 = 700, y3 = 300;
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processPosition(mapper, x3, y3);
- processId(mapper, 3);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(2, motionArgs.pointerIds[0]);
- ASSERT_EQ(3, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
- // Second finger up.
- x3 += 30; y3 -= 20;
- processPosition(mapper, x3, y3);
- processId(mapper, 3);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(2, motionArgs.pointerIds[0]);
- ASSERT_EQ(3, motionArgs.pointerIds[1]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(3, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
- // Last finger up.
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(3, motionArgs.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR);
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawTouchMajor = 7;
- int32_t rawTouchMinor = 6;
- int32_t rawToolMajor = 9;
- int32_t rawToolMinor = 8;
- int32_t rawPressure = 11;
- int32_t rawOrientation = 3;
- int32_t id = 5;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
- float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
- float toolMajor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMajor / RAW_TOOL_MAX;
- float toolMinor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMinor / RAW_TOOL_MAX;
- float touchMajor = min(toolMajor * pressure, toolMajor);
- float touchMinor = min(toolMinor * pressure, toolMinor);
- float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
-
- processPosition(mapper, rawX, rawY);
- processTouchMajor(mapper, rawTouchMajor);
- processTouchMinor(mapper, rawTouchMinor);
- processToolMajor(mapper, rawToolMajor);
- processToolMinor(mapper, rawToolMinor);
- processPressure(mapper, rawPressure);
- processOrientation(mapper, rawOrientation);
- processId(mapper, id);
- processMTSync(mapper);
- processSync(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(id, args.pointerIds[0]);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION | TOUCH | TOOL | MINOR);
- addConfigurationProperty("touch.touchSize.calibration", "geometric");
- addConfigurationProperty("touch.toolSize.calibration", "geometric");
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawTouchMajor = 140;
- int32_t rawTouchMinor = 120;
- int32_t rawToolMajor = 180;
- int32_t rawToolMinor = 160;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float pressure = float(rawTouchMajor) / RAW_TOUCH_MAX;
- float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
- float scale = avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN),
- float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN));
- float toolMajor = float(rawToolMajor) * scale;
- float toolMinor = float(rawToolMinor) * scale;
- float touchMajor = min(float(rawTouchMajor) * scale, toolMajor);
- float touchMinor = min(float(rawTouchMinor) * scale, toolMinor);
-
- processPosition(mapper, rawX, rawY);
- processTouchMajor(mapper, rawTouchMajor);
- processTouchMinor(mapper, rawTouchMinor);
- processToolMajor(mapper, rawToolMajor);
- processToolMinor(mapper, rawToolMinor);
- processMTSync(mapper);
- processSync(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_SummedLinearCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION | TOUCH | TOOL);
- addConfigurationProperty("touch.touchSize.calibration", "pressure");
- addConfigurationProperty("touch.toolSize.calibration", "linear");
- addConfigurationProperty("touch.toolSize.linearScale", "10");
- addConfigurationProperty("touch.toolSize.linearBias", "160");
- addConfigurationProperty("touch.toolSize.isSummed", "1");
- addConfigurationProperty("touch.pressure.calibration", "amplitude");
- addConfigurationProperty("touch.pressure.source", "touch");
- addConfigurationProperty("touch.pressure.scale", "0.01");
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- // Note: We only provide a single common touch/tool value because the device is assumed
- // not to emit separate values for each pointer (isSummed = 1).
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawX2 = 150;
- int32_t rawY2 = 250;
- int32_t rawTouchMajor = 60;
- int32_t rawToolMajor = 5;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float x2 = toDisplayX(rawX2);
- float y2 = toDisplayY(rawY2);
- float pressure = float(rawTouchMajor) * 0.01f;
- float size = float(rawToolMajor) / RAW_TOOL_MAX;
- float tool = (float(rawToolMajor) * 10.0f + 160.0f) / 2;
- float touch = min(tool * pressure, tool);
-
- processPosition(mapper, rawX, rawY);
- processTouchMajor(mapper, rawTouchMajor);
- processToolMajor(mapper, rawToolMajor);
- processMTSync(mapper);
- processPosition(mapper, rawX2, rawY2);
- processTouchMajor(mapper, rawTouchMajor);
- processToolMajor(mapper, rawToolMajor);
- processMTSync(mapper);
- processSync(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- args.action);
- ASSERT_EQ(size_t(2), args.pointerCount);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, size, touch, touch, tool, tool, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
- x2, y2, pressure, size, touch, touch, tool, tool, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_AreaCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
- prepareAxes(POSITION | TOUCH | TOOL);
- addConfigurationProperty("touch.touchSize.calibration", "pressure");
- addConfigurationProperty("touch.toolSize.calibration", "area");
- addConfigurationProperty("touch.toolSize.areaScale", "22");
- addConfigurationProperty("touch.toolSize.areaBias", "1");
- addConfigurationProperty("touch.toolSize.linearScale", "9.2");
- addConfigurationProperty("touch.toolSize.linearBias", "3");
- addConfigurationProperty("touch.pressure.calibration", "amplitude");
- addConfigurationProperty("touch.pressure.source", "touch");
- addConfigurationProperty("touch.pressure.scale", "0.01");
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawTouchMajor = 60;
- int32_t rawToolMajor = 5;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float pressure = float(rawTouchMajor) * 0.01f;
- float size = float(rawToolMajor) / RAW_TOOL_MAX;
- float tool = sqrtf(float(rawToolMajor) * 22.0f + 1.0f) * 9.2f + 3.0f;
- float touch = min(tool * pressure, tool);
-
- processPosition(mapper, rawX, rawY);
- processTouchMajor(mapper, rawTouchMajor);
- processToolMajor(mapper, rawToolMajor);
- processMTSync(mapper);
- processSync(mapper);
-
- FakeInputDispatcher::NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, size, touch, touch, tool, tool, 0));
-}
-
-} // namespace android