diff options
Diffstat (limited to 'widget/gonk/libui')
48 files changed, 0 insertions, 29736 deletions
diff --git a/widget/gonk/libui/EventHub.cpp b/widget/gonk/libui/EventHub.cpp deleted file mode 100644 index 9da29bbeb..000000000 --- a/widget/gonk/libui/EventHub.cpp +++ /dev/null @@ -1,1549 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "EventHub" - -// #define LOG_NDEBUG 0 -#include "cutils_log.h" - -#include "EventHub.h" - -#include <hardware_legacy/power.h> - -#include <cutils/properties.h> -#include "cutils_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 "KeyLayoutMap.h" -#include "KeyCharacterMap.h" -#include "VirtualKeyMap.h" - -#include <string.h> -#include <stdint.h> -#include <dirent.h> - -#include <sys/inotify.h> -#include <sys/epoll.h> -#include <sys/ioctl.h> -#include <sys/limits.h> -#include "sha1.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) - -#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"; -} - -static String8 sha1(const String8& in) { - SHA1_CTX ctx; - SHA1Init(&ctx); - SHA1Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size()); - u_char digest[SHA1_DIGEST_LENGTH]; - SHA1Final(digest, &ctx); - - String8 out; - for (size_t i = 0; i < SHA1_DIGEST_LENGTH; i++) { - out.appendFormat("%02x", digest[i]); - } - return out; -} - -static void setDescriptor(InputDeviceIdentifier& identifier) { - // Compute a device descriptor that uniquely identifies the device. - // The descriptor is assumed to be a stable identifier. Its value should not - // change between reboots, reconnections, firmware updates or new releases of Android. - // Ideally, we also want the descriptor to be short and relatively opaque. - String8 rawDescriptor; - rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product); - if (!identifier.uniqueId.isEmpty()) { - rawDescriptor.append("uniqueId:"); - rawDescriptor.append(identifier.uniqueId); - } if (identifier.vendor == 0 && identifier.product == 0) { - // If we don't know the vendor and product id, then the device is probably - // built-in so we need to rely on other information to uniquely identify - // the input device. Usually we try to avoid relying on the device name or - // location but for built-in input device, they are unlikely to ever change. - if (!identifier.name.isEmpty()) { - rawDescriptor.append("name:"); - rawDescriptor.append(identifier.name); - } else if (!identifier.location.isEmpty()) { - rawDescriptor.append("location:"); - rawDescriptor.append(identifier.location); - } - } - identifier.descriptor = sha1(rawDescriptor); - ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(), - identifier.descriptor.string()); -} - -// --- Global Functions --- - -uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) { - // Touch devices get dibs on touch-related axes. - if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) { - switch (axis) { - case ABS_X: - case ABS_Y: - case ABS_PRESSURE: - case ABS_TOOL_WIDTH: - case ABS_DISTANCE: - case ABS_TILT_X: - case ABS_TILT_Y: - case ABS_MT_SLOT: - case ABS_MT_TOUCH_MAJOR: - case ABS_MT_TOUCH_MINOR: - case ABS_MT_WIDTH_MAJOR: - case ABS_MT_WIDTH_MINOR: - case ABS_MT_ORIENTATION: - case ABS_MT_POSITION_X: - case ABS_MT_POSITION_Y: - case ABS_MT_TOOL_TYPE: - case ABS_MT_BLOB_ID: - case ABS_MT_TRACKING_ID: - case ABS_MT_PRESSURE: - case ABS_MT_DISTANCE: - return INPUT_DEVICE_CLASS_TOUCH; - } - } - - // Joystick devices get the rest. - return deviceClasses & INPUT_DEVICE_CLASS_JOYSTICK; -} - -// --- 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), configuration(NULL), virtualKeyMap(NULL), - ffEffectPlaying(false), ffEffectId(-1), - timestampOverrideSec(0), timestampOverrideUsec(0) { - memset(keyBitmask, 0, sizeof(keyBitmask)); - memset(absBitmask, 0, sizeof(absBitmask)); - memset(relBitmask, 0, sizeof(relBitmask)); - memset(swBitmask, 0, sizeof(swBitmask)); - memset(ledBitmask, 0, sizeof(ledBitmask)); - memset(ffBitmask, 0, sizeof(ffBitmask)); - memset(propBitmask, 0, sizeof(propBitmask)); -} - -EventHub::Device::~Device() { - close(); - delete configuration; - delete virtualKeyMap; -} - -void EventHub::Device::close() { - if (fd >= 0) { - ::close(fd); - fd = -1; - } -} - - -// --- EventHub --- - -const uint32_t EventHub::EPOLL_ID_INOTIFY; -const uint32_t EventHub::EPOLL_ID_WAKE; -const int EventHub::EPOLL_SIZE_HINT; -const int EventHub::EPOLL_MAX_EVENTS; - -EventHub::EventHub(void) : - mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), - mOpeningDevices(0), mClosingDevices(0), - mNeedToSendFinishedDeviceScan(false), - mNeedToReopenDevices(false), mNeedToScanDevices(true), - mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); - - mEpollFd = epoll_create(EPOLL_SIZE_HINT); - LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); - - mINotifyFd = inotify_init(); - int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE); - LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s. errno=%d", - DEVICE_PATH, errno); - - struct epoll_event eventItem; - memset(&eventItem, 0, sizeof(eventItem)); - eventItem.events = EPOLLIN; - eventItem.data.u32 = EPOLL_ID_INOTIFY; - result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno); - - int wakeFds[2]; - result = pipe(wakeFds); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); - - mWakeReadPipeFd = wakeFds[0]; - mWakeWritePipeFd = wakeFds[1]; - - result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", - errno); - - result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", - errno); - - eventItem.data.u32 = EPOLL_ID_WAKE; - result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", - errno); -} - -EventHub::~EventHub(void) { - closeAllDevicesLocked(); - - while (mClosingDevices) { - Device* device = mClosingDevices; - mClosingDevices = device->next; - delete device; - } - - ::close(mEpollFd); - ::close(mINotifyFd); - ::close(mWakeReadPipeFd); - ::close(mWakeWritePipeFd); - - release_wake_lock(WAKE_LOCK_ID); -} - -InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - if (device == NULL) return InputDeviceIdentifier(); - return device->identifier; -} - -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(); - - if (axis >= 0 && axis <= ABS_MAX) { - AutoMutex _l(mLock); - - Device* device = getDeviceLocked(deviceId); - if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) { - struct input_absinfo info; - if(ioctl(device->fd, EVIOCGABS(axis), &info)) { - ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", - axis, device->identifier.name.string(), device->fd, errno); - 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; - outAxisInfo->resolution = info.resolution; - } - return OK; - } - } - return -1; -} - -bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const { - if (axis >= 0 && axis <= REL_MAX) { - AutoMutex _l(mLock); - - Device* device = getDeviceLocked(deviceId); - if (device) { - return test_bit(axis, device->relBitmask); - } - } - return false; -} - -bool EventHub::hasInputProperty(int32_t deviceId, int property) const { - if (property >= 0 && property <= INPUT_PROP_MAX) { - AutoMutex _l(mLock); - - Device* device = getDeviceLocked(deviceId); - if (device) { - return test_bit(property, device->propBitmask); - } - } - return false; -} - -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 && !device->isVirtual() && test_bit(scanCode, device->keyBitmask)) { - uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; - memset(keyState, 0, sizeof(keyState)); - if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) { - return test_bit(scanCode, keyState) ? 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 && !device->isVirtual() && device->keyMap.haveKeyLayout()) { - Vector<int32_t> scanCodes; - device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes); - if (scanCodes.size() != 0) { - uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; - memset(keyState, 0, sizeof(keyState)); - if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) { - for (size_t i = 0; i < scanCodes.size(); i++) { - int32_t sc = scanCodes.itemAt(i); - if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, keyState)) { - return AKEY_STATE_DOWN; - } - } - return AKEY_STATE_UP; - } - } - } - return AKEY_STATE_UNKNOWN; -} - -int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const { - if (sw >= 0 && sw <= SW_MAX) { - AutoMutex _l(mLock); - - Device* device = getDeviceLocked(deviceId); - if (device && !device->isVirtual() && test_bit(sw, device->swBitmask)) { - uint8_t swState[sizeof_bit_array(SW_MAX + 1)]; - memset(swState, 0, sizeof(swState)); - if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) { - return test_bit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP; - } - } - } - return AKEY_STATE_UNKNOWN; -} - -status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const { - *outValue = 0; - - if (axis >= 0 && axis <= ABS_MAX) { - AutoMutex _l(mLock); - - Device* device = getDeviceLocked(deviceId); - if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) { - struct input_absinfo info; - if(ioctl(device->fd, EVIOCGABS(axis), &info)) { - ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", - axis, device->identifier.name.string(), device->fd, errno); - return -errno; - } - - *outValue = info.value; - return OK; - } - } - return -1; -} - -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 && device->keyMap.haveKeyLayout()) { - Vector<int32_t> scanCodes; - for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) { - scanCodes.clear(); - - status_t err = device->keyMap.keyLayoutMap->findScanCodesForKey( - 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; - } - return false; -} - -status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, - int32_t* outKeycode, uint32_t* outFlags) const { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - - if (device) { - // Check the key character map first. - sp<KeyCharacterMap> kcm = device->getKeyCharacterMap(); - if (kcm != NULL) { - if (!kcm->mapKey(scanCode, usageCode, outKeycode)) { - *outFlags = 0; - return NO_ERROR; - } - } - - // Check the key layout next. - if (device->keyMap.haveKeyLayout()) { - if (!device->keyMap.keyLayoutMap->mapKey( - scanCode, usageCode, outKeycode, outFlags)) { - return NO_ERROR; - } - } - } - - *outKeycode = 0; - *outFlags = 0; - return NAME_NOT_FOUND; -} - -status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - - if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo); - if (err == NO_ERROR) { - return NO_ERROR; - } - } - - return NAME_NOT_FOUND; -} - -void EventHub::setExcludedDevices(const Vector<String8>& devices) { - AutoMutex _l(mLock); - - mExcludedDevices = devices; -} - -bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - if (device && scanCode >= 0 && scanCode <= KEY_MAX) { - if (test_bit(scanCode, device->keyBitmask)) { - return true; - } - } - return false; -} - -bool EventHub::hasLed(int32_t deviceId, int32_t led) const { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - if (device && led >= 0 && led <= LED_MAX) { - if (test_bit(led, device->ledBitmask)) { - return true; - } - } - return false; -} - -void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - if (device && !device->isVirtual() && led >= 0 && led <= LED_MAX) { - 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()); - } -} - -sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - if (device) { - return device->getKeyCharacterMap(); - } - return NULL; -} - -bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, - const sp<KeyCharacterMap>& map) { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - if (device) { - if (map != device->overlayKeyMap) { - device->overlayKeyMap = map; - device->combinedKeyMap = KeyCharacterMap::combine( - device->keyMap.keyCharacterMap, map); - return true; - } - } - return false; -} - -void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - if (device && !device->isVirtual()) { - ff_effect effect; - memset(&effect, 0, sizeof(effect)); - effect.type = FF_RUMBLE; - effect.id = device->ffEffectId; - effect.u.rumble.strong_magnitude = 0xc000; - effect.u.rumble.weak_magnitude = 0xc000; - effect.replay.length = (duration + 999999LL) / 1000000LL; - effect.replay.delay = 0; - if (ioctl(device->fd, EVIOCSFF, &effect)) { - ALOGW("Could not upload force feedback effect to device %s due to error %d.", - device->identifier.name.string(), errno); - return; - } - device->ffEffectId = effect.id; - - struct input_event ev; - ev.time.tv_sec = 0; - ev.time.tv_usec = 0; - ev.type = EV_FF; - ev.code = device->ffEffectId; - ev.value = 1; - if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) { - ALOGW("Could not start force feedback effect on device %s due to error %d.", - device->identifier.name.string(), errno); - return; - } - device->ffEffectPlaying = true; - } -} - -void EventHub::cancelVibrate(int32_t deviceId) { - AutoMutex _l(mLock); - Device* device = getDeviceLocked(deviceId); - if (device && !device->isVirtual()) { - if (device->ffEffectPlaying) { - device->ffEffectPlaying = false; - - struct input_event ev; - ev.time.tv_sec = 0; - ev.time.tv_usec = 0; - ev.type = EV_FF; - ev.code = device->ffEffectId; - ev.value = 0; - if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) { - ALOGW("Could not stop force feedback effect on device %s due to error %d.", - device->identifier.name.string(), errno); - return; - } - } - } -} - -EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const { - if (deviceId == BUILT_IN_KEYBOARD_ID) { - deviceId = mBuiltInKeyboardId; - } - ssize_t index = mDevices.indexOfKey(deviceId); - return index >= 0 ? mDevices.valueAt(index) : NULL; -} - -EventHub::Device* EventHub::getDeviceByPathLocked(const char* devicePath) const { - for (size_t i = 0; i < mDevices.size(); i++) { - Device* device = mDevices.valueAt(i); - if (device->path == devicePath) { - return device; - } - } - return NULL; -} - -size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { - ALOG_ASSERT(bufferSize >= 1); - - AutoMutex _l(mLock); - - struct input_event readBuffer[bufferSize]; - - RawEvent* event = buffer; - size_t capacity = bufferSize; - bool awoken = false; - for (;;) { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - - // Reopen input devices if needed. - if (mNeedToReopenDevices) { - mNeedToReopenDevices = false; - - ALOGI("Reopening all input devices due to a configuration change."); - - closeAllDevicesLocked(); - mNeedToScanDevices = true; - break; // return to the caller before we actually rescan - } - - // Report any devices that had last been added/removed. - while (mClosingDevices) { - Device* device = mClosingDevices; - ALOGV("Reporting device closed: id=%d, name=%s\n", - device->id, device->path.string()); - mClosingDevices = device->next; - event->when = now; - event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id; - event->type = DEVICE_REMOVED; - event += 1; - delete device; - mNeedToSendFinishedDeviceScan = true; - if (--capacity == 0) { - break; - } - } - - if (mNeedToScanDevices) { - mNeedToScanDevices = false; - scanDevicesLocked(); - mNeedToSendFinishedDeviceScan = true; - } - - while (mOpeningDevices != NULL) { - Device* device = mOpeningDevices; - ALOGV("Reporting device opened: id=%d, name=%s\n", - device->id, device->path.string()); - mOpeningDevices = device->next; - event->when = now; - event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; - event->type = DEVICE_ADDED; - event += 1; - mNeedToSendFinishedDeviceScan = true; - if (--capacity == 0) { - break; - } - } - - if (mNeedToSendFinishedDeviceScan) { - mNeedToSendFinishedDeviceScan = false; - event->when = now; - event->type = FINISHED_DEVICE_SCAN; - event += 1; - if (--capacity == 0) { - break; - } - } - - // Grab the next input event. - bool deviceChanged = false; - while (mPendingEventIndex < mPendingEventCount) { - const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++]; - if (eventItem.data.u32 == EPOLL_ID_INOTIFY) { - if (eventItem.events & EPOLLIN) { - mPendingINotify = true; - } else { - ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events); - } - continue; - } - - if (eventItem.data.u32 == EPOLL_ID_WAKE) { - if (eventItem.events & EPOLLIN) { - ALOGV("awoken after wake()"); - awoken = true; - char buffer[16]; - ssize_t nRead; - do { - nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); - } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer)); - } else { - ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.", - eventItem.events); - } - continue; - } - - ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32); - if (deviceIndex < 0) { - ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.", - eventItem.events, eventItem.data.u32); - continue; - } - - Device* device = mDevices.valueAt(deviceIndex); - if (eventItem.events & EPOLLIN) { - int32_t readSize = read(device->fd, readBuffer, - sizeof(struct input_event) * capacity); - if (readSize == 0 || (readSize < 0 && errno == ENODEV)) { - // Device was removed before INotify noticed. - ALOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d " - "capacity: %d errno: %d)\n", - device->fd, readSize, bufferSize, capacity, errno); - deviceChanged = true; - closeDeviceLocked(device); - } else if (readSize < 0) { - if (errno != EAGAIN && errno != EINTR) { - ALOGW("could not get event (errno=%d)", errno); - } - } else if ((readSize % sizeof(struct input_event)) != 0) { - ALOGE("could not get event (wrong size: %d)", readSize); - } else { - int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; - - size_t count = size_t(readSize) / sizeof(struct input_event); - for (size_t i = 0; i < count; i++) { - struct input_event& iev = readBuffer[i]; - ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d", - device->path.string(), - (int) iev.time.tv_sec, (int) iev.time.tv_usec, - iev.type, iev.code, iev.value); - - // Some input devices may have a better concept of the time - // when an input event was actually generated than the kernel - // which simply timestamps all events on entry to evdev. - // This is a custom Android extension of the input protocol - // mainly intended for use with uinput based device drivers. - if (iev.type == EV_MSC) { - if (iev.code == MSC_ANDROID_TIME_SEC) { - device->timestampOverrideSec = iev.value; - continue; - } else if (iev.code == MSC_ANDROID_TIME_USEC) { - device->timestampOverrideUsec = iev.value; - continue; - } - } - if (device->timestampOverrideSec || device->timestampOverrideUsec) { - iev.time.tv_sec = device->timestampOverrideSec; - iev.time.tv_usec = device->timestampOverrideUsec; - if (iev.type == EV_SYN && iev.code == SYN_REPORT) { - device->timestampOverrideSec = 0; - device->timestampOverrideUsec = 0; - } - ALOGV("applied override time %d.%06d", - int(iev.time.tv_sec), int(iev.time.tv_usec)); - } - -#ifdef HAVE_POSIX_CLOCKS - // Use the time specified in the event instead of the current time - // so that downstream code can get more accurate estimates of - // event dispatch latency from the time the event is enqueued onto - // the evdev client buffer. - // - // The event's timestamp fortuitously uses the same monotonic clock - // time base as the rest of Android. The kernel event device driver - // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts(). - // The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere - // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a - // system call that also queries ktime_get_ts(). - event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL - + nsecs_t(iev.time.tv_usec) * 1000LL; - ALOGV("event time %lld, now %lld", event->when, now); - - // Bug 7291243: Add a guard in case the kernel generates timestamps - // that appear to be far into the future because they were generated - // using the wrong clock source. - // - // This can happen because when the input device is initially opened - // it has a default clock source of CLOCK_REALTIME. Any input events - // enqueued right after the device is opened will have timestamps - // generated using CLOCK_REALTIME. We later set the clock source - // to CLOCK_MONOTONIC but it is already too late. - // - // Invalid input event timestamps can result in ANRs, crashes and - // and other issues that are hard to track down. We must not let them - // propagate through the system. - // - // Log a warning so that we notice the problem and recover gracefully. - if (event->when >= now + 10 * 1000000000LL) { - // Double-check. Time may have moved on. - nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC); - if (event->when > time) { - ALOGW("An input event from %s has a timestamp that appears to " - "have been generated using the wrong clock source " - "(expected CLOCK_MONOTONIC): " - "event time %lld, current time %lld, call time %lld. " - "Using current time instead.", - device->path.string(), event->when, time, now); - event->when = time; - } else { - ALOGV("Event time is ok but failed the fast path and required " - "an extra call to systemTime: " - "event time %lld, current time %lld, call time %lld.", - event->when, time, now); - } - } -#else - event->when = now; -#endif - event->deviceId = deviceId; - event->type = iev.type; - event->code = iev.code; - event->value = iev.value; - event += 1; - capacity -= 1; - } - if (capacity == 0) { - // The result buffer is full. Reset the pending event index - // so we will try to read the device again on the next iteration. - mPendingEventIndex -= 1; - break; - } - } - } else if (eventItem.events & EPOLLHUP) { - ALOGI("Removing device %s due to epoll hang-up event.", - device->identifier.name.string()); - deviceChanged = true; - closeDeviceLocked(device); - } else { - ALOGW("Received unexpected epoll event 0x%08x for device %s.", - eventItem.events, device->identifier.name.string()); - } - } - - // readNotify() will modify the list of devices so this must be done after - // processing all other events to ensure that we read all remaining events - // before closing the devices. - if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) { - mPendingINotify = false; - readNotifyLocked(); - deviceChanged = true; - } - - // Report added or removed devices immediately. - if (deviceChanged) { - continue; - } - - // Return now if we have collected any events or if we were explicitly awoken. - if (event != buffer || awoken) { - break; - } - - // Poll for events. Mind the wake lock dance! - // We hold a wake lock at all times except during epoll_wait(). 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. - // - // The timeout is advisory only. If the device is asleep, it will not wake just to - // service the timeout. - mPendingEventIndex = 0; - - mLock.unlock(); // release lock before poll, must be before release_wake_lock - release_wake_lock(WAKE_LOCK_ID); - - int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis); - - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); - mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock - - if (pollResult == 0) { - // Timed out. - mPendingEventCount = 0; - break; - } - - if (pollResult < 0) { - // An error occurred. - mPendingEventCount = 0; - - // Sleep after errors to avoid locking up the system. - // Hopefully the error is transient. - if (errno != EINTR) { - ALOGW("poll failed (errno=%d)\n", errno); - usleep(100000); - } - } else { - // Some events occurred. - mPendingEventCount = size_t(pollResult); - } - } - - // All done, return the number of events we read. - return event - buffer; -} - -void EventHub::wake() { - ALOGV("wake() called"); - - ssize_t nWrite; - do { - nWrite = write(mWakeWritePipeFd, "W", 1); - } while (nWrite == -1 && errno == EINTR); - - if (nWrite != 1 && errno != EAGAIN) { - ALOGW("Could not write wake signal, errno=%d", errno); - } -} - -void EventHub::scanDevicesLocked() { - status_t res = scanDirLocked(DEVICE_PATH); - if(res < 0) { - ALOGE("scan dir failed for %s\n", DEVICE_PATH); - } - if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) { - createVirtualKeyboardLocked(); - } -} - -// ---------------------------------------------------------------------------- - -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, - AKEYCODE_BUTTON_1, AKEYCODE_BUTTON_2, AKEYCODE_BUTTON_3, AKEYCODE_BUTTON_4, - AKEYCODE_BUTTON_5, AKEYCODE_BUTTON_6, AKEYCODE_BUTTON_7, AKEYCODE_BUTTON_8, - AKEYCODE_BUTTON_9, AKEYCODE_BUTTON_10, AKEYCODE_BUTTON_11, AKEYCODE_BUTTON_12, - AKEYCODE_BUTTON_13, AKEYCODE_BUTTON_14, AKEYCODE_BUTTON_15, AKEYCODE_BUTTON_16, -}; - -status_t EventHub::openDeviceLocked(const char *devicePath) { - char buffer[80]; - - ALOGV("Opening device: %s", devicePath); - - int fd = open(devicePath, O_RDWR | O_CLOEXEC); - if(fd < 0) { - ALOGE("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 - for (size_t i = 0; i < mExcludedDevices.size(); i++) { - const String8& item = mExcludedDevices.itemAt(i); - if (identifier.name == item) { - ALOGI("ignoring event id %s driver %s\n", devicePath, item.string()); - close(fd); - return -1; - } - } - - // Get device driver version. - int driverVersion; - if(ioctl(fd, EVIOCGVERSION, &driverVersion)) { - ALOGE("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)) { - ALOGE("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); - } - - // Fill in the descriptor. - setDescriptor(identifier); - - // Make file descriptor non-blocking for use with poll(). - if (fcntl(fd, F_SETFL, O_NONBLOCK)) { - ALOGE("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); - - ALOGV("add device %d: %s\n", deviceId, devicePath); - ALOGV(" bus: %04x\n" - " vendor %04x\n" - " product %04x\n" - " version %04x\n", - identifier.bus, identifier.vendor, identifier.product, identifier.version); - ALOGV(" name: \"%s\"\n", identifier.name.string()); - ALOGV(" location: \"%s\"\n", identifier.location.string()); - ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string()); - ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.string()); - ALOGV(" driver: v%d.%d.%d\n", - driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff); - - // Load the configuration file for the device. - loadConfigurationLocked(device); - - // Figure out the kinds of events the device reports. - ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask); - ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask); - ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask); - ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask); - ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask); - ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask); - ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask); - - // See if this is a keyboard. Ignore everything in the button range except for - // joystick and gamepad buttons which are handled like keyboards for the most part. - bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) - || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK), - sizeof_bit_array(KEY_MAX + 1)); - bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC), - sizeof_bit_array(BTN_MOUSE)) - || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK), - sizeof_bit_array(BTN_DIGI)); - if (haveKeyboardKeys || haveGamepadButtons) { - device->classes |= INPUT_DEVICE_CLASS_KEYBOARD; - } - - // See if this is a cursor device such as a trackball or mouse. - if (test_bit(BTN_MOUSE, device->keyBitmask) - && test_bit(REL_X, device->relBitmask) - && test_bit(REL_Y, device->relBitmask)) { - device->classes |= INPUT_DEVICE_CLASS_CURSOR; - } - - // See if this is a touch pad. - // Is this a new modern multi-touch driver? - if (test_bit(ABS_MT_POSITION_X, device->absBitmask) - && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) { - // Some joysticks such as the PS3 controller report axes that conflict - // with the ABS_MT range. Try to confirm that the device really is - // a touch screen. - if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) { - device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT; - } - // Is this an old style single-touch driver? - } else if (test_bit(BTN_TOUCH, device->keyBitmask) - && test_bit(ABS_X, device->absBitmask) - && test_bit(ABS_Y, device->absBitmask)) { - device->classes |= INPUT_DEVICE_CLASS_TOUCH; - } - - // See if this device is a joystick. - // Assumes that joysticks always have gamepad buttons in order to distinguish them - // from other devices such as accelerometers that also have absolute axes. - if (haveGamepadButtons) { - uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK; - for (int i = 0; i <= ABS_MAX; i++) { - if (test_bit(i, device->absBitmask) - && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) { - device->classes = assumedClasses; - break; - } - } - } - - // Check whether this device has switches. - for (int i = 0; i <= SW_MAX; i++) { - if (test_bit(i, device->swBitmask)) { - device->classes |= INPUT_DEVICE_CLASS_SWITCH; - break; - } - } - - // Check whether this device supports the vibrator. - if (test_bit(FF_RUMBLE, device->ffBitmask)) { - device->classes |= INPUT_DEVICE_CLASS_VIBRATOR; - } - - // Configure virtual keys. - if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) { - // 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 = loadVirtualKeyMapLocked(device); - if (!status) { - device->classes |= INPUT_DEVICE_CLASS_KEYBOARD; - } - } - - // Load the key map. - // We need to do this for joysticks too because the key layout may specify axes. - status_t keyMapStatus = NAME_NOT_FOUND; - if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) { - // Load the keymap for the device. - keyMapStatus = loadKeyMapLocked(device); - } - - // Configure the keyboard, gamepad or virtual keyboard. - if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) { - // Register the keyboard as a built-in keyboard if it is eligible. - if (!keyMapStatus - && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD - && isEligibleBuiltInKeyboard(device->identifier, - device->configuration, &device->keyMap)) { - mBuiltInKeyboardId = device->id; - } - - // '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; - } - } - - // Disable kernel key repeat since we handle it ourselves - unsigned int repeatRate[] = {0,0}; - if (ioctl(fd, EVIOCSREP, repeatRate)) { - ALOGW("Unable to disable kernel key repeat for %s: %s", devicePath, strerror(errno)); - } - } - - // If the device isn't recognized as something we handle, don't monitor it. - if (device->classes == 0) { - ALOGV("Dropping device: id=%d, path='%s', name='%s'", - deviceId, devicePath, device->identifier.name.string()); - delete device; - return -1; - } - - // Determine whether the device is external or internal. - if (isExternalDeviceLocked(device)) { - device->classes |= INPUT_DEVICE_CLASS_EXTERNAL; - } - - // Register with epoll. - struct epoll_event eventItem; - memset(&eventItem, 0, sizeof(eventItem)); - eventItem.events = EPOLLIN; - eventItem.data.u32 = deviceId; - if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) { - ALOGE("Could not add device fd to epoll instance. errno=%d", errno); - delete device; - return -1; - } - - // Enable wake-lock behavior on kernels that support it. - // TODO: Only need this for devices that can really wake the system. - bool usingSuspendBlockIoctl = !ioctl(fd, EVIOCSSUSPENDBLOCK, 1); - - // Tell the kernel that we want to use the monotonic clock for reporting timestamps - // associated with input events. This is important because the input system - // uses the timestamps extensively and assumes they were recorded using the monotonic - // clock. - // - // In older kernel, before Linux 3.4, there was no way to tell the kernel which - // clock to use to input event timestamps. The standard kernel behavior was to - // record a real time timestamp, which isn't what we want. Android kernels therefore - // contained a patch to the evdev_event() function in drivers/input/evdev.c to - // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic - // clock to be used instead of the real time clock. - // - // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock. - // Therefore, we no longer require the Android-specific kernel patch described above - // as long as we make sure to set select the monotonic clock. We do that here. - int clockId = CLOCK_MONOTONIC; - bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId); - - ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, " - "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, " - "usingSuspendBlockIoctl=%s, usingClockIoctl=%s", - deviceId, fd, devicePath, device->identifier.name.string(), - device->classes, - device->configurationFile.string(), - device->keyMap.keyLayoutFile.string(), - device->keyMap.keyCharacterMapFile.string(), - toString(mBuiltInKeyboardId == deviceId), - toString(usingSuspendBlockIoctl), toString(usingClockIoctl)); - - addDeviceLocked(device); - return 0; -} - -void EventHub::createVirtualKeyboardLocked() { - InputDeviceIdentifier identifier; - identifier.name = "Virtual"; - identifier.uniqueId = "<virtual>"; - setDescriptor(identifier); - - Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier); - device->classes = INPUT_DEVICE_CLASS_KEYBOARD - | INPUT_DEVICE_CLASS_ALPHAKEY - | INPUT_DEVICE_CLASS_DPAD - | INPUT_DEVICE_CLASS_VIRTUAL; - loadKeyMapLocked(device); - addDeviceLocked(device); -} - -void EventHub::addDeviceLocked(Device* device) { - mDevices.add(device->id, device); - device->next = mOpeningDevices; - mOpeningDevices = device; -} - -void EventHub::loadConfigurationLocked(Device* device) { - device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier( - device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION); - if (device->configurationFile.isEmpty()) { - ALOGD("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) { - ALOGE("Error loading input device configuration file for device '%s'. " - "Using default configuration.", - device->identifier.name.string()); - } - } -} - -status_t EventHub::loadVirtualKeyMapLocked(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::loadKeyMapLocked(Device* device) { - return device->keyMap.load(device->identifier, device->configuration); -} - -bool EventHub::isExternalDeviceLocked(Device* device) { - if (device->configuration) { - bool value; - if (device->configuration->tryGetProperty(String8("device.internal"), value)) { - return !value; - } - } - return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH; -} - -bool EventHub::hasKeycodeLocked(Device* device, int keycode) const { - if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) { - return false; - } - - Vector<int32_t> scanCodes; - device->keyMap.keyLayoutMap->findScanCodesForKey(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; -} - -status_t EventHub::closeDeviceByPathLocked(const char *devicePath) { - Device* device = getDeviceByPathLocked(devicePath); - if (device) { - closeDeviceLocked(device); - return 0; - } - ALOGV("Remove device: %s not found, device may already have been removed.", devicePath); - return -1; -} - -void EventHub::closeAllDevicesLocked() { - while (mDevices.size() > 0) { - closeDeviceLocked(mDevices.valueAt(mDevices.size() - 1)); - } -} - -void EventHub::closeDeviceLocked(Device* device) { - ALOGI("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); - - if (device->id == mBuiltInKeyboardId) { - ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this", - device->path.string(), mBuiltInKeyboardId); - mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD; - } - - if (!device->isVirtual()) { - if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) { - ALOGW("Could not remove device fd from epoll instance. errno=%d", errno); - } - } - - mDevices.removeItem(device->id); - device->close(); - - // Unlink for opening devices list if it is present. - Device* pred = NULL; - bool found = false; - for (Device* entry = mOpeningDevices; entry != NULL; ) { - if (entry == device) { - found = true; - break; - } - pred = entry; - entry = entry->next; - } - if (found) { - // Unlink the device from the opening devices list then delete it. - // We don't need to tell the client that the device was closed because - // it does not even know it was opened in the first place. - ALOGI("Device %s was immediately closed after opening.", device->path.string()); - if (pred) { - pred->next = device->next; - } else { - mOpeningDevices = device->next; - } - delete device; - } else { - // Link into closing devices list. - // The device will be deleted later after we have informed the client. - device->next = mClosingDevices; - mClosingDevices = device; - } -} - -status_t EventHub::readNotifyLocked() { - int res; - char devname[PATH_MAX]; - char *filename; - char event_buf[512]; - int event_size; - int event_pos = 0; - struct inotify_event *event; - - ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd); - res = read(mINotifyFd, event_buf, sizeof(event_buf)); - if(res < (int)sizeof(*event)) { - if(errno == EINTR) - return 0; - ALOGW("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) { - openDeviceLocked(devname); - } else { - ALOGI("Removing device '%s' due to inotify event\n", devname); - closeDeviceByPathLocked(devname); - } - } - event_size = sizeof(*event) + event->len; - res -= event_size; - event_pos += event_size; - } - return 0; -} - -status_t EventHub::scanDirLocked(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); - openDeviceLocked(devname); - } - closedir(dir); - return 0; -} - -void EventHub::requestReopenDevices() { - ALOGV("requestReopenDevices() called"); - - AutoMutex _l(mLock); - mNeedToReopenDevices = true; -} - -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 = 0; i < mDevices.size(); i++) { - const Device* device = mDevices.valueAt(i); - 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 "Descriptor: %s\n", device->identifier.descriptor.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()); - dump.appendFormat(INDENT3 "HaveKeyboardLayoutOverlay: %s\n", - toString(device->overlayKeyMap != NULL)); - } - } // release lock -} - -void EventHub::monitor() { - // Acquire and release the lock to ensure that the event hub has not deadlocked. - mLock.lock(); - mLock.unlock(); -} - - -}; // namespace android diff --git a/widget/gonk/libui/EventHub.h b/widget/gonk/libui/EventHub.h deleted file mode 100644 index e4e658b21..000000000 --- a/widget/gonk/libui/EventHub.h +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -#ifndef _RUNTIME_EVENT_HUB_H -#define _RUNTIME_EVENT_HUB_H - -#include "Input.h" -#include "InputDevice.h" -#include "Keyboard.h" -#include "KeyLayoutMap.h" -#include "KeyCharacterMap.h" -#include "VirtualKeyMap.h" -#include <utils/String8.h> -#include <utils/threads.h> -#include "cutils_log.h" -#include <utils/threads.h> -#include <utils/List.h> -#include <utils/Errors.h> -#include <utils/PropertyMap.h> -#include <utils/Vector.h> -#include <utils/KeyedVector.h> - -#include "linux_input.h" -#include <sys/epoll.h> - -/* Convenience constants. */ - -#define BTN_FIRST 0x100 // first button code -#define BTN_LAST 0x15f // last button code - -/* - * These constants are used privately in Android to pass raw timestamps - * through evdev from uinput device drivers because there is currently no - * other way to transfer this information. The evdev driver automatically - * timestamps all input events with the time they were posted and clobbers - * whatever information was passed in. - * - * For the purposes of this hack, the timestamp is specified in the - * CLOCK_MONOTONIC timebase and is split into two EV_MSC events specifying - * seconds and microseconds. - */ -#define MSC_ANDROID_TIME_SEC 0x6 -#define MSC_ANDROID_TIME_USEC 0x7 - -namespace android { - -enum { - // Device id of a special "virtual" keyboard that is always present. - VIRTUAL_KEYBOARD_ID = -1, - // Device id of the "built-in" keyboard if there is one. - BUILT_IN_KEYBOARD_ID = 0, -}; - -/* - * A raw event as retrieved from the EventHub. - */ -struct RawEvent { - nsecs_t when; - int32_t deviceId; - int32_t type; - int32_t code; - int32_t value; -}; - -/* Describes an absolute axis. */ -struct RawAbsoluteAxisInfo { - bool valid; // true if the information is valid, false otherwise - - int32_t minValue; // minimum value - int32_t maxValue; // maximum value - int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8 - int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise - int32_t resolution; // resolution in units per mm or radians per mm - - inline void clear() { - valid = false; - minValue = 0; - maxValue = 0; - flat = 0; - fuzz = 0; - resolution = 0; - } -}; - -/* - * Input device classes. - */ -enum { - /* The input device is a keyboard or has buttons. */ - INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001, - - /* The input device is an alpha-numeric keyboard (not just a dial pad). */ - INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002, - - /* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */ - INPUT_DEVICE_CLASS_TOUCH = 0x00000004, - - /* The input device is a cursor device such as a trackball or mouse. */ - INPUT_DEVICE_CLASS_CURSOR = 0x00000008, - - /* The input device is a multi-touch touchscreen. */ - INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010, - - /* The input device is a directional pad (implies keyboard, has DPAD keys). */ - INPUT_DEVICE_CLASS_DPAD = 0x00000020, - - /* The input device is a gamepad (implies keyboard, has BUTTON keys). */ - INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040, - - /* The input device has switches. */ - INPUT_DEVICE_CLASS_SWITCH = 0x00000080, - - /* The input device is a joystick (implies gamepad, has joystick absolute axes). */ - INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100, - - /* The input device has a vibrator (supports FF_RUMBLE). */ - INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200, - - /* The input device is virtual (not a real device, not part of UI configuration). */ - INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000, - - /* The input device is external (not built-in). */ - INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000, -}; - -/* - * Gets the class that owns an axis, in cases where multiple classes might claim - * the same axis for different purposes. - */ -extern uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses); - -/* - * Grand Central Station for events. - * - * The event hub aggregates input events received across all known input - * devices on the system, including devices that may be emulated by the simulator - * environment. In addition, the event hub generates fake input events to indicate - * when devices are added or removed. - * - * The event hub provides a stream of input events (via the getEvent function). - * It also supports querying the current actual state of input devices such as identifying - * which keys are currently down. Finally, the event hub keeps track of the capabilities of - * individual input devices, such as their class and the set of key codes that they support. - */ -class EventHubInterface : public virtual RefBase { -protected: - EventHubInterface() { } - virtual ~EventHubInterface() { } - -public: - // Synthetic raw event type codes produced when devices are added or removed. - enum { - // Sent when a device is added. - DEVICE_ADDED = 0x10000000, - // Sent when a device is removed. - DEVICE_REMOVED = 0x20000000, - // Sent when all added/removed devices from the most recent scan have been reported. - // This event is always sent at least once. - FINISHED_DEVICE_SCAN = 0x30000000, - - FIRST_SYNTHETIC_EVENT = DEVICE_ADDED, - }; - - virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0; - - virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0; - - virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0; - - virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, - RawAbsoluteAxisInfo* outAxisInfo) const = 0; - - virtual bool hasRelativeAxis(int32_t deviceId, int axis) const = 0; - - virtual bool hasInputProperty(int32_t deviceId, int property) const = 0; - - virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, - int32_t* outKeycode, uint32_t* outFlags) const = 0; - - virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, - AxisInfo* outAxisInfo) const = 0; - - // Sets devices that are excluded from opening. - // This can be used to ignore input devices for sensors. - virtual void setExcludedDevices(const Vector<String8>& devices) = 0; - - /* - * Wait for events to become available and returns them. - * After returning, the EventHub holds onto a wake lock until the next call to getEvent. - * This ensures that the device will not go to sleep while the event is being processed. - * If the device needs to remain awake longer than that, then the caller is responsible - * for taking care of it (say, by poking the power manager user activity timer). - * - * The timeout is advisory only. If the device is asleep, it will not wake just to - * service the timeout. - * - * Returns the number of events obtained, or 0 if the timeout expired. - */ - virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0; - - /* - * Query current input state. - */ - virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0; - virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0; - virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0; - virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, - int32_t* outValue) const = 0; - - /* - * Examine key input devices for specific framework keycode support - */ - virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes, - uint8_t* outFlags) const = 0; - - virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0; - virtual bool hasLed(int32_t deviceId, int32_t led) const = 0; - virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0; - - virtual void getVirtualKeyDefinitions(int32_t deviceId, - Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0; - - virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const = 0; - virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) = 0; - - /* Control the vibrator. */ - virtual void vibrate(int32_t deviceId, nsecs_t duration) = 0; - virtual void cancelVibrate(int32_t deviceId) = 0; - - /* Requests the EventHub to reopen all input devices on the next call to getEvents(). */ - virtual void requestReopenDevices() = 0; - - /* Wakes up getEvents() if it is blocked on a read. */ - virtual void wake() = 0; - - /* Dump EventHub state to a string. */ - virtual void dump(String8& dump) = 0; - - /* Called by the heatbeat to ensures that the reader has not deadlocked. */ - virtual void monitor() = 0; -}; - -class EventHub : public EventHubInterface -{ -public: - EventHub(); - - virtual uint32_t getDeviceClasses(int32_t deviceId) const; - - virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const; - - virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const; - - virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, - RawAbsoluteAxisInfo* outAxisInfo) const; - - virtual bool hasRelativeAxis(int32_t deviceId, int axis) const; - - virtual bool hasInputProperty(int32_t deviceId, int property) const; - - virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, - int32_t* outKeycode, uint32_t* outFlags) const; - - virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, - AxisInfo* outAxisInfo) const; - - virtual void setExcludedDevices(const Vector<String8>& devices); - - virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const; - virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const; - virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const; - virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const; - - virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, - const int32_t* keyCodes, uint8_t* outFlags) const; - - virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize); - - virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const; - virtual bool hasLed(int32_t deviceId, int32_t led) const; - virtual void setLedState(int32_t deviceId, int32_t led, bool on); - - virtual void getVirtualKeyDefinitions(int32_t deviceId, - Vector<VirtualKeyDefinition>& outVirtualKeys) const; - - virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const; - virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map); - - virtual void vibrate(int32_t deviceId, nsecs_t duration); - virtual void cancelVibrate(int32_t deviceId); - - virtual void requestReopenDevices(); - - virtual void wake(); - - virtual void dump(String8& dump); - virtual void monitor(); - -protected: - virtual ~EventHub(); - -private: - struct Device { - Device* next; - - int fd; // may be -1 if device is virtual - const int32_t id; - const String8 path; - const InputDeviceIdentifier identifier; - - uint32_t classes; - - uint8_t keyBitmask[(KEY_MAX + 1) / 8]; - uint8_t absBitmask[(ABS_MAX + 1) / 8]; - uint8_t relBitmask[(REL_MAX + 1) / 8]; - uint8_t swBitmask[(SW_MAX + 1) / 8]; - uint8_t ledBitmask[(LED_MAX + 1) / 8]; - uint8_t ffBitmask[(FF_MAX + 1) / 8]; - uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8]; - - String8 configurationFile; - PropertyMap* configuration; - VirtualKeyMap* virtualKeyMap; - KeyMap keyMap; - - sp<KeyCharacterMap> overlayKeyMap; - sp<KeyCharacterMap> combinedKeyMap; - - bool ffEffectPlaying; - int16_t ffEffectId; // initially -1 - - int32_t timestampOverrideSec; - int32_t timestampOverrideUsec; - - Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier); - ~Device(); - - void close(); - - inline bool isVirtual() const { return fd < 0; } - - const sp<KeyCharacterMap>& getKeyCharacterMap() const { - if (combinedKeyMap != NULL) { - return combinedKeyMap; - } - return keyMap.keyCharacterMap; - } - }; - - status_t openDeviceLocked(const char *devicePath); - void createVirtualKeyboardLocked(); - void addDeviceLocked(Device* device); - - status_t closeDeviceByPathLocked(const char *devicePath); - void closeDeviceLocked(Device* device); - void closeAllDevicesLocked(); - - status_t scanDirLocked(const char *dirname); - void scanDevicesLocked(); - status_t readNotifyLocked(); - - Device* getDeviceLocked(int32_t deviceId) const; - Device* getDeviceByPathLocked(const char* devicePath) const; - - bool hasKeycodeLocked(Device* device, int keycode) const; - - void loadConfigurationLocked(Device* device); - status_t loadVirtualKeyMapLocked(Device* device); - status_t loadKeyMapLocked(Device* device); - - bool isExternalDeviceLocked(Device* device); - - // Protect all internal state. - mutable Mutex mLock; - - // The actual id of the built-in keyboard, or NO_BUILT_IN_KEYBOARD if none. - // EventHub remaps the built-in keyboard to id 0 externally as required by the API. - enum { - // Must not conflict with any other assigned device ids, including - // the virtual keyboard id (-1). - NO_BUILT_IN_KEYBOARD = -2, - }; - int32_t mBuiltInKeyboardId; - - int32_t mNextDeviceId; - - KeyedVector<int32_t, Device*> mDevices; - - Device *mOpeningDevices; - Device *mClosingDevices; - - bool mNeedToSendFinishedDeviceScan; - bool mNeedToReopenDevices; - bool mNeedToScanDevices; - Vector<String8> mExcludedDevices; - - int mEpollFd; - int mINotifyFd; - int mWakeReadPipeFd; - int mWakeWritePipeFd; - - // Ids used for epoll notifications not associated with devices. - static const uint32_t EPOLL_ID_INOTIFY = 0x80000001; - static const uint32_t EPOLL_ID_WAKE = 0x80000002; - - // Epoll FD list size hint. - static const int EPOLL_SIZE_HINT = 8; - - // Maximum number of signalled FDs to handle at a time. - static const int EPOLL_MAX_EVENTS = 16; - - // The array of pending epoll events and the index of the next event to be handled. - struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS]; - size_t mPendingEventCount; - size_t mPendingEventIndex; - bool mPendingINotify; -}; - -}; // namespace android - -#endif // _RUNTIME_EVENT_HUB_H diff --git a/widget/gonk/libui/Input.cpp b/widget/gonk/libui/Input.cpp deleted file mode 100644 index 2208191e6..000000000 --- a/widget/gonk/libui/Input.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Input" -//#define LOG_NDEBUG 0 -#include "cutils_log.h" - -#include <math.h> -#include <limits.h> - -#include "Input.h" - -#ifdef HAVE_ANDROID_OS -#include <binder/Parcel.h> - -#include "SkPoint.h" -#include "SkMatrix.h" -#include "SkScalar.h" -#endif - -namespace android { - -// --- InputEvent --- - -void InputEvent::initialize(int32_t deviceId, int32_t source) { - mDeviceId = deviceId; - mSource = source; -} - -void InputEvent::initialize(const InputEvent& from) { - mDeviceId = from.mDeviceId; - mSource = from.mSource; -} - -// --- KeyEvent --- - -bool KeyEvent::hasDefaultAction(int32_t keyCode) { - switch (keyCode) { - case AKEYCODE_HOME: - case AKEYCODE_BACK: - case AKEYCODE_CALL: - case AKEYCODE_ENDCALL: - case AKEYCODE_VOLUME_UP: - case AKEYCODE_VOLUME_DOWN: - case AKEYCODE_VOLUME_MUTE: - case AKEYCODE_POWER: - case AKEYCODE_CAMERA: - case AKEYCODE_HEADSETHOOK: - case AKEYCODE_MENU: - case AKEYCODE_NOTIFICATION: - case AKEYCODE_FOCUS: - case AKEYCODE_SEARCH: - case AKEYCODE_MEDIA_PLAY: - case AKEYCODE_MEDIA_PAUSE: - case AKEYCODE_MEDIA_PLAY_PAUSE: - case AKEYCODE_MEDIA_STOP: - case AKEYCODE_MEDIA_NEXT: - case AKEYCODE_MEDIA_PREVIOUS: - case AKEYCODE_MEDIA_REWIND: - case AKEYCODE_MEDIA_RECORD: - case AKEYCODE_MEDIA_FAST_FORWARD: - case AKEYCODE_MUTE: - case AKEYCODE_BRIGHTNESS_DOWN: - case AKEYCODE_BRIGHTNESS_UP: - return true; - } - - return false; -} - -bool KeyEvent::hasDefaultAction() const { - return hasDefaultAction(getKeyCode()); -} - -bool KeyEvent::isSystemKey(int32_t keyCode) { - switch (keyCode) { - case AKEYCODE_MENU: - case AKEYCODE_SOFT_RIGHT: - case AKEYCODE_HOME: - case AKEYCODE_BACK: - case AKEYCODE_CALL: - case AKEYCODE_ENDCALL: - case AKEYCODE_VOLUME_UP: - case AKEYCODE_VOLUME_DOWN: - case AKEYCODE_VOLUME_MUTE: - case AKEYCODE_MUTE: - case AKEYCODE_POWER: - case AKEYCODE_HEADSETHOOK: - case AKEYCODE_MEDIA_PLAY: - case AKEYCODE_MEDIA_PAUSE: - case AKEYCODE_MEDIA_PLAY_PAUSE: - case AKEYCODE_MEDIA_STOP: - case AKEYCODE_MEDIA_NEXT: - case AKEYCODE_MEDIA_PREVIOUS: - case AKEYCODE_MEDIA_REWIND: - case AKEYCODE_MEDIA_RECORD: - case AKEYCODE_MEDIA_FAST_FORWARD: - case AKEYCODE_CAMERA: - case AKEYCODE_FOCUS: - case AKEYCODE_SEARCH: - case AKEYCODE_BRIGHTNESS_DOWN: - case AKEYCODE_BRIGHTNESS_UP: - return true; - } - - return false; -} - -bool KeyEvent::isSystemKey() const { - return isSystemKey(getKeyCode()); -} - -void KeyEvent::initialize( - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime) { - InputEvent::initialize(deviceId, source); - mAction = action; - mFlags = flags; - mKeyCode = keyCode; - mScanCode = scanCode; - mMetaState = metaState; - mRepeatCount = repeatCount; - mDownTime = downTime; - mEventTime = eventTime; -} - -void KeyEvent::initialize(const KeyEvent& from) { - InputEvent::initialize(from); - mAction = from.mAction; - mFlags = from.mFlags; - mKeyCode = from.mKeyCode; - mScanCode = from.mScanCode; - mMetaState = from.mMetaState; - mRepeatCount = from.mRepeatCount; - mDownTime = from.mDownTime; - mEventTime = from.mEventTime; -} - - -// --- PointerCoords --- - -float PointerCoords::getAxisValue(int32_t axis) const { - if (axis < 0 || axis > 63) { - return 0; - } - - uint64_t axisBit = 1LL << axis; - if (!(bits & axisBit)) { - return 0; - } - uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); - return values[index]; -} - -status_t PointerCoords::setAxisValue(int32_t axis, float value) { - if (axis < 0 || axis > 63) { - return NAME_NOT_FOUND; - } - - uint64_t axisBit = 1LL << axis; - uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); - if (!(bits & axisBit)) { - if (value == 0) { - return OK; // axes with value 0 do not need to be stored - } - uint32_t count = __builtin_popcountll(bits); - if (count >= MAX_AXES) { - tooManyAxes(axis); - return NO_MEMORY; - } - bits |= axisBit; - for (uint32_t i = count; i > index; i--) { - values[i] = values[i - 1]; - } - } - values[index] = value; - return OK; -} - -static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) { - float value = c.getAxisValue(axis); - if (value != 0) { - c.setAxisValue(axis, value * scaleFactor); - } -} - -void PointerCoords::scale(float scaleFactor) { - // No need to scale pressure or size since they are normalized. - // No need to scale orientation since it is meaningless to do so. - scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor); -} - -#ifdef HAVE_ANDROID_OS -status_t PointerCoords::readFromParcel(Parcel* parcel) { - bits = parcel->readInt64(); - - uint32_t count = __builtin_popcountll(bits); - if (count > MAX_AXES) { - return BAD_VALUE; - } - - for (uint32_t i = 0; i < count; i++) { - values[i] = parcel->readFloat(); - } - return OK; -} - -status_t PointerCoords::writeToParcel(Parcel* parcel) const { - parcel->writeInt64(bits); - - uint32_t count = __builtin_popcountll(bits); - for (uint32_t i = 0; i < count; i++) { - parcel->writeFloat(values[i]); - } - return OK; -} -#endif - -void PointerCoords::tooManyAxes(int axis) { - ALOGW("Could not set value for axis %d because the PointerCoords structure is full and " - "cannot contain more than %d axis values.", axis, int(MAX_AXES)); -} - -bool PointerCoords::operator==(const PointerCoords& other) const { - if (bits != other.bits) { - return false; - } - uint32_t count = __builtin_popcountll(bits); - for (uint32_t i = 0; i < count; i++) { - if (values[i] != other.values[i]) { - return false; - } - } - return true; -} - -void PointerCoords::copyFrom(const PointerCoords& other) { - bits = other.bits; - uint32_t count = __builtin_popcountll(bits); - for (uint32_t i = 0; i < count; i++) { - values[i] = other.values[i]; - } -} - - -// --- PointerProperties --- - -bool PointerProperties::operator==(const PointerProperties& other) const { - return id == other.id - && toolType == other.toolType; -} - -void PointerProperties::copyFrom(const PointerProperties& other) { - id = other.id; - toolType = other.toolType; -} - - -// --- MotionEvent --- - -void MotionEvent::initialize( - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - size_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords) { - InputEvent::initialize(deviceId, source); - mAction = action; - mFlags = flags; - mEdgeFlags = edgeFlags; - mMetaState = metaState; - mButtonState = buttonState; - mXOffset = xOffset; - mYOffset = yOffset; - mXPrecision = xPrecision; - mYPrecision = yPrecision; - mDownTime = downTime; - mPointerProperties.clear(); - mPointerProperties.appendArray(pointerProperties, pointerCount); - mSampleEventTimes.clear(); - mSamplePointerCoords.clear(); - addSample(eventTime, pointerCoords); -} - -void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { - InputEvent::initialize(other->mDeviceId, other->mSource); - mAction = other->mAction; - mFlags = other->mFlags; - mEdgeFlags = other->mEdgeFlags; - mMetaState = other->mMetaState; - mButtonState = other->mButtonState; - mXOffset = other->mXOffset; - mYOffset = other->mYOffset; - mXPrecision = other->mXPrecision; - mYPrecision = other->mYPrecision; - mDownTime = other->mDownTime; - mPointerProperties = other->mPointerProperties; - - if (keepHistory) { - mSampleEventTimes = other->mSampleEventTimes; - mSamplePointerCoords = other->mSamplePointerCoords; - } else { - mSampleEventTimes.clear(); - mSampleEventTimes.push(other->getEventTime()); - mSamplePointerCoords.clear(); - size_t pointerCount = other->getPointerCount(); - size_t historySize = other->getHistorySize(); - mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array() - + (historySize * pointerCount), pointerCount); - } -} - -void MotionEvent::addSample( - int64_t eventTime, - const PointerCoords* pointerCoords) { - mSampleEventTimes.push(eventTime); - mSamplePointerCoords.appendArray(pointerCoords, getPointerCount()); -} - -const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { - return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; -} - -float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { - return getRawPointerCoords(pointerIndex)->getAxisValue(axis); -} - -float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { - float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis); - switch (axis) { - case AMOTION_EVENT_AXIS_X: - return value + mXOffset; - case AMOTION_EVENT_AXIS_Y: - return value + mYOffset; - } - return value; -} - -const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( - size_t pointerIndex, size_t historicalIndex) const { - return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; -} - -float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, - size_t historicalIndex) const { - return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); -} - -float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, - size_t historicalIndex) const { - float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); - switch (axis) { - case AMOTION_EVENT_AXIS_X: - return value + mXOffset; - case AMOTION_EVENT_AXIS_Y: - return value + mYOffset; - } - return value; -} - -ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { - size_t pointerCount = mPointerProperties.size(); - for (size_t i = 0; i < pointerCount; i++) { - if (mPointerProperties.itemAt(i).id == pointerId) { - return i; - } - } - return -1; -} - -void MotionEvent::offsetLocation(float xOffset, float yOffset) { - mXOffset += xOffset; - mYOffset += yOffset; -} - -void MotionEvent::scale(float scaleFactor) { - mXOffset *= scaleFactor; - mYOffset *= scaleFactor; - mXPrecision *= scaleFactor; - mYPrecision *= scaleFactor; - - size_t numSamples = mSamplePointerCoords.size(); - for (size_t i = 0; i < numSamples; i++) { - mSamplePointerCoords.editItemAt(i).scale(scaleFactor); - } -} - -#ifdef HAVE_ANDROID_OS -static inline float transformAngle(const SkMatrix* matrix, float angleRadians) { - // Construct and transform a vector oriented at the specified clockwise angle from vertical. - // Coordinate system: down is increasing Y, right is increasing X. - SkPoint vector; - vector.fX = SkFloatToScalar(sinf(angleRadians)); - vector.fY = SkFloatToScalar(-cosf(angleRadians)); - matrix->mapVectors(& vector, 1); - - // Derive the transformed vector's clockwise angle from vertical. - float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY)); - if (result < - M_PI_2) { - result += M_PI; - } else if (result > M_PI_2) { - result -= M_PI; - } - return result; -} - -void MotionEvent::transform(const SkMatrix* matrix) { - float oldXOffset = mXOffset; - float oldYOffset = mYOffset; - - // The tricky part of this implementation is to preserve the value of - // rawX and rawY. So we apply the transformation to the first point - // then derive an appropriate new X/Y offset that will preserve rawX and rawY. - SkPoint point; - float rawX = getRawX(0); - float rawY = getRawY(0); - matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset), - & point); - float newX = SkScalarToFloat(point.fX); - float newY = SkScalarToFloat(point.fY); - float newXOffset = newX - rawX; - float newYOffset = newY - rawY; - - mXOffset = newXOffset; - mYOffset = newYOffset; - - // Apply the transformation to all samples. - size_t numSamples = mSamplePointerCoords.size(); - for (size_t i = 0; i < numSamples; i++) { - PointerCoords& c = mSamplePointerCoords.editItemAt(i); - float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset; - float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset; - matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point); - c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset); - c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset); - - float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); - c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation)); - } -} - -status_t MotionEvent::readFromParcel(Parcel* parcel) { - size_t pointerCount = parcel->readInt32(); - size_t sampleCount = parcel->readInt32(); - if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) { - return BAD_VALUE; - } - - mDeviceId = parcel->readInt32(); - mSource = parcel->readInt32(); - mAction = parcel->readInt32(); - mFlags = parcel->readInt32(); - mEdgeFlags = parcel->readInt32(); - mMetaState = parcel->readInt32(); - mButtonState = parcel->readInt32(); - mXOffset = parcel->readFloat(); - mYOffset = parcel->readFloat(); - mXPrecision = parcel->readFloat(); - mYPrecision = parcel->readFloat(); - mDownTime = parcel->readInt64(); - - mPointerProperties.clear(); - mPointerProperties.setCapacity(pointerCount); - mSampleEventTimes.clear(); - mSampleEventTimes.setCapacity(sampleCount); - mSamplePointerCoords.clear(); - mSamplePointerCoords.setCapacity(sampleCount * pointerCount); - - for (size_t i = 0; i < pointerCount; i++) { - mPointerProperties.push(); - PointerProperties& properties = mPointerProperties.editTop(); - properties.id = parcel->readInt32(); - properties.toolType = parcel->readInt32(); - } - - while (sampleCount-- > 0) { - mSampleEventTimes.push(parcel->readInt64()); - for (size_t i = 0; i < pointerCount; i++) { - mSamplePointerCoords.push(); - status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel); - if (status) { - return status; - } - } - } - return OK; -} - -status_t MotionEvent::writeToParcel(Parcel* parcel) const { - size_t pointerCount = mPointerProperties.size(); - size_t sampleCount = mSampleEventTimes.size(); - - parcel->writeInt32(pointerCount); - parcel->writeInt32(sampleCount); - - parcel->writeInt32(mDeviceId); - parcel->writeInt32(mSource); - parcel->writeInt32(mAction); - parcel->writeInt32(mFlags); - parcel->writeInt32(mEdgeFlags); - parcel->writeInt32(mMetaState); - parcel->writeInt32(mButtonState); - parcel->writeFloat(mXOffset); - parcel->writeFloat(mYOffset); - parcel->writeFloat(mXPrecision); - parcel->writeFloat(mYPrecision); - parcel->writeInt64(mDownTime); - - for (size_t i = 0; i < pointerCount; i++) { - const PointerProperties& properties = mPointerProperties.itemAt(i); - parcel->writeInt32(properties.id); - parcel->writeInt32(properties.toolType); - } - - const PointerCoords* pc = mSamplePointerCoords.array(); - for (size_t h = 0; h < sampleCount; h++) { - parcel->writeInt64(mSampleEventTimes.itemAt(h)); - for (size_t i = 0; i < pointerCount; i++) { - status_t status = (pc++)->writeToParcel(parcel); - if (status) { - return status; - } - } - } - return OK; -} -#endif - -bool MotionEvent::isTouchEvent(int32_t source, int32_t action) { - if (source & AINPUT_SOURCE_CLASS_POINTER) { - // Specifically excludes HOVER_MOVE and SCROLL. - switch (action & AMOTION_EVENT_ACTION_MASK) { - case AMOTION_EVENT_ACTION_DOWN: - case AMOTION_EVENT_ACTION_MOVE: - case AMOTION_EVENT_ACTION_UP: - case AMOTION_EVENT_ACTION_POINTER_DOWN: - case AMOTION_EVENT_ACTION_POINTER_UP: - case AMOTION_EVENT_ACTION_CANCEL: - case AMOTION_EVENT_ACTION_OUTSIDE: - return true; - } - } - return false; -} - - -// --- PooledInputEventFactory --- - -PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) : - mMaxPoolSize(maxPoolSize) { -} - -PooledInputEventFactory::~PooledInputEventFactory() { - for (size_t i = 0; i < mKeyEventPool.size(); i++) { - delete mKeyEventPool.itemAt(i); - } - for (size_t i = 0; i < mMotionEventPool.size(); i++) { - delete mMotionEventPool.itemAt(i); - } -} - -KeyEvent* PooledInputEventFactory::createKeyEvent() { - if (!mKeyEventPool.isEmpty()) { - KeyEvent* event = mKeyEventPool.top(); - mKeyEventPool.pop(); - return event; - } - return new KeyEvent(); -} - -MotionEvent* PooledInputEventFactory::createMotionEvent() { - if (!mMotionEventPool.isEmpty()) { - MotionEvent* event = mMotionEventPool.top(); - mMotionEventPool.pop(); - return event; - } - return new MotionEvent(); -} - -void PooledInputEventFactory::recycle(InputEvent* event) { - switch (event->getType()) { - case AINPUT_EVENT_TYPE_KEY: - if (mKeyEventPool.size() < mMaxPoolSize) { - mKeyEventPool.push(static_cast<KeyEvent*>(event)); - return; - } - break; - case AINPUT_EVENT_TYPE_MOTION: - if (mMotionEventPool.size() < mMaxPoolSize) { - mMotionEventPool.push(static_cast<MotionEvent*>(event)); - return; - } - break; - } - delete event; -} - -} // namespace android diff --git a/widget/gonk/libui/Input.h b/widget/gonk/libui/Input.h deleted file mode 100644 index 3d958bfab..000000000 --- a/widget/gonk/libui/Input.h +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_INPUT_H -#define _ANDROIDFW_INPUT_H - -/** - * Native input event structures. - */ - -#include "android_input.h" -#include <utils/Vector.h> -#include <utils/KeyedVector.h> -#include <utils/Timers.h> -#include <utils/RefBase.h> -#include <utils/String8.h> - -#ifdef HAVE_ANDROID_OS -class SkMatrix; -#endif - -/* - * Additional private constants not defined in ndk/ui/input.h. - */ -enum { - /* Signifies that the key is being predispatched */ - AKEY_EVENT_FLAG_PREDISPATCH = 0x20000000, - - /* Private control to determine when an app is tracking a key sequence. */ - AKEY_EVENT_FLAG_START_TRACKING = 0x40000000, - - /* Key event is inconsistent with previously sent key events. */ - AKEY_EVENT_FLAG_TAINTED = 0x80000000, -}; - -enum { - /* Motion event is inconsistent with previously sent motion events. */ - AMOTION_EVENT_FLAG_TAINTED = 0x80000000, -}; - -enum { - /* Used when a motion event is not associated with any display. - * Typically used for non-pointer events. */ - ADISPLAY_ID_NONE = -1, - - /* The default display id. */ - ADISPLAY_ID_DEFAULT = 0, -}; - -enum { - /* - * Indicates that an input device has switches. - * This input source flag is hidden from the API because switches are only used by the system - * and applications have no way to interact with them. - */ - AINPUT_SOURCE_SWITCH = 0x80000000, -}; - -/* - * SystemUiVisibility constants from View. - */ -enum { - ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE = 0, - ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN = 0x00000001, -}; - -/* - * Maximum number of pointers supported per motion event. - * Smallest number of pointers is 1. - * (We want at least 10 but some touch controllers obstensibly configured for 10 pointers - * will occasionally emit 11. There is not much harm making this constant bigger.) - */ -#define MAX_POINTERS 16 - -/* - * Maximum pointer id value supported in a motion event. - * Smallest pointer id is 0. - * (This is limited by our use of BitSet32 to track pointer assignments.) - */ -#define MAX_POINTER_ID 31 - -/* - * Declare a concrete type for the NDK's input event forward declaration. - */ -struct AInputEvent { - virtual ~AInputEvent() { } -}; - -/* - * Declare a concrete type for the NDK's input device forward declaration. - */ -struct AInputDevice { - virtual ~AInputDevice() { } -}; - - -namespace android { - -#ifdef HAVE_ANDROID_OS -class Parcel; -#endif - -/* - * Flags that flow alongside events in the input dispatch system to help with certain - * policy decisions such as waking from device sleep. - * - * These flags are also defined in frameworks/base/core/java/android/view/WindowManagerPolicy.java. - */ -enum { - /* These flags originate in RawEvents and are generally set in the key map. - * NOTE: If you edit these flags, also edit labels in KeycodeLabels.h. */ - - POLICY_FLAG_WAKE = 0x00000001, - POLICY_FLAG_WAKE_DROPPED = 0x00000002, - POLICY_FLAG_SHIFT = 0x00000004, - POLICY_FLAG_CAPS_LOCK = 0x00000008, - POLICY_FLAG_ALT = 0x00000010, - POLICY_FLAG_ALT_GR = 0x00000020, - POLICY_FLAG_MENU = 0x00000040, - POLICY_FLAG_LAUNCHER = 0x00000080, - POLICY_FLAG_VIRTUAL = 0x00000100, - POLICY_FLAG_FUNCTION = 0x00000200, - - POLICY_FLAG_RAW_MASK = 0x0000ffff, - - /* These flags are set by the input dispatcher. */ - - // Indicates that the input event was injected. - POLICY_FLAG_INJECTED = 0x01000000, - - // Indicates that the input event is from a trusted source such as a directly attached - // input device or an application with system-wide event injection permission. - POLICY_FLAG_TRUSTED = 0x02000000, - - // Indicates that the input event has passed through an input filter. - POLICY_FLAG_FILTERED = 0x04000000, - - // Disables automatic key repeating behavior. - POLICY_FLAG_DISABLE_KEY_REPEAT = 0x08000000, - - /* These flags are set by the input reader policy as it intercepts each event. */ - - // Indicates that the screen was off when the event was received and the event - // should wake the device. - POLICY_FLAG_WOKE_HERE = 0x10000000, - - // Indicates that the screen was dim when the event was received and the event - // should brighten the device. - POLICY_FLAG_BRIGHT_HERE = 0x20000000, - - // Indicates that the event should be dispatched to applications. - // The input event should still be sent to the InputDispatcher so that it can see all - // input events received include those that it will not deliver. - POLICY_FLAG_PASS_TO_USER = 0x40000000, -}; - -/* - * Pointer coordinate data. - */ -struct PointerCoords { - enum { MAX_AXES = 14 }; // 14 so that sizeof(PointerCoords) == 64 - - // Bitfield of axes that are present in this structure. - uint64_t bits; - - // Values of axes that are stored in this structure packed in order by axis id - // for each axis that is present in the structure according to 'bits'. - float values[MAX_AXES]; - - inline void clear() { - bits = 0; - } - - float getAxisValue(int32_t axis) const; - status_t setAxisValue(int32_t axis, float value); - - void scale(float scale); - - inline float getX() const { - return getAxisValue(AMOTION_EVENT_AXIS_X); - } - - inline float getY() const { - return getAxisValue(AMOTION_EVENT_AXIS_Y); - } - -#ifdef HAVE_ANDROID_OS - status_t readFromParcel(Parcel* parcel); - status_t writeToParcel(Parcel* parcel) const; -#endif - - bool operator==(const PointerCoords& other) const; - inline bool operator!=(const PointerCoords& other) const { - return !(*this == other); - } - - void copyFrom(const PointerCoords& other); - -private: - void tooManyAxes(int axis); -}; - -/* - * Pointer property data. - */ -struct PointerProperties { - // The id of the pointer. - int32_t id; - - // The pointer tool type. - int32_t toolType; - - inline void clear() { - id = -1; - toolType = 0; - } - - bool operator==(const PointerProperties& other) const; - inline bool operator!=(const PointerProperties& other) const { - return !(*this == other); - } - - void copyFrom(const PointerProperties& other); -}; - -/* - * Input events. - */ -class InputEvent : public AInputEvent { -public: - virtual ~InputEvent() { } - - virtual int32_t getType() const = 0; - - inline int32_t getDeviceId() const { return mDeviceId; } - - inline int32_t getSource() const { return mSource; } - - inline void setSource(int32_t source) { mSource = source; } - -protected: - void initialize(int32_t deviceId, int32_t source); - void initialize(const InputEvent& from); - - int32_t mDeviceId; - int32_t mSource; -}; - -/* - * Key events. - */ -class KeyEvent : public InputEvent { -public: - virtual ~KeyEvent() { } - - virtual int32_t getType() const { return AINPUT_EVENT_TYPE_KEY; } - - inline int32_t getAction() const { return mAction; } - - inline int32_t getFlags() const { return mFlags; } - - inline void setFlags(int32_t flags) { mFlags = flags; } - - inline int32_t getKeyCode() const { return mKeyCode; } - - inline int32_t getScanCode() const { return mScanCode; } - - inline int32_t getMetaState() const { return mMetaState; } - - inline int32_t getRepeatCount() const { return mRepeatCount; } - - inline nsecs_t getDownTime() const { return mDownTime; } - - inline nsecs_t getEventTime() const { return mEventTime; } - - // Return true if this event may have a default action implementation. - static bool hasDefaultAction(int32_t keyCode); - bool hasDefaultAction() const; - - // Return true if this event represents a system key. - static bool isSystemKey(int32_t keyCode); - bool isSystemKey() const; - - void initialize( - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime); - void initialize(const KeyEvent& from); - -protected: - int32_t mAction; - int32_t mFlags; - int32_t mKeyCode; - int32_t mScanCode; - int32_t mMetaState; - int32_t mRepeatCount; - nsecs_t mDownTime; - nsecs_t mEventTime; -}; - -/* - * Motion events. - */ -class MotionEvent : public InputEvent { -public: - virtual ~MotionEvent() { } - - virtual int32_t getType() const { return AINPUT_EVENT_TYPE_MOTION; } - - inline int32_t getAction() const { return mAction; } - - inline int32_t getActionMasked() const { return mAction & AMOTION_EVENT_ACTION_MASK; } - - inline int32_t getActionIndex() const { - return (mAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) - >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; - } - - inline void setAction(int32_t action) { mAction = action; } - - inline int32_t getFlags() const { return mFlags; } - - inline void setFlags(int32_t flags) { mFlags = flags; } - - inline int32_t getEdgeFlags() const { return mEdgeFlags; } - - inline void setEdgeFlags(int32_t edgeFlags) { mEdgeFlags = edgeFlags; } - - inline int32_t getMetaState() const { return mMetaState; } - - inline void setMetaState(int32_t metaState) { mMetaState = metaState; } - - inline int32_t getButtonState() const { return mButtonState; } - - inline float getXOffset() const { return mXOffset; } - - inline float getYOffset() const { return mYOffset; } - - inline float getXPrecision() const { return mXPrecision; } - - inline float getYPrecision() const { return mYPrecision; } - - inline nsecs_t getDownTime() const { return mDownTime; } - - inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; } - - inline size_t getPointerCount() const { return mPointerProperties.size(); } - - inline const PointerProperties* getPointerProperties(size_t pointerIndex) const { - return &mPointerProperties[pointerIndex]; - } - - inline int32_t getPointerId(size_t pointerIndex) const { - return mPointerProperties[pointerIndex].id; - } - - inline int32_t getToolType(size_t pointerIndex) const { - return mPointerProperties[pointerIndex].toolType; - } - - inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; } - - const PointerCoords* getRawPointerCoords(size_t pointerIndex) const; - - float getRawAxisValue(int32_t axis, size_t pointerIndex) const; - - inline float getRawX(size_t pointerIndex) const { - return getRawAxisValue(AMOTION_EVENT_AXIS_X, pointerIndex); - } - - inline float getRawY(size_t pointerIndex) const { - return getRawAxisValue(AMOTION_EVENT_AXIS_Y, pointerIndex); - } - - float getAxisValue(int32_t axis, size_t pointerIndex) const; - - inline float getX(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_X, pointerIndex); - } - - inline float getY(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_Y, pointerIndex); - } - - inline float getPressure(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pointerIndex); - } - - inline float getSize(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_SIZE, pointerIndex); - } - - inline float getTouchMajor(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, pointerIndex); - } - - inline float getTouchMinor(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, pointerIndex); - } - - inline float getToolMajor(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, pointerIndex); - } - - inline float getToolMinor(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, pointerIndex); - } - - inline float getOrientation(size_t pointerIndex) const { - return getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, pointerIndex); - } - - inline size_t getHistorySize() const { return mSampleEventTimes.size() - 1; } - - inline nsecs_t getHistoricalEventTime(size_t historicalIndex) const { - return mSampleEventTimes[historicalIndex]; - } - - const PointerCoords* getHistoricalRawPointerCoords( - size_t pointerIndex, size_t historicalIndex) const; - - float getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, - size_t historicalIndex) const; - - inline float getHistoricalRawX(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalRawAxisValue( - AMOTION_EVENT_AXIS_X, pointerIndex, historicalIndex); - } - - inline float getHistoricalRawY(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalRawAxisValue( - AMOTION_EVENT_AXIS_Y, pointerIndex, historicalIndex); - } - - float getHistoricalAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const; - - inline float getHistoricalX(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_X, pointerIndex, historicalIndex); - } - - inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_Y, pointerIndex, historicalIndex); - } - - inline float getHistoricalPressure(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_PRESSURE, pointerIndex, historicalIndex); - } - - inline float getHistoricalSize(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_SIZE, pointerIndex, historicalIndex); - } - - inline float getHistoricalTouchMajor(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_TOUCH_MAJOR, pointerIndex, historicalIndex); - } - - inline float getHistoricalTouchMinor(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_TOUCH_MINOR, pointerIndex, historicalIndex); - } - - inline float getHistoricalToolMajor(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_TOOL_MAJOR, pointerIndex, historicalIndex); - } - - inline float getHistoricalToolMinor(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_TOOL_MINOR, pointerIndex, historicalIndex); - } - - inline float getHistoricalOrientation(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalAxisValue( - AMOTION_EVENT_AXIS_ORIENTATION, pointerIndex, historicalIndex); - } - - ssize_t findPointerIndex(int32_t pointerId) const; - - void initialize( - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - size_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords); - - void copyFrom(const MotionEvent* other, bool keepHistory); - - void addSample( - nsecs_t eventTime, - const PointerCoords* pointerCoords); - - void offsetLocation(float xOffset, float yOffset); - - void scale(float scaleFactor); - -#ifdef HAVE_ANDROID_OS - void transform(const SkMatrix* matrix); - - status_t readFromParcel(Parcel* parcel); - status_t writeToParcel(Parcel* parcel) const; -#endif - - static bool isTouchEvent(int32_t source, int32_t action); - inline bool isTouchEvent() const { - return isTouchEvent(mSource, mAction); - } - - // Low-level accessors. - inline const PointerProperties* getPointerProperties() const { - return mPointerProperties.array(); - } - inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); } - inline const PointerCoords* getSamplePointerCoords() const { - return mSamplePointerCoords.array(); - } - -protected: - int32_t mAction; - int32_t mFlags; - int32_t mEdgeFlags; - int32_t mMetaState; - int32_t mButtonState; - float mXOffset; - float mYOffset; - float mXPrecision; - float mYPrecision; - nsecs_t mDownTime; - Vector<PointerProperties> mPointerProperties; - Vector<nsecs_t> mSampleEventTimes; - Vector<PointerCoords> mSamplePointerCoords; -}; - -/* - * Input event factory. - */ -class InputEventFactoryInterface { -protected: - virtual ~InputEventFactoryInterface() { } - -public: - InputEventFactoryInterface() { } - - virtual KeyEvent* createKeyEvent() = 0; - virtual MotionEvent* createMotionEvent() = 0; -}; - -/* - * A simple input event factory implementation that uses a single preallocated instance - * of each type of input event that are reused for each request. - */ -class PreallocatedInputEventFactory : public InputEventFactoryInterface { -public: - PreallocatedInputEventFactory() { } - virtual ~PreallocatedInputEventFactory() { } - - virtual KeyEvent* createKeyEvent() { return & mKeyEvent; } - virtual MotionEvent* createMotionEvent() { return & mMotionEvent; } - -private: - KeyEvent mKeyEvent; - MotionEvent mMotionEvent; -}; - -/* - * An input event factory implementation that maintains a pool of input events. - */ -class PooledInputEventFactory : public InputEventFactoryInterface { -public: - PooledInputEventFactory(size_t maxPoolSize = 20); - virtual ~PooledInputEventFactory(); - - virtual KeyEvent* createKeyEvent(); - virtual MotionEvent* createMotionEvent(); - - void recycle(InputEvent* event); - -private: - const size_t mMaxPoolSize; - - Vector<KeyEvent*> mKeyEventPool; - Vector<MotionEvent*> mMotionEventPool; -}; - -} // namespace android - -#endif // _ANDROIDFW_INPUT_H diff --git a/widget/gonk/libui/InputApplication.cpp b/widget/gonk/libui/InputApplication.cpp deleted file mode 100644 index ce432356b..000000000 --- a/widget/gonk/libui/InputApplication.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputApplication" - -#include "InputApplication.h" - -#include "cutils_log.h" - -namespace android { - -// --- InputApplicationHandle --- - -InputApplicationHandle::InputApplicationHandle() : - mInfo(NULL) { -} - -InputApplicationHandle::~InputApplicationHandle() { - delete mInfo; -} - -void InputApplicationHandle::releaseInfo() { - if (mInfo) { - delete mInfo; - mInfo = NULL; - } -} - -} // namespace android diff --git a/widget/gonk/libui/InputApplication.h b/widget/gonk/libui/InputApplication.h deleted file mode 100644 index ba789559c..000000000 --- a/widget/gonk/libui/InputApplication.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UI_INPUT_APPLICATION_H -#define _UI_INPUT_APPLICATION_H - -#include "Input.h" - -#include <utils/RefBase.h> -#include <utils/Timers.h> -#include <utils/String8.h> - -namespace android { - -/* - * Describes the properties of an application that can receive input. - */ -struct InputApplicationInfo { - String8 name; - nsecs_t dispatchingTimeout; -}; - - -/* - * Handle for an application that can receive input. - * - * Used by the native input dispatcher as a handle for the window manager objects - * that describe an application. - */ -class InputApplicationHandle : public RefBase { -public: - inline const InputApplicationInfo* getInfo() const { - return mInfo; - } - - inline String8 getName() const { - return mInfo ? mInfo->name : String8("<invalid>"); - } - - inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const { - return mInfo ? mInfo->dispatchingTimeout : defaultValue; - } - - /** - * Requests that the state of this object be updated to reflect - * the most current available information about the application. - * - * This method should only be called from within the input dispatcher's - * critical section. - * - * Returns true on success, or false if the handle is no longer valid. - */ - virtual bool updateInfo() = 0; - - /** - * Releases the storage used by the associated information when it is - * no longer needed. - */ - void releaseInfo(); - -protected: - InputApplicationHandle(); - virtual ~InputApplicationHandle(); - - InputApplicationInfo* mInfo; -}; - -} // namespace android - -#endif // _UI_INPUT_APPLICATION_H diff --git a/widget/gonk/libui/InputDevice.cpp b/widget/gonk/libui/InputDevice.cpp deleted file mode 100644 index 01a437dd4..000000000 --- a/widget/gonk/libui/InputDevice.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputDevice" - -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> - -#include "InputDevice.h" - -namespace android { - -static const char* CONFIGURATION_FILE_DIR[] = { - "idc/", - "keylayout/", - "keychars/", -}; - -static const char* CONFIGURATION_FILE_EXTENSION[] = { - ".idc", - ".kl", - ".kcm", -}; - -static bool isValidNameChar(char ch) { - return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_'); -} - -static void appendInputDeviceConfigurationFileRelativePath(String8& path, - const String8& name, InputDeviceConfigurationFileType type) { - path.append(CONFIGURATION_FILE_DIR[type]); - for (size_t i = 0; i < name.length(); i++) { - char ch = name[i]; - if (!isValidNameChar(ch)) { - ch = '_'; - } - path.append(&ch, 1); - } - path.append(CONFIGURATION_FILE_EXTENSION[type]); -} - -String8 getInputDeviceConfigurationFilePathByDeviceIdentifier( - const InputDeviceIdentifier& deviceIdentifier, - InputDeviceConfigurationFileType type) { - if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) { - if (deviceIdentifier.version != 0) { - // Try vendor product version. - String8 versionPath(getInputDeviceConfigurationFilePathByName( - String8::format("Vendor_%04x_Product_%04x_Version_%04x", - deviceIdentifier.vendor, deviceIdentifier.product, - deviceIdentifier.version), - type)); - if (!versionPath.isEmpty()) { - return versionPath; - } - } - - // Try vendor product. - String8 productPath(getInputDeviceConfigurationFilePathByName( - String8::format("Vendor_%04x_Product_%04x", - deviceIdentifier.vendor, deviceIdentifier.product), - type)); - if (!productPath.isEmpty()) { - return productPath; - } - } - - // Try device name. - return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type); -} - -String8 getInputDeviceConfigurationFilePathByName( - const String8& name, InputDeviceConfigurationFileType type) { - // Search system repository. - String8 path; - path.setTo(getenv("ANDROID_ROOT")); - path.append("/usr/"); - appendInputDeviceConfigurationFileRelativePath(path, name, type); -#if DEBUG_PROBE - ALOGD("Probing for system provided input device configuration file: path='%s'", path.string()); -#endif - if (!access(path.string(), R_OK)) { -#if DEBUG_PROBE - ALOGD("Found"); -#endif - return path; - } - - // Search user repository. - // TODO Should only look here if not in safe mode. - path.setTo(getenv("ANDROID_DATA")); - path.append("/system/devices/"); - appendInputDeviceConfigurationFileRelativePath(path, name, type); -#if DEBUG_PROBE - ALOGD("Probing for system user input device configuration file: path='%s'", path.string()); -#endif - if (!access(path.string(), R_OK)) { -#if DEBUG_PROBE - ALOGD("Found"); -#endif - return path; - } - - // Not found. -#if DEBUG_PROBE - ALOGD("Probe failed to find input device configuration file: name='%s', type=%d", - name.string(), type); -#endif - return String8(); -} - - -// --- InputDeviceInfo --- - -InputDeviceInfo::InputDeviceInfo() { - initialize(-1, -1, InputDeviceIdentifier(), String8(), false); -} - -InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : - mId(other.mId), mGeneration(other.mGeneration), mIdentifier(other.mIdentifier), - mAlias(other.mAlias), mIsExternal(other.mIsExternal), mSources(other.mSources), - mKeyboardType(other.mKeyboardType), - mKeyCharacterMap(other.mKeyCharacterMap), - mHasVibrator(other.mHasVibrator), - mMotionRanges(other.mMotionRanges) { -} - -InputDeviceInfo::~InputDeviceInfo() { -} - -void InputDeviceInfo::initialize(int32_t id, int32_t generation, - const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal) { - mId = id; - mGeneration = generation; - mIdentifier = identifier; - mAlias = alias; - mIsExternal = isExternal; - mSources = 0; - mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; - mHasVibrator = false; - mMotionRanges.clear(); -} - -const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( - int32_t axis, uint32_t source) const { - size_t numRanges = mMotionRanges.size(); - for (size_t i = 0; i < numRanges; i++) { - const MotionRange& range = mMotionRanges.itemAt(i); - if (range.axis == axis && range.source == source) { - return ⦥ - } - } - return NULL; -} - -void InputDeviceInfo::addSource(uint32_t source) { - mSources |= source; -} - -void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, - float flat, float fuzz, float resolution) { - MotionRange range = { axis, source, min, max, flat, fuzz, resolution }; - mMotionRanges.add(range); -} - -void InputDeviceInfo::addMotionRange(const MotionRange& range) { - mMotionRanges.add(range); -} - -} // namespace android diff --git a/widget/gonk/libui/InputDevice.h b/widget/gonk/libui/InputDevice.h deleted file mode 100644 index 0ab5863c9..000000000 --- a/widget/gonk/libui/InputDevice.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_INPUT_DEVICE_H -#define _ANDROIDFW_INPUT_DEVICE_H - -#include "Input.h" -#include "KeyCharacterMap.h" - -namespace android { - -/* - * Identifies a device. - */ -struct InputDeviceIdentifier { - inline InputDeviceIdentifier() : - bus(0), vendor(0), product(0), version(0) { - } - - // Information provided by the kernel. - String8 name; - String8 location; - String8 uniqueId; - uint16_t bus; - uint16_t vendor; - uint16_t product; - uint16_t version; - - // A composite input device descriptor string that uniquely identifies the device - // even across reboots or reconnections. The value of this field is used by - // upper layers of the input system to associate settings with individual devices. - // It is hashed from whatever kernel provided information is available. - // Ideally, the way this value is computed should not change between Android releases - // because that would invalidate persistent settings that rely on it. - String8 descriptor; -}; - -/* - * Describes the characteristics and capabilities of an input device. - */ -class InputDeviceInfo { -public: - InputDeviceInfo(); - InputDeviceInfo(const InputDeviceInfo& other); - ~InputDeviceInfo(); - - struct MotionRange { - int32_t axis; - uint32_t source; - float min; - float max; - float flat; - float fuzz; - float resolution; - }; - - void initialize(int32_t id, int32_t generation, const InputDeviceIdentifier& identifier, - const String8& alias, bool isExternal); - - inline int32_t getId() const { return mId; } - inline int32_t getGeneration() const { return mGeneration; } - inline const InputDeviceIdentifier& getIdentifier() const { return mIdentifier; } - inline const String8& getAlias() const { return mAlias; } - inline const String8& getDisplayName() const { - return mAlias.isEmpty() ? mIdentifier.name : mAlias; - } - inline bool isExternal() const { return mIsExternal; } - inline uint32_t getSources() const { return mSources; } - - const MotionRange* getMotionRange(int32_t axis, uint32_t source) const; - - void addSource(uint32_t source); - void addMotionRange(int32_t axis, uint32_t source, - float min, float max, float flat, float fuzz, float resolution); - void addMotionRange(const MotionRange& range); - - inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } - inline int32_t getKeyboardType() const { return mKeyboardType; } - - inline void setKeyCharacterMap(const sp<KeyCharacterMap>& value) { - mKeyCharacterMap = value; - } - - inline sp<KeyCharacterMap> getKeyCharacterMap() const { - return mKeyCharacterMap; - } - - inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; } - inline bool hasVibrator() const { return mHasVibrator; } - - inline const Vector<MotionRange>& getMotionRanges() const { - return mMotionRanges; - } - -private: - int32_t mId; - int32_t mGeneration; - InputDeviceIdentifier mIdentifier; - String8 mAlias; - bool mIsExternal; - uint32_t mSources; - int32_t mKeyboardType; - sp<KeyCharacterMap> mKeyCharacterMap; - bool mHasVibrator; - - Vector<MotionRange> mMotionRanges; -}; - -/* Types of input device configuration files. */ -enum InputDeviceConfigurationFileType { - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0, /* .idc file */ - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT = 1, /* .kl file */ - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP = 2, /* .kcm file */ -}; - -/* - * Gets the path of an input device configuration file, if one is available. - * Considers both system provided and user installed configuration files. - * - * The device identifier is used to construct several default configuration file - * names to try based on the device name, vendor, product, and version. - * - * Returns an empty string if not found. - */ -extern String8 getInputDeviceConfigurationFilePathByDeviceIdentifier( - const InputDeviceIdentifier& deviceIdentifier, - InputDeviceConfigurationFileType type); - -/* - * Gets the path of an input device configuration file, if one is available. - * Considers both system provided and user installed configuration files. - * - * The name is case-sensitive and is used to construct the filename to resolve. - * All characters except 'a'-'z', 'A'-'Z', '0'-'9', '-', and '_' are replaced by underscores. - * - * Returns an empty string if not found. - */ -extern String8 getInputDeviceConfigurationFilePathByName( - const String8& name, InputDeviceConfigurationFileType type); - -} // namespace android - -#endif // _ANDROIDFW_INPUT_DEVICE_H diff --git a/widget/gonk/libui/InputDispatcher.cpp b/widget/gonk/libui/InputDispatcher.cpp deleted file mode 100644 index 7adaa1998..000000000 --- a/widget/gonk/libui/InputDispatcher.cpp +++ /dev/null @@ -1,4430 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputDispatcher" -#define ATRACE_TAG ATRACE_TAG_INPUT - -//#define LOG_NDEBUG 0 -#include "cutils_log.h" - -// 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 the dispatch cycle. -#define DEBUG_DISPATCH_CYCLE 0 - -// Log debug messages about registrations. -#define DEBUG_REGISTRATION 0 - -// Log debug messages about input event injection. -#define DEBUG_INJECTION 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 - -// Log debug messages about hover events. -#define DEBUG_HOVER 0 - -#include "InputDispatcher.h" - -#include "Trace.h" -#include "PowerManager.h" - -#include <stddef.h> -#include <unistd.h> -#include <errno.h> -#include <limits.h> -#include <time.h> - -#define INDENT " " -#define INDENT2 " " -#define INDENT3 " " -#define INDENT4 " " - -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 - -// Amount of time to allow for an event to be dispatched (measured since its eventTime) -// before considering it stale and dropping it. -const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec - -// Amount of time to allow touch events to be streamed out to a connection before requiring -// that the first event be finished. This value extends the ANR timeout by the specified -// amount. For example, if streaming is allowed to get ahead by one second relative to the -// queue of waiting unfinished events, then ANRs will similarly be delayed by one second. -const nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec - -// Log a warning when an event takes longer than this to process, even if an ANR does not occur. -const nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec - - -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)) { - ALOGE("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: - case AMOTION_EVENT_ACTION_HOVER_ENTER: - case AMOTION_EVENT_ACTION_HOVER_MOVE: - case AMOTION_EVENT_ACTION_HOVER_EXIT: - case AMOTION_EVENT_ACTION_SCROLL: - 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 PointerProperties* pointerProperties) { - if (! isValidMotionAction(action, pointerCount)) { - ALOGE("Motion event has invalid action code 0x%x", action); - return false; - } - if (pointerCount < 1 || pointerCount > MAX_POINTERS) { - ALOGE("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 = pointerProperties[i].id; - if (id < 0 || id > MAX_POINTER_ID) { - ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d", - id, MAX_POINTER_ID); - return false; - } - if (pointerIdBits.hasBit(id)) { - ALOGE("Motion event has duplicate pointer id %d", id); - return false; - } - pointerIdBits.markBit(id); - } - return true; -} - -static bool isMainDisplay(int32_t displayId) { - return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE; -} - -static void dumpRegion(String8& dump, const SkRegion& region) { - if (region.isEmpty()) { - dump.append("<empty>"); - return; - } - - bool first = true; - for (SkRegion::Iterator it(region); !it.done(); it.next()) { - if (first) { - first = false; - } else { - dump.append("|"); - } - const SkIRect& rect = it.rect(); - dump.appendFormat("[%d,%d][%d,%d]", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); - } -} - - -// --- InputDispatcher --- - -InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) : - mPolicy(policy), - mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX), - mNextUnblockedEvent(NULL), - mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false), - mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) { - mLooper = new Looper(false); - - mKeyRepeatState.lastKeyEntry = NULL; - - policy->getDispatcherConfiguration(&mConfig); -} - -InputDispatcher::~InputDispatcher() { - { // acquire lock - AutoMutex _l(mLock); - - resetKeyRepeatLocked(); - releasePendingEventLocked(); - drainInboundQueueLocked(); - } - - while (mConnectionsByFd.size() != 0) { - unregisterInputChannel(mConnectionsByFd.valueAt(0)->inputChannel); - } -} - -void InputDispatcher::dispatchOnce() { - nsecs_t nextWakeupTime = LONG_LONG_MAX; - { // acquire lock - AutoMutex _l(mLock); - mDispatcherIsAliveCondition.broadcast(); - - // Run a dispatch loop if there are no pending commands. - // The dispatch loop might enqueue commands to run afterwards. - if (!haveCommandsLocked()) { - dispatchOnceInnerLocked(&nextWakeupTime); - } - - // Run all pending commands if there are any. - // If any commands were run then force the next poll to wake up immediately. - if (runCommandsLockedInterruptible()) { - nextWakeupTime = LONG_LONG_MIN; - } - } // release lock - - // Wait for callback or timeout or wake. (make sure we round up, not down) - nsecs_t currentTime = now(); - int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime); - mLooper->pollOnce(timeoutMillis); -} - -void InputDispatcher::dispatchOnceInnerLocked(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 (!mPolicy->isKeyRepeatEnabled()) { - resetKeyRepeatLocked(); - } - - // If dispatching is frozen, do not process timeouts or try to deliver any new events. - if (mDispatchFrozen) { -#if DEBUG_FOCUS - ALOGD("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); - } else { - if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) { - *nextWakeupTime = mKeyRepeatState.nextRepeatTime; - } - } - } - - // Nothing to do if there is no pending event. - if (!mPendingEvent) { - return; - } - } else { - // Inbound queue has at least one entry. - mPendingEvent = mInboundQueue.dequeueAtHead(); - traceInboundQueueLengthLocked(); - } - - // Poke user activity for this event. - if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) { - pokeUserActivityLocked(mPendingEvent); - } - - // Get ready to dispatch the event. - resetANRTimeoutsLocked(); - } - - // Now we have an event to dispatch. - // All events are eventually dequeued and processed this way, even if we intend to drop them. - ALOG_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; - } - - if (mNextUnblockedEvent == mPendingEvent) { - mNextUnblockedEvent = NULL; - } - - 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_DEVICE_RESET: { - DeviceResetEntry* typedEntry = - static_cast<DeviceResetEntry*>(mPendingEvent); - done = dispatchDeviceResetLocked(currentTime, typedEntry); - dropReason = DROP_REASON_NOT_DROPPED; // device resets 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; - } - } - if (dropReason == DROP_REASON_NOT_DROPPED - && isStaleEventLocked(currentTime, typedEntry)) { - dropReason = DROP_REASON_STALE; - } - if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) { - dropReason = DROP_REASON_BLOCKED; - } - done = dispatchKeyLocked(currentTime, typedEntry, &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; - } - if (dropReason == DROP_REASON_NOT_DROPPED - && isStaleEventLocked(currentTime, typedEntry)) { - dropReason = DROP_REASON_STALE; - } - if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) { - dropReason = DROP_REASON_BLOCKED; - } - done = dispatchMotionLocked(currentTime, typedEntry, - &dropReason, nextWakeupTime); - break; - } - - default: - ALOG_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); - traceInboundQueueLengthLocked(); - - switch (entry->type) { - case EventEntry::TYPE_KEY: { - // Optimize app switch latency. - // If the application takes too long to catch up then we drop all events preceding - // the app switch 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 - ALOGD("App switch is pending!"); -#endif - mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT; - mAppSwitchSawKeyDown = false; - needWake = true; - } - } - } - break; - } - - case EventEntry::TYPE_MOTION: { - // Optimize case where the current application is unresponsive and the user - // decides to touch a window in a different application. - // If the application takes too long to catch up then we drop all events preceding - // the touch into the other window. - MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); - if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN - && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) - && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY - && mInputTargetWaitApplicationHandle != NULL) { - int32_t displayId = motionEntry->displayId; - int32_t x = int32_t(motionEntry->pointerCoords[0]. - getAxisValue(AMOTION_EVENT_AXIS_X)); - int32_t y = int32_t(motionEntry->pointerCoords[0]. - getAxisValue(AMOTION_EVENT_AXIS_Y)); - sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); - if (touchedWindowHandle != NULL - && touchedWindowHandle->inputApplicationHandle - != mInputTargetWaitApplicationHandle) { - // User touched a different application than the one we are waiting on. - // Flag the event, and start pruning the input queue. - mNextUnblockedEvent = motionEntry; - needWake = true; - } - } - break; - } - } - - return needWake; -} - -sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, - int32_t x, int32_t y) { - // Traverse windows from front to back to find touched window. - size_t numWindows = mWindowHandles.size(); - for (size_t i = 0; i < numWindows; i++) { - sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); - const InputWindowInfo* windowInfo = windowHandle->getInfo(); - if (windowInfo->displayId == displayId) { - int32_t flags = windowInfo->layoutParamsFlags; - - if (windowInfo->visible) { - if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { - bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE - | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; - if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { - // Found window. - return windowHandle; - } - } - } - - if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { - // Error window is on top but not visible, so touch is dropped. - return NULL; - } - } - } - return NULL; -} - -void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) { - const char* reason; - switch (dropReason) { - case DROP_REASON_POLICY: -#if DEBUG_INBOUND_EVENT_DETAILS - ALOGD("Dropped event because policy consumed it."); -#endif - reason = "inbound event was dropped because the policy consumed it"; - break; - case DROP_REASON_DISABLED: - ALOGI("Dropped event because input dispatch is disabled."); - reason = "inbound event was dropped because input dispatch is disabled"; - break; - case DROP_REASON_APP_SWITCH: - ALOGI("Dropped event because of pending overdue app switch."); - reason = "inbound event was dropped because of pending overdue app switch"; - break; - case DROP_REASON_BLOCKED: - ALOGI("Dropped event because the current application is not responding and the user " - "has started interacting with a different application."); - reason = "inbound event was dropped because the current application is not responding " - "and the user has started interacting with a different application"; - break; - case DROP_REASON_STALE: - ALOGI("Dropped event because it is stale."); - reason = "inbound event was dropped because it is stale"; - break; - default: - ALOG_ASSERT(false); - return; - } - - switch (entry->type) { - case EventEntry::TYPE_KEY: { - CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason); - synthesizeCancelationEventsForAllConnectionsLocked(options); - break; - } - case EventEntry::TYPE_MOTION: { - MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); - if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) { - CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason); - synthesizeCancelationEventsForAllConnectionsLocked(options); - } else { - CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason); - synthesizeCancelationEventsForAllConnectionsLocked(options); - } - break; - } - } -} - -bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) { - return keyCode == AKEYCODE_HOME - || keyCode == AKEYCODE_ENDCALL - || keyCode == AKEYCODE_APP_SWITCH; -} - -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) { - ALOGD("App switch has arrived."); - } else { - ALOGD("App switch was abandoned."); - } -#endif -} - -bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) { - return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT; -} - -bool InputDispatcher::haveCommandsLocked() const { - return !mCommandQueue.isEmpty(); -} - -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(); - delete commandEntry; - } while (! mCommandQueue.isEmpty()); - return true; -} - -InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) { - CommandEntry* commandEntry = new CommandEntry(command); - mCommandQueue.enqueueAtTail(commandEntry); - return commandEntry; -} - -void InputDispatcher::drainInboundQueueLocked() { - while (! mInboundQueue.isEmpty()) { - EventEntry* entry = mInboundQueue.dequeueAtHead(); - releaseInboundEventLocked(entry); - } - traceInboundQueueLengthLocked(); -} - -void InputDispatcher::releasePendingEventLocked() { - if (mPendingEvent) { - resetANRTimeoutsLocked(); - 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 - ALOGD("Injected inbound event was dropped."); -#endif - setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); - } - if (entry == mNextUnblockedEvent) { - mNextUnblockedEvent = NULL; - } - entry->release(); -} - -void InputDispatcher::resetKeyRepeatLocked() { - if (mKeyRepeatState.lastKeyEntry) { - mKeyRepeatState.lastKeyEntry->release(); - mKeyRepeatState.lastKeyEntry = NULL; - } -} - -InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) { - 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) { - entry->recycle(); - entry->eventTime = currentTime; - entry->policyFlags = policyFlags; - entry->repeatCount += 1; - } else { - KeyEntry* newEntry = new KeyEntry(currentTime, - entry->deviceId, entry->source, policyFlags, - entry->action, entry->flags, entry->keyCode, entry->scanCode, - entry->metaState, entry->repeatCount + 1, entry->downTime); - - mKeyRepeatState.lastKeyEntry = newEntry; - entry->release(); - - 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; - - mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay; - return entry; -} - -bool InputDispatcher::dispatchConfigurationChangedLocked( - nsecs_t currentTime, ConfigurationChangedEntry* entry) { -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("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::dispatchDeviceResetLocked( - nsecs_t currentTime, DeviceResetEntry* entry) { -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("dispatchDeviceReset - eventTime=%lld, deviceId=%d", entry->eventTime, entry->deviceId); -#endif - - CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, - "device was reset"); - options.deviceId = entry->deviceId; - synthesizeCancelationEventsForAllConnectionsLocked(options); - return true; -} - -bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, - 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->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) { - 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 + mConfig.keyRepeatTimeout; - } - mKeyRepeatState.lastKeyEntry = entry; - entry->refCount += 1; - } else if (! entry->syntheticRepeat) { - resetKeyRepeatLocked(); - } - - if (entry->repeatCount == 1) { - entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS; - } else { - entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS; - } - - entry->dispatchInProgress = true; - - logOutboundKeyDetailsLocked("dispatchKey - ", entry); - } - - // Handle case where the policy asked us to try again later last time. - if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) { - if (currentTime < entry->interceptKeyWakeupTime) { - if (entry->interceptKeyWakeupTime < *nextWakeupTime) { - *nextWakeupTime = entry->interceptKeyWakeupTime; - } - return false; // wait until next wakeup - } - entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; - entry->interceptKeyWakeupTime = 0; - } - - // 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 (mFocusedWindowHandle != NULL) { - commandEntry->inputWindowHandle = mFocusedWindowHandle; - } - 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) { - setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY - ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED); - return true; - } - - // Identify targets. - Vector<InputTarget> inputTargets; - int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime, - entry, inputTargets, nextWakeupTime); - if (injectionResult == INPUT_EVENT_INJECTION_PENDING) { - return false; - } - - setInjectionResultLocked(entry, injectionResult); - if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) { - return true; - } - - addMonitoringTargetsLocked(inputTargets); - - // Dispatch the key. - dispatchEventLocked(currentTime, entry, inputTargets); - return true; -} - -void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) { -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("%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; - - logOutboundMotionDetailsLocked("dispatchMotion - ", entry); - } - - // Clean up if dropping the event. - if (*dropReason != DROP_REASON_NOT_DROPPED) { - 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. - Vector<InputTarget> inputTargets; - - bool conflictingPointerActions = false; - int32_t injectionResult; - if (isPointerEvent) { - // Pointer event. (eg. touchscreen) - injectionResult = findTouchedWindowTargetsLocked(currentTime, - entry, inputTargets, nextWakeupTime, &conflictingPointerActions); - } else { - // Non touch event. (eg. trackball) - injectionResult = findFocusedWindowTargetsLocked(currentTime, - entry, inputTargets, nextWakeupTime); - } - if (injectionResult == INPUT_EVENT_INJECTION_PENDING) { - return false; - } - - setInjectionResultLocked(entry, injectionResult); - if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) { - return true; - } - - // TODO: support sending secondary display events to input monitors - if (isMainDisplay(entry->displayId)) { - addMonitoringTargetsLocked(inputTargets); - } - - // Dispatch the motion. - if (conflictingPointerActions) { - CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, - "conflicting pointer actions"); - synthesizeCancelationEventsForAllConnectionsLocked(options); - } - dispatchEventLocked(currentTime, entry, inputTargets); - return true; -} - - -void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) { -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " - "action=0x%x, flags=0x%x, " - "metaState=0x%x, buttonState=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->buttonState, - entry->edgeFlags, entry->xPrecision, entry->yPrecision, - entry->downTime); - - for (uint32_t i = 0; i < entry->pointerCount; i++) { - ALOGD(" Pointer %d: id=%d, toolType=%d, " - "x=%f, y=%f, pressure=%f, size=%f, " - "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, " - "orientation=%f", - i, entry->pointerProperties[i].id, - entry->pointerProperties[i].toolType, - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y), - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE), - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), - entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); - } -#endif -} - -void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, - EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("dispatchEventToCurrentInputTargets"); -#endif - - ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true - - pokeUserActivityLocked(eventEntry); - - for (size_t i = 0; i < inputTargets.size(); i++) { - const InputTarget& inputTarget = inputTargets.itemAt(i); - - ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel); - if (connectionIndex >= 0) { - sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); - prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget); - } else { -#if DEBUG_FOCUS - ALOGD("Dropping event delivery to target with channel '%s' because it " - "is no longer registered with the input dispatcher.", - inputTarget.inputChannel->getName().string()); -#endif - } - } -} - -int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, - const EventEntry* entry, - const sp<InputApplicationHandle>& applicationHandle, - const sp<InputWindowHandle>& windowHandle, - nsecs_t* nextWakeupTime, const char* reason) { - if (applicationHandle == NULL && windowHandle == NULL) { - if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) { -#if DEBUG_FOCUS - ALOGD("Waiting for system to become ready for input. Reason: %s", reason); -#endif - mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY; - mInputTargetWaitStartTime = currentTime; - mInputTargetWaitTimeoutTime = LONG_LONG_MAX; - mInputTargetWaitTimeoutExpired = false; - mInputTargetWaitApplicationHandle.clear(); - } - } else { - if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) { -#if DEBUG_FOCUS - ALOGD("Waiting for application to become ready for input: %s. Reason: %s", - getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(), - reason); -#endif - nsecs_t timeout; - if (windowHandle != NULL) { - timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT); - } else if (applicationHandle != NULL) { - timeout = applicationHandle->getDispatchingTimeout( - DEFAULT_INPUT_DISPATCHING_TIMEOUT); - } else { - timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT; - } - - mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY; - mInputTargetWaitStartTime = currentTime; - mInputTargetWaitTimeoutTime = currentTime + timeout; - mInputTargetWaitTimeoutExpired = false; - mInputTargetWaitApplicationHandle.clear(); - - if (windowHandle != NULL) { - mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle; - } - if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) { - mInputTargetWaitApplicationHandle = applicationHandle; - } - } - } - - if (mInputTargetWaitTimeoutExpired) { - return INPUT_EVENT_INJECTION_TIMED_OUT; - } - - if (currentTime >= mInputTargetWaitTimeoutTime) { - onANRLocked(currentTime, applicationHandle, windowHandle, - entry->eventTime, mInputTargetWaitStartTime, reason); - - // 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; - - // 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 = mConnectionsByFd.valueAt(connectionIndex); - sp<InputWindowHandle> windowHandle = connection->inputWindowHandle; - - if (windowHandle != NULL) { - mTouchState.removeWindow(windowHandle); - } - - if (connection->status == Connection::STATUS_NORMAL) { - CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, - "application not responding"); - synthesizeCancelationEventsForConnectionLocked(connection, options); - } - } - } - } -} - -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 - ALOGD("Resetting ANR timeouts."); -#endif - - // Reset input target wait timeout. - mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE; - mInputTargetWaitApplicationHandle.clear(); -} - -int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, - const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) { - int32_t injectionResult; - - // If there is no currently focused window and no focused application - // then drop the event. - if (mFocusedWindowHandle == NULL) { - if (mFocusedApplicationHandle != NULL) { - injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplicationHandle, NULL, nextWakeupTime, - "Waiting because no window has focus but there is a " - "focused application that may eventually add a window " - "when it finishes starting up."); - goto Unresponsive; - } - - ALOGI("Dropping event because there is no focused window or focused application."); - injectionResult = INPUT_EVENT_INJECTION_FAILED; - goto Failed; - } - - // Check permissions. - if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) { - injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED; - goto Failed; - } - - // If the currently focused window is paused then keep waiting. - if (mFocusedWindowHandle->getInfo()->paused) { - injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, - "Waiting because the focused window is paused."); - goto Unresponsive; - } - - // If the currently focused window is still working on previous events then keep waiting. - if (!isWindowReadyForMoreInputLocked(currentTime, mFocusedWindowHandle, entry)) { - injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, - "Waiting because the focused window has not finished " - "processing the input events that were previously delivered to it."); - goto Unresponsive; - } - - // Success! Output targets. - injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED; - addWindowTargetLocked(mFocusedWindowHandle, - InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0), - inputTargets); - - // Done. -Failed: -Unresponsive: - nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime); - updateDispatchStatisticsLocked(currentTime, entry, - injectionResult, timeSpentWaitingForApplication); -#if DEBUG_FOCUS - ALOGD("findFocusedWindow finished: injectionResult=%d, " - "timeSpentWaitingForApplication=%0.1fms", - injectionResult, timeSpentWaitingForApplication / 1000000.0); -#endif - return injectionResult; -} - -int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, - const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime, - bool* outConflictingPointerActions) { - enum InjectionPermission { - INJECTION_PERMISSION_UNKNOWN, - INJECTION_PERMISSION_GRANTED, - INJECTION_PERMISSION_DENIED - }; - - // 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 displayId = entry->displayId; - 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; - sp<InputWindowHandle> newHoverWindowHandle; - - bool isSplit = mTouchState.split; - bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0 - && (mTouchState.deviceId != entry->deviceId - || mTouchState.source != entry->source - || mTouchState.displayId != displayId); - bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE - || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER - || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT); - bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN - || maskedAction == AMOTION_EVENT_ACTION_SCROLL - || isHoverAction); - bool wrongDevice = false; - if (newGesture) { - bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN; - if (switchedDevice && mTouchState.down && !down) { -#if DEBUG_FOCUS - ALOGD("Dropping event because a pointer for a different device is already down."); -#endif - mTempTouchState.copyFrom(mTouchState); - injectionResult = INPUT_EVENT_INJECTION_FAILED; - switchedDevice = false; - wrongDevice = true; - goto Failed; - } - mTempTouchState.reset(); - mTempTouchState.down = down; - mTempTouchState.deviceId = entry->deviceId; - mTempTouchState.source = entry->source; - mTempTouchState.displayId = displayId; - isSplit = false; - } else { - mTempTouchState.copyFrom(mTouchState); - } - - if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) { - /* Case 1: New splittable pointer going down, or need target for hover or scroll. */ - - int32_t pointerIndex = getMotionEventActionPointerIndex(action); - int32_t x = int32_t(entry->pointerCoords[pointerIndex]. - getAxisValue(AMOTION_EVENT_AXIS_X)); - int32_t y = int32_t(entry->pointerCoords[pointerIndex]. - getAxisValue(AMOTION_EVENT_AXIS_Y)); - sp<InputWindowHandle> newTouchedWindowHandle; - sp<InputWindowHandle> topErrorWindowHandle; - bool isTouchModal = false; - - // Traverse windows from front to back to find touched window and outside targets. - size_t numWindows = mWindowHandles.size(); - for (size_t i = 0; i < numWindows; i++) { - sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); - const InputWindowInfo* windowInfo = windowHandle->getInfo(); - if (windowInfo->displayId != displayId) { - continue; // wrong display - } - - int32_t flags = windowInfo->layoutParamsFlags; - if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { - if (topErrorWindowHandle == NULL) { - topErrorWindowHandle = windowHandle; - } - } - - if (windowInfo->visible) { - if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { - isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE - | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; - if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { - if (! screenWasOff - || (flags & InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING)) { - newTouchedWindowHandle = windowHandle; - } - break; // found touched window, exit window loop - } - } - - if (maskedAction == AMOTION_EVENT_ACTION_DOWN - && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) { - int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE; - if (isWindowObscuredAtPointLocked(windowHandle, x, y)) { - outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; - } - - mTempTouchState.addOrUpdateWindow( - windowHandle, 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 (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) { - injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - NULL, NULL, nextWakeupTime, - "Waiting because a system error window is about to be displayed."); - injectionPermission = INJECTION_PERMISSION_UNKNOWN; - goto Unresponsive; - } - - // Figure out whether splitting will be allowed for this window. - if (newTouchedWindowHandle != NULL - && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) { - // New window supports splitting. - isSplit = true; - } else if (isSplit) { - // New window does not support splitting but we have already split events. - // Ignore the new window. - newTouchedWindowHandle = NULL; - } - - // Handle the case where we did not find a window. - if (newTouchedWindowHandle == NULL) { - // Try to assign the pointer to the first foreground window we find, if there is one. - newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle(); - if (newTouchedWindowHandle == NULL) { - // There is no touched window. If this is an initial down event - // then wait for a window to appear that will handle the touch. This is - // to ensure that we report an ANR in the case where an application has started - // but not yet put up a window and the user is starting to get impatient. - if (maskedAction == AMOTION_EVENT_ACTION_DOWN - && mFocusedApplicationHandle != NULL) { - injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplicationHandle, NULL, nextWakeupTime, - "Waiting because there is no touchable window that can " - "handle the event but there is focused application that may " - "eventually add a new window when it finishes starting up."); - goto Unresponsive; - } - - ALOGI("Dropping event because there is no touched window."); - injectionResult = INPUT_EVENT_INJECTION_FAILED; - goto Failed; - } - } - - // Set target flags. - int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS; - if (isSplit) { - targetFlags |= InputTarget::FLAG_SPLIT; - } - if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) { - targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; - } - - // Update hover state. - if (isHoverAction) { - newHoverWindowHandle = newTouchedWindowHandle; - } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) { - newHoverWindowHandle = mLastHoverWindowHandle; - } - - // Update the temporary touch state. - BitSet32 pointerIds; - if (isSplit) { - uint32_t pointerId = entry->pointerProperties[pointerIndex].id; - pointerIds.markBit(pointerId); - } - mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, 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_FOCUS - ALOGD("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 whether touches should slip outside of the current foreground window. - if (maskedAction == AMOTION_EVENT_ACTION_MOVE - && entry->pointerCount == 1 - && mTempTouchState.isSlippery()) { - int32_t x = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); - int32_t y = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); - - sp<InputWindowHandle> oldTouchedWindowHandle = - mTempTouchState.getFirstForegroundWindowHandle(); - sp<InputWindowHandle> newTouchedWindowHandle = - findTouchedWindowAtLocked(displayId, x, y); - if (oldTouchedWindowHandle != newTouchedWindowHandle - && newTouchedWindowHandle != NULL) { -#if DEBUG_FOCUS - ALOGD("Touch is slipping out of window %s into window %s.", - oldTouchedWindowHandle->getName().string(), - newTouchedWindowHandle->getName().string()); -#endif - // Make a slippery exit from the old window. - mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle, - InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0)); - - // Make a slippery entrance into the new window. - if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) { - isSplit = true; - } - - int32_t targetFlags = InputTarget::FLAG_FOREGROUND - | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER; - if (isSplit) { - targetFlags |= InputTarget::FLAG_SPLIT; - } - if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) { - targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; - } - - BitSet32 pointerIds; - if (isSplit) { - pointerIds.markBit(entry->pointerProperties[0].id); - } - mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds); - } - } - } - - if (newHoverWindowHandle != mLastHoverWindowHandle) { - // Let the previous window know that the hover sequence is over. - if (mLastHoverWindowHandle != NULL) { -#if DEBUG_HOVER - ALOGD("Sending hover exit event to window %s.", - mLastHoverWindowHandle->getName().string()); -#endif - mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle, - InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0)); - } - - // Let the new window know that the hover sequence is starting. - if (newHoverWindowHandle != NULL) { -#if DEBUG_HOVER - ALOGD("Sending hover enter event to window %s.", - newHoverWindowHandle->getName().string()); -#endif - mTempTouchState.addOrUpdateWindow(newHoverWindowHandle, - InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0)); - } - } - - // 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.windowHandle, - entry->injectionState)) { - injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED; - injectionPermission = INJECTION_PERMISSION_DENIED; - goto Failed; - } - } - } - if (! haveForegroundWindow) { -#if DEBUG_FOCUS - ALOGD("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; - } - - // Check whether windows listening for outside touches are owned by the same UID. If it is - // set the policy flag that we will not reveal coordinate information to this window. - if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { - sp<InputWindowHandle> foregroundWindowHandle = - mTempTouchState.getFirstForegroundWindowHandle(); - const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid; - for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { - const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; - if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { - sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle; - if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) { - mTempTouchState.addOrUpdateWindow(inputWindowHandle, - InputTarget::FLAG_ZERO_COORDS, BitSet32(0)); - } - } - } - } - - // 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.windowHandle->getInfo()->paused) { - injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - NULL, touchedWindow.windowHandle, nextWakeupTime, - "Waiting because the touched window is paused."); - goto Unresponsive; - } - - // If the touched window is still working on previous events then keep waiting. - if (!isWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle, entry)) { - injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - NULL, touchedWindow.windowHandle, nextWakeupTime, - "Waiting because the touched window has not finished " - "processing the input events that were previously delivered to it."); - 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. - // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper - // engine only supports touch events. We would need to add a mechanism similar - // to View.onGenericMotionEvent to enable wallpapers to handle these events. - if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { - sp<InputWindowHandle> foregroundWindowHandle = - mTempTouchState.getFirstForegroundWindowHandle(); - if (foregroundWindowHandle->getInfo()->hasWallpaper) { - for (size_t i = 0; i < mWindowHandles.size(); i++) { - sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); - const InputWindowInfo* info = windowHandle->getInfo(); - if (info->displayId == displayId - && windowHandle->getInfo()->layoutParamsType - == InputWindowInfo::TYPE_WALLPAPER) { - mTempTouchState.addOrUpdateWindow(windowHandle, - InputTarget::FLAG_WINDOW_IS_OBSCURED - | InputTarget::FLAG_DISPATCH_AS_IS, - 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.windowHandle, touchedWindow.targetFlags, - touchedWindow.pointerIds, inputTargets); - } - - // Drop the outside or hover touch windows since we will not care about them - // in the next iteration. - mTempTouchState.filterNonAsIsTouchWindows(); - -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 (!wrongDevice) { - if (switchedDevice) { -#if DEBUG_FOCUS - ALOGD("Conflicting pointer actions: Switched to a different device."); -#endif - *outConflictingPointerActions = true; - } - - if (isHoverAction) { - // Started hovering, therefore no longer down. - if (mTouchState.down) { -#if DEBUG_FOCUS - ALOGD("Conflicting pointer actions: Hover received while pointer was down."); -#endif - *outConflictingPointerActions = true; - } - mTouchState.reset(); - if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER - || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { - mTouchState.deviceId = entry->deviceId; - mTouchState.source = entry->source; - mTouchState.displayId = displayId; - } - } else if (maskedAction == AMOTION_EVENT_ACTION_UP - || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { - // All pointers up or canceled. - mTouchState.reset(); - } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { - // First pointer went down. - if (mTouchState.down) { -#if DEBUG_FOCUS - ALOGD("Conflicting pointer actions: Down received while already down."); -#endif - *outConflictingPointerActions = true; - } - mTouchState.copyFrom(mTempTouchState); - } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { - // One pointer went up. - if (isSplit) { - int32_t pointerIndex = getMotionEventActionPointerIndex(action); - uint32_t pointerId = entry->pointerProperties[pointerIndex].id; - - 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; - } - } - mTouchState.copyFrom(mTempTouchState); - } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) { - // Discard temporary touch state since it was only valid for this action. - } else { - // Save changes to touch state as-is for all other actions. - mTouchState.copyFrom(mTempTouchState); - } - - // Update hover state. - mLastHoverWindowHandle = newHoverWindowHandle; - } - } else { -#if DEBUG_FOCUS - ALOGD("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 - ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, " - "timeSpentWaitingForApplication=%0.1fms", - injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0); -#endif - return injectionResult; -} - -void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, - int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) { - inputTargets.push(); - - const InputWindowInfo* windowInfo = windowHandle->getInfo(); - InputTarget& target = inputTargets.editTop(); - target.inputChannel = windowInfo->inputChannel; - target.flags = targetFlags; - target.xOffset = - windowInfo->frameLeft; - target.yOffset = - windowInfo->frameTop; - target.scaleFactor = windowInfo->scaleFactor; - target.pointerIds = pointerIds; -} - -void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets) { - for (size_t i = 0; i < mMonitoringChannels.size(); i++) { - inputTargets.push(); - - InputTarget& target = inputTargets.editTop(); - target.inputChannel = mMonitoringChannels[i]; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; - target.xOffset = 0; - target.yOffset = 0; - target.pointerIds.clear(); - target.scaleFactor = 1.0f; - } -} - -bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, - const InjectionState* injectionState) { - if (injectionState - && (windowHandle == NULL - || windowHandle->getInfo()->ownerUid != injectionState->injectorUid) - && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) { - if (windowHandle != NULL) { - ALOGW("Permission denied: injecting event from pid %d uid %d to window %s " - "owned by uid %d", - injectionState->injectorPid, injectionState->injectorUid, - windowHandle->getName().string(), - windowHandle->getInfo()->ownerUid); - } else { - ALOGW("Permission denied: injecting event from pid %d uid %d", - injectionState->injectorPid, injectionState->injectorUid); - } - return false; - } - return true; -} - -bool InputDispatcher::isWindowObscuredAtPointLocked( - const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const { - int32_t displayId = windowHandle->getInfo()->displayId; - size_t numWindows = mWindowHandles.size(); - for (size_t i = 0; i < numWindows; i++) { - sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i); - if (otherHandle == windowHandle) { - break; - } - - const InputWindowInfo* otherInfo = otherHandle->getInfo(); - if (otherInfo->displayId == displayId - && otherInfo->visible && !otherInfo->isTrustedOverlay() - && otherInfo->frameContainsPoint(x, y)) { - return true; - } - } - return false; -} - -bool InputDispatcher::isWindowReadyForMoreInputLocked(nsecs_t currentTime, - const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry) { - ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel()); - if (connectionIndex >= 0) { - sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); - if (connection->inputPublisherBlocked) { - return false; - } - if (eventEntry->type == EventEntry::TYPE_KEY) { - // If the event is a key event, then we must wait for all previous events to - // complete before delivering it because previous events may have the - // side-effect of transferring focus to a different window and we want to - // ensure that the following keys are sent to the new window. - // - // Suppose the user touches a button in a window then immediately presses "A". - // If the button causes a pop-up window to appear then we want to ensure that - // the "A" key is delivered to the new pop-up window. This is because users - // often anticipate pending UI changes when typing on a keyboard. - // To obtain this behavior, we must serialize key events with respect to all - // prior input events. - return connection->outboundQueue.isEmpty() - && connection->waitQueue.isEmpty(); - } - // Touch events can always be sent to a window immediately because the user intended - // to touch whatever was visible at the time. Even if focus changes or a new - // window appears moments later, the touch event was meant to be delivered to - // whatever window happened to be on screen at the time. - // - // Generic motion events, such as trackball or joystick events are a little trickier. - // Like key events, generic motion events are delivered to the focused window. - // Unlike key events, generic motion events don't tend to transfer focus to other - // windows and it is not important for them to be serialized. So we prefer to deliver - // generic motion events as soon as possible to improve efficiency and reduce lag - // through batching. - // - // The one case where we pause input event delivery is when the wait queue is piling - // up with lots of events because the application is not responding. - // This condition ensures that ANRs are detected reliably. - if (!connection->waitQueue.isEmpty() - && currentTime >= connection->waitQueue.head->eventEntry->eventTime - + STREAM_AHEAD_EVENT_TIMEOUT) { - return false; - } - } - return true; -} - -String8 InputDispatcher::getApplicationWindowLabelLocked( - const sp<InputApplicationHandle>& applicationHandle, - const sp<InputWindowHandle>& windowHandle) { - if (applicationHandle != NULL) { - if (windowHandle != NULL) { - String8 label(applicationHandle->getName()); - label.append(" - "); - label.append(windowHandle->getName()); - return label; - } else { - return applicationHandle->getName(); - } - } else if (windowHandle != NULL) { - return windowHandle->getName(); - } else { - return String8("<unknown application or window>"); - } -} - -void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) { - if (mFocusedWindowHandle != NULL) { - const InputWindowInfo* info = mFocusedWindowHandle->getInfo(); - if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("Not poking user activity: disabled by window '%s'.", info->name.string()); -#endif - return; - } - } - - int32_t eventType = USER_ACTIVITY_EVENT_OTHER; - switch (eventEntry->type) { - case EventEntry::TYPE_MOTION: { - const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry); - if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) { - return; - } - - if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) { - eventType = USER_ACTIVITY_EVENT_TOUCH; - } - break; - } - case EventEntry::TYPE_KEY: { - const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry); - if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) { - return; - } - eventType = USER_ACTIVITY_EVENT_BUTTON; - 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) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, " - "xOffset=%f, yOffset=%f, scaleFactor=%f, " - "pointerIds=0x%x", - connection->getInputChannelName(), inputTarget->flags, - inputTarget->xOffset, inputTarget->yOffset, - inputTarget->scaleFactor, inputTarget->pointerIds.value); -#endif - - // 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 - ALOGD("channel '%s' ~ Dropping event because the channel status is %s", - connection->getInputChannelName(), connection->getStatusLabel()); -#endif - return; - } - - // Split a motion event if needed. - if (inputTarget->flags & InputTarget::FLAG_SPLIT) { - ALOG_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 (!splitMotionEntry) { - return; // split event was dropped - } -#if DEBUG_FOCUS - ALOGD("channel '%s' ~ Split motion event.", - connection->getInputChannelName()); - logOutboundMotionDetailsLocked(" ", splitMotionEntry); -#endif - enqueueDispatchEntriesLocked(currentTime, connection, - splitMotionEntry, inputTarget); - splitMotionEntry->release(); - return; - } - } - - // Not splitting. Enqueue dispatch entries for the event as is. - enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget); -} - -void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, - const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) { - bool wasEmpty = connection->outboundQueue.isEmpty(); - - // Enqueue dispatch entries for the requested modes. - enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT); - enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_OUTSIDE); - enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER); - enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_IS); - enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT); - enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER); - - // If the outbound queue was previously empty, start the dispatch cycle going. - if (wasEmpty && !connection->outboundQueue.isEmpty()) { - startDispatchCycleLocked(currentTime, connection); - } -} - -void InputDispatcher::enqueueDispatchEntryLocked( - const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget, - int32_t dispatchMode) { - int32_t inputTargetFlags = inputTarget->flags; - if (!(inputTargetFlags & dispatchMode)) { - return; - } - inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode; - - // This is a new event. - // Enqueue a new dispatch entry onto the outbound queue for this connection. - DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref - inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset, - inputTarget->scaleFactor); - - // Apply target flags and update the connection's input state. - switch (eventEntry->type) { - case EventEntry::TYPE_KEY: { - KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry); - dispatchEntry->resolvedAction = keyEntry->action; - dispatchEntry->resolvedFlags = keyEntry->flags; - - if (!connection->inputState.trackKey(keyEntry, - dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event", - connection->getInputChannelName()); -#endif - delete dispatchEntry; - return; // skip the inconsistent event - } - break; - } - - case EventEntry::TYPE_MOTION: { - MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry); - if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { - dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE; - } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) { - dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT; - } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) { - dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER; - } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) { - dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL; - } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) { - dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN; - } else { - dispatchEntry->resolvedAction = motionEntry->action; - } - if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE - && !connection->inputState.isHovering( - motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event", - connection->getInputChannelName()); -#endif - dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER; - } - - dispatchEntry->resolvedFlags = motionEntry->flags; - if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) { - dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; - } - - if (!connection->inputState.trackMotion(motionEntry, - dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event", - connection->getInputChannelName()); -#endif - delete dispatchEntry; - return; // skip the inconsistent event - } - break; - } - } - - // Remember that we are waiting for this dispatch to complete. - if (dispatchEntry->hasForegroundTarget()) { - incrementPendingForegroundDispatchesLocked(eventEntry); - } - - // Enqueue the dispatch entry. - connection->outboundQueue.enqueueAtTail(dispatchEntry); - traceOutboundQueueLengthLocked(connection); -} - -void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ startDispatchCycle", - connection->getInputChannelName()); -#endif - - while (connection->status == Connection::STATUS_NORMAL - && !connection->outboundQueue.isEmpty()) { - DispatchEntry* dispatchEntry = connection->outboundQueue.head; - dispatchEntry->deliveryTime = currentTime; - - // Publish the event. - status_t status; - EventEntry* eventEntry = dispatchEntry->eventEntry; - switch (eventEntry->type) { - case EventEntry::TYPE_KEY: { - KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry); - - // Publish the key event. - status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq, - keyEntry->deviceId, keyEntry->source, - dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, - keyEntry->keyCode, keyEntry->scanCode, - keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime, - keyEntry->eventTime); - break; - } - - case EventEntry::TYPE_MOTION: { - MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry); - - PointerCoords scaledCoords[MAX_POINTERS]; - const PointerCoords* usingCoords = motionEntry->pointerCoords; - - // Set the X and Y offset depending on the input source. - float xOffset, yOffset, scaleFactor; - if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) - && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) { - scaleFactor = dispatchEntry->scaleFactor; - xOffset = dispatchEntry->xOffset * scaleFactor; - yOffset = dispatchEntry->yOffset * scaleFactor; - if (scaleFactor != 1.0f) { - for (size_t i = 0; i < motionEntry->pointerCount; i++) { - scaledCoords[i] = motionEntry->pointerCoords[i]; - scaledCoords[i].scale(scaleFactor); - } - usingCoords = scaledCoords; - } - } else { - xOffset = 0.0f; - yOffset = 0.0f; - scaleFactor = 1.0f; - - // We don't want the dispatch target to know. - if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) { - for (size_t i = 0; i < motionEntry->pointerCount; i++) { - scaledCoords[i].clear(); - } - usingCoords = scaledCoords; - } - } - - // Publish the motion event. - status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq, - motionEntry->deviceId, motionEntry->source, - dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, - motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState, - xOffset, yOffset, - motionEntry->xPrecision, motionEntry->yPrecision, - motionEntry->downTime, motionEntry->eventTime, - motionEntry->pointerCount, motionEntry->pointerProperties, - usingCoords); - break; - } - - default: - ALOG_ASSERT(false); - return; - } - - // Check the result. - if (status) { - if (status == WOULD_BLOCK) { - if (connection->waitQueue.isEmpty()) { - ALOGE("channel '%s' ~ Could not publish event because the pipe is full. " - "This is unexpected because the wait queue is empty, so the pipe " - "should be empty and we shouldn't have any problems writing an " - "event to it, status=%d", connection->getInputChannelName(), status); - abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/); - } else { - // Pipe is full and we are waiting for the app to finish process some events - // before sending more events to it. -#if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ Could not publish event because the pipe is full, " - "waiting for the application to catch up", - connection->getInputChannelName()); -#endif - connection->inputPublisherBlocked = true; - } - } else { - ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, " - "status=%d", connection->getInputChannelName(), status); - abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/); - } - return; - } - - // Re-enqueue the event on the wait queue. - connection->outboundQueue.dequeue(dispatchEntry); - traceOutboundQueueLengthLocked(connection); - connection->waitQueue.enqueueAtTail(dispatchEntry); - traceWaitQueueLengthLocked(connection); - } -} - -void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection, uint32_t seq, bool handled) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s", - connection->getInputChannelName(), seq, toString(handled)); -#endif - - connection->inputPublisherBlocked = false; - - if (connection->status == Connection::STATUS_BROKEN - || connection->status == Connection::STATUS_ZOMBIE) { - return; - } - - // Notify other system components and prepare to start the next dispatch cycle. - onDispatchCycleFinishedLocked(currentTime, connection, seq, handled); -} - -void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection, bool notify) { -#if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s", - connection->getInputChannelName(), toString(notify)); -#endif - - // Clear the dispatch queues. - drainDispatchQueueLocked(&connection->outboundQueue); - traceOutboundQueueLengthLocked(connection); - drainDispatchQueueLocked(&connection->waitQueue); - traceWaitQueueLengthLocked(connection); - - // The connection appears to be unrecoverably broken. - // Ignore already broken or zombie connections. - if (connection->status == Connection::STATUS_NORMAL) { - connection->status = Connection::STATUS_BROKEN; - - if (notify) { - // Notify other system components. - onDispatchCycleBrokenLocked(currentTime, connection); - } - } -} - -void InputDispatcher::drainDispatchQueueLocked(Queue<DispatchEntry>* queue) { - while (!queue->isEmpty()) { - DispatchEntry* dispatchEntry = queue->dequeueAtHead(); - releaseDispatchEntryLocked(dispatchEntry); - } -} - -void InputDispatcher::releaseDispatchEntryLocked(DispatchEntry* dispatchEntry) { - if (dispatchEntry->hasForegroundTarget()) { - decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry); - } - delete dispatchEntry; -} - -int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { - InputDispatcher* d = static_cast<InputDispatcher*>(data); - - { // acquire lock - AutoMutex _l(d->mLock); - - ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd); - if (connectionIndex < 0) { - ALOGE("Received spurious receive callback for unknown input channel. " - "fd=%d, events=0x%x", fd, events); - return 0; // remove the callback - } - - bool notify; - sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex); - if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) { - if (!(events & ALOOPER_EVENT_INPUT)) { - ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " - "events=0x%x", connection->getInputChannelName(), events); - return 1; - } - - nsecs_t currentTime = now(); - bool gotOne = false; - status_t status; - for (;;) { - uint32_t seq; - bool handled; - status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled); - if (status) { - break; - } - d->finishDispatchCycleLocked(currentTime, connection, seq, handled); - gotOne = true; - } - if (gotOne) { - d->runCommandsLockedInterruptible(); - if (status == WOULD_BLOCK) { - return 1; - } - } - - notify = status != DEAD_OBJECT || !connection->monitor; - if (notify) { - ALOGE("channel '%s' ~ Failed to receive finished signal. status=%d", - connection->getInputChannelName(), status); - } - } else { - // Monitor channels are never explicitly unregistered. - // We do it automatically when the remote endpoint is closed so don't warn - // about them. - notify = !connection->monitor; - if (notify) { - ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. " - "events=0x%x", connection->getInputChannelName(), events); - } - } - - // Unregister the channel. - d->unregisterInputChannelLocked(connection->inputChannel, notify); - return 0; // remove the callback - } // release lock -} - -void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( - const CancelationOptions& options) { - for (size_t i = 0; i < mConnectionsByFd.size(); i++) { - synthesizeCancelationEventsForConnectionLocked( - mConnectionsByFd.valueAt(i), options); - } -} - -void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked( - const sp<InputChannel>& channel, const CancelationOptions& options) { - ssize_t index = getConnectionIndexLocked(channel); - if (index >= 0) { - synthesizeCancelationEventsForConnectionLocked( - mConnectionsByFd.valueAt(index), options); - } -} - -void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( - const sp<Connection>& connection, const CancelationOptions& options) { - if (connection->status == Connection::STATUS_BROKEN) { - return; - } - - nsecs_t currentTime = now(); - - Vector<EventEntry*> cancelationEvents; - connection->inputState.synthesizeCancelationEvents(currentTime, - cancelationEvents, options); - - if (!cancelationEvents.isEmpty()) { -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync " - "with reality: %s, mode=%d.", - connection->getInputChannelName(), cancelationEvents.size(), - options.reason, options.mode); -#endif - for (size_t i = 0; i < cancelationEvents.size(); i++) { - EventEntry* cancelationEventEntry = cancelationEvents.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; - } - - InputTarget target; - sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel); - if (windowHandle != NULL) { - const InputWindowInfo* windowInfo = windowHandle->getInfo(); - target.xOffset = -windowInfo->frameLeft; - target.yOffset = -windowInfo->frameTop; - target.scaleFactor = windowInfo->scaleFactor; - } else { - target.xOffset = 0; - target.yOffset = 0; - target.scaleFactor = 1.0f; - } - target.inputChannel = connection->inputChannel; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; - - enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref - &target, InputTarget::FLAG_DISPATCH_AS_IS); - - cancelationEventEntry->release(); - } - - startDispatchCycleLocked(currentTime, connection); - } -} - -InputDispatcher::MotionEntry* -InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) { - ALOG_ASSERT(pointerIds.value != 0); - - PointerProperties splitPointerProperties[MAX_POINTERS]; - PointerCoords splitPointerCoords[MAX_POINTERS]; - - uint32_t originalPointerCount = originalMotionEntry->pointerCount; - uint32_t splitPointerCount = 0; - - for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount; - originalPointerIndex++) { - const PointerProperties& pointerProperties = - originalMotionEntry->pointerProperties[originalPointerIndex]; - uint32_t pointerId = uint32_t(pointerProperties.id); - if (pointerIds.hasBit(pointerId)) { - splitPointerProperties[splitPointerCount].copyFrom(pointerProperties); - splitPointerCoords[splitPointerCount].copyFrom( - originalMotionEntry->pointerCoords[originalPointerIndex]); - splitPointerCount += 1; - } - } - - if (splitPointerCount != pointerIds.count()) { - // This is bad. We are missing some of the pointers that we expected to deliver. - // Most likely this indicates that we received an ACTION_MOVE events that has - // different pointer ids than we expected based on the previous ACTION_DOWN - // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers - // in this way. - ALOGW("Dropping split motion event because the pointer count is %d but " - "we expected there to be %d pointers. This probably means we received " - "a broken sequence of pointer ids from the input device.", - splitPointerCount, pointerIds.count()); - return NULL; - } - - 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); - const PointerProperties& pointerProperties = - originalMotionEntry->pointerProperties[originalPointerIndex]; - uint32_t pointerId = uint32_t(pointerProperties.id); - 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 != uint32_t(splitPointerProperties[splitPointerIndex].id)) { - splitPointerIndex += 1; - } - action = maskedAction | (splitPointerIndex - << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - } - } else { - // An unrelated pointer changed. - action = AMOTION_EVENT_ACTION_MOVE; - } - } - - MotionEntry* splitMotionEntry = new MotionEntry( - originalMotionEntry->eventTime, - originalMotionEntry->deviceId, - originalMotionEntry->source, - originalMotionEntry->policyFlags, - action, - originalMotionEntry->flags, - originalMotionEntry->metaState, - originalMotionEntry->buttonState, - originalMotionEntry->edgeFlags, - originalMotionEntry->xPrecision, - originalMotionEntry->yPrecision, - originalMotionEntry->downTime, - originalMotionEntry->displayId, - splitPointerCount, splitPointerProperties, splitPointerCoords); - - if (originalMotionEntry->injectionState) { - splitMotionEntry->injectionState = originalMotionEntry->injectionState; - splitMotionEntry->injectionState->refCount += 1; - } - - return splitMotionEntry; -} - -void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { -#if DEBUG_INBOUND_EVENT_DETAILS - ALOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime); -#endif - - bool needWake; - { // acquire lock - AutoMutex _l(mLock); - - ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime); - needWake = enqueueInboundEventLocked(newEntry); - } // release lock - - if (needWake) { - mLooper->wake(); - } -} - -void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { -#if DEBUG_INBOUND_EVENT_DETAILS - ALOGD("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", - args->eventTime, args->deviceId, args->source, args->policyFlags, - args->action, args->flags, args->keyCode, args->scanCode, - args->metaState, args->downTime); -#endif - if (!validateKeyEvent(args->action)) { - return; - } - - uint32_t policyFlags = args->policyFlags; - int32_t flags = args->flags; - int32_t metaState = args->metaState; - if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { - policyFlags |= POLICY_FLAG_VIRTUAL; - flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; - } - if (policyFlags & POLICY_FLAG_ALT) { - metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON; - } - if (policyFlags & POLICY_FLAG_ALT_GR) { - metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON; - } - if (policyFlags & POLICY_FLAG_SHIFT) { - metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON; - } - if (policyFlags & POLICY_FLAG_CAPS_LOCK) { - metaState |= AMETA_CAPS_LOCK_ON; - } - if (policyFlags & POLICY_FLAG_FUNCTION) { - metaState |= AMETA_FUNCTION_ON; - } - - policyFlags |= POLICY_FLAG_TRUSTED; - - KeyEvent event; - event.initialize(args->deviceId, args->source, args->action, - flags, args->keyCode, args->scanCode, metaState, 0, - args->downTime, args->eventTime); - - mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); - - if (policyFlags & POLICY_FLAG_WOKE_HERE) { - flags |= AKEY_EVENT_FLAG_WOKE_HERE; - } - - bool needWake; - { // acquire lock - mLock.lock(); - - if (shouldSendKeyToInputFilterLocked(args)) { - mLock.unlock(); - - policyFlags |= POLICY_FLAG_FILTERED; - if (!mPolicy->filterInputEvent(&event, policyFlags)) { - return; // event was consumed by the filter - } - - mLock.lock(); - } - - int32_t repeatCount = 0; - KeyEntry* newEntry = new KeyEntry(args->eventTime, - args->deviceId, args->source, policyFlags, - args->action, flags, args->keyCode, args->scanCode, - metaState, repeatCount, args->downTime); - - needWake = enqueueInboundEventLocked(newEntry); - mLock.unlock(); - } // release lock - - if (needWake) { - mLooper->wake(); - } -} - -bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) { - return mInputFilterEnabled; -} - -void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { -#if DEBUG_INBOUND_EVENT_DETAILS - ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " - "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, " - "xPrecision=%f, yPrecision=%f, downTime=%lld", - args->eventTime, args->deviceId, args->source, args->policyFlags, - args->action, args->flags, args->metaState, args->buttonState, - args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime); - for (uint32_t i = 0; i < args->pointerCount; i++) { - ALOGD(" Pointer %d: id=%d, toolType=%d, " - "x=%f, y=%f, pressure=%f, size=%f, " - "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, " - "orientation=%f", - i, args->pointerProperties[i].id, - args->pointerProperties[i].toolType, - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); - } -#endif - if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) { - return; - } - - uint32_t policyFlags = args->policyFlags; - policyFlags |= POLICY_FLAG_TRUSTED; - mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags); - - bool needWake; - { // acquire lock - mLock.lock(); - - if (shouldSendMotionToInputFilterLocked(args)) { - mLock.unlock(); - - MotionEvent event; - event.initialize(args->deviceId, args->source, args->action, args->flags, - args->edgeFlags, args->metaState, args->buttonState, 0, 0, - args->xPrecision, args->yPrecision, - args->downTime, args->eventTime, - args->pointerCount, args->pointerProperties, args->pointerCoords); - - policyFlags |= POLICY_FLAG_FILTERED; - if (!mPolicy->filterInputEvent(&event, policyFlags)) { - return; // event was consumed by the filter - } - - mLock.lock(); - } - - // Just enqueue a new motion event. - MotionEntry* newEntry = new MotionEntry(args->eventTime, - args->deviceId, args->source, policyFlags, - args->action, args->flags, args->metaState, args->buttonState, - args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, - args->displayId, - args->pointerCount, args->pointerProperties, args->pointerCoords); - - needWake = enqueueInboundEventLocked(newEntry); - mLock.unlock(); - } // release lock - - if (needWake) { - mLooper->wake(); - } -} - -bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) { - // TODO: support sending secondary display events to input filter - return mInputFilterEnabled && isMainDisplay(args->displayId); -} - -void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) { -#if DEBUG_INBOUND_EVENT_DETAILS - ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, switchMask=0x%08x", - args->eventTime, args->policyFlags, - args->switchValues, args->switchMask); -#endif - - uint32_t policyFlags = args->policyFlags; - policyFlags |= POLICY_FLAG_TRUSTED; - mPolicy->notifySwitch(args->eventTime, - args->switchValues, args->switchMask, policyFlags); -} - -void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { -#if DEBUG_INBOUND_EVENT_DETAILS - ALOGD("notifyDeviceReset - eventTime=%lld, deviceId=%d", - args->eventTime, args->deviceId); -#endif - - bool needWake; - { // acquire lock - AutoMutex _l(mLock); - - DeviceResetEntry* newEntry = new DeviceResetEntry(args->eventTime, args->deviceId); - needWake = enqueueInboundEventLocked(newEntry); - } // release lock - - if (needWake) { - mLooper->wake(); - } -} - -int32_t InputDispatcher::injectInputEvent(const InputEvent* event, - int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, - uint32_t policyFlags) { -#if DEBUG_INBOUND_EVENT_DETAILS - ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, " - "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x", - event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags); -#endif - - nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis); - - policyFlags |= POLICY_FLAG_INJECTED; - if (hasInjectionPermission(injectorPid, injectorUid)) { - policyFlags |= POLICY_FLAG_TRUSTED; - } - - EventEntry* firstInjectedEntry; - EventEntry* lastInjectedEntry; - 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; - } - - if (!(policyFlags & POLICY_FLAG_FILTERED)) { - mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags); - } - - if (policyFlags & POLICY_FLAG_WOKE_HERE) { - flags |= AKEY_EVENT_FLAG_WOKE_HERE; - } - - mLock.lock(); - firstInjectedEntry = new KeyEntry(keyEvent->getEventTime(), - keyEvent->getDeviceId(), keyEvent->getSource(), - policyFlags, action, flags, - keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(), - keyEvent->getRepeatCount(), keyEvent->getDownTime()); - lastInjectedEntry = firstInjectedEntry; - break; - } - - case AINPUT_EVENT_TYPE_MOTION: { - const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event); - int32_t displayId = ADISPLAY_ID_DEFAULT; - int32_t action = motionEvent->getAction(); - size_t pointerCount = motionEvent->getPointerCount(); - const PointerProperties* pointerProperties = motionEvent->getPointerProperties(); - if (! validateMotionEvent(action, pointerCount, pointerProperties)) { - return INPUT_EVENT_INJECTION_FAILED; - } - - if (!(policyFlags & POLICY_FLAG_FILTERED)) { - nsecs_t eventTime = motionEvent->getEventTime(); - mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags); - } - - mLock.lock(); - const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes(); - const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords(); - firstInjectedEntry = new MotionEntry(*sampleEventTimes, - motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags, - action, motionEvent->getFlags(), - motionEvent->getMetaState(), motionEvent->getButtonState(), - motionEvent->getEdgeFlags(), - motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), displayId, - uint32_t(pointerCount), pointerProperties, samplePointerCoords); - lastInjectedEntry = firstInjectedEntry; - for (size_t i = motionEvent->getHistorySize(); i > 0; i--) { - sampleEventTimes += 1; - samplePointerCoords += pointerCount; - MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes, - motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags, - action, motionEvent->getFlags(), - motionEvent->getMetaState(), motionEvent->getButtonState(), - motionEvent->getEdgeFlags(), - motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), displayId, - uint32_t(pointerCount), pointerProperties, samplePointerCoords); - lastInjectedEntry->next = nextInjectedEntry; - lastInjectedEntry = nextInjectedEntry; - } - break; - } - - default: - ALOGW("Cannot inject event of type %d", event->getType()); - return INPUT_EVENT_INJECTION_FAILED; - } - - InjectionState* injectionState = new InjectionState(injectorPid, injectorUid); - if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) { - injectionState->injectionIsAsync = true; - } - - injectionState->refCount += 1; - lastInjectedEntry->injectionState = injectionState; - - bool needWake = false; - for (EventEntry* entry = firstInjectedEntry; entry != NULL; ) { - EventEntry* nextEntry = entry->next; - needWake |= enqueueInboundEventLocked(entry); - entry = nextEntry; - } - - 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 - ALOGD("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 - ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.", - injectionState->pendingForegroundDispatches); -#endif - nsecs_t remainingTimeout = endTime - now(); - if (remainingTimeout <= 0) { -#if DEBUG_INJECTION - ALOGD("injectInputEvent - Timed out waiting for pending foreground " - "dispatches to finish."); -#endif - injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT; - break; - } - - mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout); - } - } - } - - injectionState->release(); - } // release lock - -#if DEBUG_INJECTION - ALOGD("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 - ALOGD("Setting input event injection result to %d. " - "injectorPid=%d, injectorUid=%d", - injectionResult, injectionState->injectorPid, injectionState->injectorUid); -#endif - - if (injectionState->injectionIsAsync - && !(entry->policyFlags & POLICY_FLAG_FILTERED)) { - // Log the outcome since the injector did not wait for the injection result. - switch (injectionResult) { - case INPUT_EVENT_INJECTION_SUCCEEDED: - ALOGV("Asynchronous input event injection succeeded."); - break; - case INPUT_EVENT_INJECTION_FAILED: - ALOGW("Asynchronous input event injection failed."); - break; - case INPUT_EVENT_INJECTION_PERMISSION_DENIED: - ALOGW("Asynchronous input event injection permission denied."); - break; - case INPUT_EVENT_INJECTION_TIMED_OUT: - ALOGW("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(); - } - } -} - -sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked( - const sp<InputChannel>& inputChannel) const { - size_t numWindows = mWindowHandles.size(); - for (size_t i = 0; i < numWindows; i++) { - const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); - if (windowHandle->getInputChannel() == inputChannel) { - return windowHandle; - } - } - return NULL; -} - -bool InputDispatcher::hasWindowHandleLocked( - const sp<InputWindowHandle>& windowHandle) const { - size_t numWindows = mWindowHandles.size(); - for (size_t i = 0; i < numWindows; i++) { - if (mWindowHandles.itemAt(i) == windowHandle) { - return true; - } - } - return false; -} - -void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) { -#if DEBUG_FOCUS - ALOGD("setInputWindows"); -#endif - { // acquire lock - AutoMutex _l(mLock); - - Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles; - mWindowHandles = inputWindowHandles; - - sp<InputWindowHandle> newFocusedWindowHandle; - bool foundHoveredWindow = false; - for (size_t i = 0; i < mWindowHandles.size(); i++) { - const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); - if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) { - mWindowHandles.removeAt(i--); - continue; - } - if (windowHandle->getInfo()->hasFocus) { - newFocusedWindowHandle = windowHandle; - } - if (windowHandle == mLastHoverWindowHandle) { - foundHoveredWindow = true; - } - } - - if (!foundHoveredWindow) { - mLastHoverWindowHandle = NULL; - } - - if (mFocusedWindowHandle != newFocusedWindowHandle) { - if (mFocusedWindowHandle != NULL) { -#if DEBUG_FOCUS - ALOGD("Focus left window: %s", - mFocusedWindowHandle->getName().string()); -#endif - sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel(); - if (focusedInputChannel != NULL) { - CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, - "focus left window"); - synthesizeCancelationEventsForInputChannelLocked( - focusedInputChannel, options); - } - } - if (newFocusedWindowHandle != NULL) { -#if DEBUG_FOCUS - ALOGD("Focus entered window: %s", - newFocusedWindowHandle->getName().string()); -#endif - } - mFocusedWindowHandle = newFocusedWindowHandle; - } - - for (size_t i = 0; i < mTouchState.windows.size(); i++) { - TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i); - if (!hasWindowHandleLocked(touchedWindow.windowHandle)) { -#if DEBUG_FOCUS - ALOGD("Touched window was removed: %s", - touchedWindow.windowHandle->getName().string()); -#endif - sp<InputChannel> touchedInputChannel = - touchedWindow.windowHandle->getInputChannel(); - if (touchedInputChannel != NULL) { - CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, - "touched window was removed"); - synthesizeCancelationEventsForInputChannelLocked( - touchedInputChannel, options); - } - mTouchState.windows.removeAt(i--); - } - } - - // Release information for windows that are no longer present. - // This ensures that unused input channels are released promptly. - // Otherwise, they might stick around until the window handle is destroyed - // which might not happen until the next GC. - for (size_t i = 0; i < oldWindowHandles.size(); i++) { - const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i); - if (!hasWindowHandleLocked(oldWindowHandle)) { -#if DEBUG_FOCUS - ALOGD("Window went away: %s", oldWindowHandle->getName().string()); -#endif - oldWindowHandle->releaseInfo(); - } - } - } // release lock - - // Wake up poll loop since it may need to make new input dispatching choices. - mLooper->wake(); -} - -void InputDispatcher::setFocusedApplication( - const sp<InputApplicationHandle>& inputApplicationHandle) { -#if DEBUG_FOCUS - ALOGD("setFocusedApplication"); -#endif - { // acquire lock - AutoMutex _l(mLock); - - if (inputApplicationHandle != NULL && inputApplicationHandle->updateInfo()) { - if (mFocusedApplicationHandle != inputApplicationHandle) { - if (mFocusedApplicationHandle != NULL) { - resetANRTimeoutsLocked(); - mFocusedApplicationHandle->releaseInfo(); - } - mFocusedApplicationHandle = inputApplicationHandle; - } - } else if (mFocusedApplicationHandle != NULL) { - resetANRTimeoutsLocked(); - mFocusedApplicationHandle->releaseInfo(); - mFocusedApplicationHandle.clear(); - } - -#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::setInputDispatchMode(bool enabled, bool frozen) { -#if DEBUG_FOCUS - ALOGD("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(); - } -} - -void InputDispatcher::setInputFilterEnabled(bool enabled) { -#if DEBUG_FOCUS - ALOGD("setInputFilterEnabled: enabled=%d", enabled); -#endif - - { // acquire lock - AutoMutex _l(mLock); - - if (mInputFilterEnabled == enabled) { - return; - } - - mInputFilterEnabled = enabled; - resetAndDropEverythingLocked("input filter is being enabled or disabled"); - } // release lock - - // Wake up poll loop since there might be work to do to drop everything. - mLooper->wake(); -} - -bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel, - const sp<InputChannel>& toChannel) { -#if DEBUG_FOCUS - ALOGD("transferTouchFocus: fromChannel=%s, toChannel=%s", - fromChannel->getName().string(), toChannel->getName().string()); -#endif - { // acquire lock - AutoMutex _l(mLock); - - sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel); - sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel); - if (fromWindowHandle == NULL || toWindowHandle == NULL) { -#if DEBUG_FOCUS - ALOGD("Cannot transfer focus because from or to window not found."); -#endif - return false; - } - if (fromWindowHandle == toWindowHandle) { -#if DEBUG_FOCUS - ALOGD("Trivial transfer to same window."); -#endif - return true; - } - if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) { -#if DEBUG_FOCUS - ALOGD("Cannot transfer focus because windows are on different displays."); -#endif - return false; - } - - bool found = false; - for (size_t i = 0; i < mTouchState.windows.size(); i++) { - const TouchedWindow& touchedWindow = mTouchState.windows[i]; - if (touchedWindow.windowHandle == fromWindowHandle) { - int32_t oldTargetFlags = touchedWindow.targetFlags; - BitSet32 pointerIds = touchedWindow.pointerIds; - - mTouchState.windows.removeAt(i); - - int32_t newTargetFlags = oldTargetFlags - & (InputTarget::FLAG_FOREGROUND - | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS); - mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds); - - found = true; - break; - } - } - - if (! found) { -#if DEBUG_FOCUS - ALOGD("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 = mConnectionsByFd.valueAt(fromConnectionIndex); - sp<Connection> toConnection = mConnectionsByFd.valueAt(toConnectionIndex); - - fromConnection->inputState.copyPointerStateTo(toConnection->inputState); - CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, - "transferring touch focus from this window to another window"); - synthesizeCancelationEventsForConnectionLocked(fromConnection, options); - } - -#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 - ALOGD("Resetting and dropping all events (%s).", reason); -#endif - - CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, reason); - synthesizeCancelationEventsForAllConnectionsLocked(options); - - resetKeyRepeatLocked(); - releasePendingEventLocked(); - drainInboundQueueLocked(); - resetANRTimeoutsLocked(); - - mTouchState.reset(); - mLastHoverWindowHandle.clear(); -} - -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'; - } - ALOGD("%s", start); - start = end; - } -} - -void InputDispatcher::dumpDispatchStateLocked(String8& dump) { - dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled); - dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen); - - if (mFocusedApplicationHandle != NULL) { - dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n", - mFocusedApplicationHandle->getName().string(), - mFocusedApplicationHandle->getDispatchingTimeout( - DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0); - } else { - dump.append(INDENT "FocusedApplication: <null>\n"); - } - dump.appendFormat(INDENT "FocusedWindow: name='%s'\n", - mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>"); - - dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down)); - dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split)); - dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId); - dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source); - dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId); - 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.windowHandle->getName().string(), - touchedWindow.pointerIds.value, - touchedWindow.targetFlags); - } - } else { - dump.append(INDENT "TouchedWindows: <none>\n"); - } - - if (!mWindowHandles.isEmpty()) { - dump.append(INDENT "Windows:\n"); - for (size_t i = 0; i < mWindowHandles.size(); i++) { - const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); - const InputWindowInfo* windowInfo = windowHandle->getInfo(); - - dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, " - "paused=%s, hasFocus=%s, hasWallpaper=%s, " - "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, " - "frame=[%d,%d][%d,%d], scale=%f, " - "touchableRegion=", - i, windowInfo->name.string(), windowInfo->displayId, - toString(windowInfo->paused), - toString(windowInfo->hasFocus), - toString(windowInfo->hasWallpaper), - toString(windowInfo->visible), - toString(windowInfo->canReceiveKeys), - windowInfo->layoutParamsFlags, windowInfo->layoutParamsType, - windowInfo->layer, - windowInfo->frameLeft, windowInfo->frameTop, - windowInfo->frameRight, windowInfo->frameBottom, - windowInfo->scaleFactor); - dumpRegion(dump, windowInfo->touchableRegion); - dump.appendFormat(", inputFeatures=0x%08x", windowInfo->inputFeatures); - dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n", - windowInfo->ownerPid, windowInfo->ownerUid, - windowInfo->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"); - } - - nsecs_t currentTime = now(); - - if (!mInboundQueue.isEmpty()) { - dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count()); - for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) { - dump.append(INDENT2); - entry->appendDescription(dump); - dump.appendFormat(", age=%0.1fms\n", - (currentTime - entry->eventTime) * 0.000001f); - } - } else { - dump.append(INDENT "InboundQueue: <empty>\n"); - } - - if (!mConnectionsByFd.isEmpty()) { - dump.append(INDENT "Connections:\n"); - for (size_t i = 0; i < mConnectionsByFd.size(); i++) { - const sp<Connection>& connection = mConnectionsByFd.valueAt(i); - dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', " - "status=%s, monitor=%s, inputPublisherBlocked=%s\n", - i, connection->getInputChannelName(), connection->getWindowName(), - connection->getStatusLabel(), toString(connection->monitor), - toString(connection->inputPublisherBlocked)); - - if (!connection->outboundQueue.isEmpty()) { - dump.appendFormat(INDENT3 "OutboundQueue: length=%u\n", - connection->outboundQueue.count()); - for (DispatchEntry* entry = connection->outboundQueue.head; entry; - entry = entry->next) { - dump.append(INDENT4); - entry->eventEntry->appendDescription(dump); - dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, age=%0.1fms\n", - entry->targetFlags, entry->resolvedAction, - (currentTime - entry->eventEntry->eventTime) * 0.000001f); - } - } else { - dump.append(INDENT3 "OutboundQueue: <empty>\n"); - } - - if (!connection->waitQueue.isEmpty()) { - dump.appendFormat(INDENT3 "WaitQueue: length=%u\n", - connection->waitQueue.count()); - for (DispatchEntry* entry = connection->waitQueue.head; entry; - entry = entry->next) { - dump.append(INDENT4); - entry->eventEntry->appendDescription(dump); - dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, " - "age=%0.1fms, wait=%0.1fms\n", - entry->targetFlags, entry->resolvedAction, - (currentTime - entry->eventEntry->eventTime) * 0.000001f, - (currentTime - entry->deliveryTime) * 0.000001f); - } - } else { - dump.append(INDENT3 "WaitQueue: <empty>\n"); - } - } - } else { - dump.append(INDENT "Connections: <none>\n"); - } - - if (isAppSwitchPendingLocked()) { - dump.appendFormat(INDENT "AppSwitch: pending, due in %0.1fms\n", - (mAppSwitchDueTime - now()) / 1000000.0); - } else { - dump.append(INDENT "AppSwitch: not pending\n"); - } - - dump.append(INDENT "Configuration:\n"); - dump.appendFormat(INDENT2 "KeyRepeatDelay: %0.1fms\n", - mConfig.keyRepeatDelay * 0.000001f); - dump.appendFormat(INDENT2 "KeyRepeatTimeout: %0.1fms\n", - mConfig.keyRepeatTimeout * 0.000001f); -} - -status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, - const sp<InputWindowHandle>& inputWindowHandle, bool monitor) { -#if DEBUG_REGISTRATION - ALOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(), - toString(monitor)); -#endif - - { // acquire lock - AutoMutex _l(mLock); - - if (getConnectionIndexLocked(inputChannel) >= 0) { - ALOGW("Attempted to register already registered input channel '%s'", - inputChannel->getName().string()); - return BAD_VALUE; - } - - sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor); - - int fd = inputChannel->getFd(); - mConnectionsByFd.add(fd, connection); - - if (monitor) { - mMonitoringChannels.push(inputChannel); - } - - mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); - } // release lock - - // Wake the looper because some connections have changed. - mLooper->wake(); - return OK; -} - -status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) { -#if DEBUG_REGISTRATION - ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string()); -#endif - - { // acquire lock - AutoMutex _l(mLock); - - status_t status = unregisterInputChannelLocked(inputChannel, false /*notify*/); - if (status) { - return status; - } - } // release lock - - // Wake the poll loop because removing the connection may have changed the current - // synchronization state. - mLooper->wake(); - return OK; -} - -status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, - bool notify) { - ssize_t connectionIndex = getConnectionIndexLocked(inputChannel); - if (connectionIndex < 0) { - ALOGW("Attempted to unregister already unregistered input channel '%s'", - inputChannel->getName().string()); - return BAD_VALUE; - } - - sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); - mConnectionsByFd.removeItemsAt(connectionIndex); - - if (connection->monitor) { - removeMonitorChannelLocked(inputChannel); - } - - mLooper->removeFd(inputChannel->getFd()); - - nsecs_t currentTime = now(); - abortBrokenDispatchCycleLocked(currentTime, connection, notify); - - connection->status = Connection::STATUS_ZOMBIE; - return OK; -} - -void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) { - for (size_t i = 0; i < mMonitoringChannels.size(); i++) { - if (mMonitoringChannels[i] == inputChannel) { - mMonitoringChannels.removeAt(i); - break; - } - } -} - -ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) { - ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd()); - if (connectionIndex >= 0) { - sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); - if (connection->inputChannel.get() == inputChannel.get()) { - return connectionIndex; - } - } - - return -1; -} - -void InputDispatcher::onDispatchCycleFinishedLocked( - nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) { - CommandEntry* commandEntry = postCommandLocked( - & InputDispatcher::doDispatchCycleFinishedLockedInterruptible); - commandEntry->connection = connection; - commandEntry->eventTime = currentTime; - commandEntry->seq = seq; - commandEntry->handled = handled; -} - -void InputDispatcher::onDispatchCycleBrokenLocked( - nsecs_t currentTime, const sp<Connection>& connection) { - ALOGE("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 sp<InputApplicationHandle>& applicationHandle, - const sp<InputWindowHandle>& windowHandle, - nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) { - float dispatchLatency = (currentTime - eventTime) * 0.000001f; - float waitDuration = (currentTime - waitStartTime) * 0.000001f; - ALOGI("Application is not responding: %s. " - "It has been %0.1fms since event, %0.1fms since wait started. Reason: %s", - getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(), - dispatchLatency, waitDuration, reason); - - // Capture a record of the InputDispatcher state at the time of the ANR. - time_t t = time(NULL); - struct tm tm; - localtime_r(&t, &tm); - char timestr[64]; - strftime(timestr, sizeof(timestr), "%F %T", &tm); - mLastANRState.clear(); - mLastANRState.append(INDENT "ANR:\n"); - mLastANRState.appendFormat(INDENT2 "Time: %s\n", timestr); - mLastANRState.appendFormat(INDENT2 "Window: %s\n", - getApplicationWindowLabelLocked(applicationHandle, windowHandle).string()); - mLastANRState.appendFormat(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency); - mLastANRState.appendFormat(INDENT2 "WaitDuration: %0.1fms\n", waitDuration); - mLastANRState.appendFormat(INDENT2 "Reason: %s\n", reason); - dumpDispatchStateLocked(mLastANRState); - - CommandEntry* commandEntry = postCommandLocked( - & InputDispatcher::doNotifyANRLockedInterruptible); - commandEntry->inputApplicationHandle = applicationHandle; - commandEntry->inputWindowHandle = windowHandle; -} - -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->inputWindowHandle); - - mLock.lock(); - } -} - -void InputDispatcher::doNotifyANRLockedInterruptible( - CommandEntry* commandEntry) { - mLock.unlock(); - - nsecs_t newTimeout = mPolicy->notifyANR( - commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle); - - mLock.lock(); - - resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, - commandEntry->inputWindowHandle != NULL - ? commandEntry->inputWindowHandle->getInputChannel() : NULL); -} - -void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( - CommandEntry* commandEntry) { - KeyEntry* entry = commandEntry->keyEntry; - - KeyEvent event; - initializeKeyEvent(&event, entry); - - mLock.unlock(); - - nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle, - &event, entry->policyFlags); - - mLock.lock(); - - if (delay < 0) { - entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP; - } else if (!delay) { - entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; - } else { - entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER; - entry->interceptKeyWakeupTime = now() + delay; - } - entry->release(); -} - -void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( - CommandEntry* commandEntry) { - sp<Connection> connection = commandEntry->connection; - nsecs_t finishTime = commandEntry->eventTime; - uint32_t seq = commandEntry->seq; - bool handled = commandEntry->handled; - - // Handle post-event policy actions. - DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq); - if (dispatchEntry) { - nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime; - if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) { - String8 msg; - msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ", - connection->getWindowName(), eventDuration * 0.000001f); - dispatchEntry->eventEntry->appendDescription(msg); - ALOGI("%s", msg.string()); - } - - bool restartEvent; - if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) { - KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry); - restartEvent = afterKeyEventLockedInterruptible(connection, - dispatchEntry, keyEntry, handled); - } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) { - MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry); - restartEvent = afterMotionEventLockedInterruptible(connection, - dispatchEntry, motionEntry, handled); - } else { - restartEvent = false; - } - - // Dequeue the event and start the next cycle. - // Note that because the lock might have been released, it is possible that the - // contents of the wait queue to have been drained, so we need to double-check - // a few things. - if (dispatchEntry == connection->findWaitQueueEntry(seq)) { - connection->waitQueue.dequeue(dispatchEntry); - traceWaitQueueLengthLocked(connection); - if (restartEvent && connection->status == Connection::STATUS_NORMAL) { - connection->outboundQueue.enqueueAtHead(dispatchEntry); - traceOutboundQueueLengthLocked(connection); - } else { - releaseDispatchEntryLocked(dispatchEntry); - } - } - - // Start the next dispatch cycle for this connection. - startDispatchCycleLocked(now(), connection); - } -} - -bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection, - DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) { - if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) { - // Get the fallback key state. - // Clear it out after dispatching the UP. - int32_t originalKeyCode = keyEntry->keyCode; - int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode); - if (keyEntry->action == AKEY_EVENT_ACTION_UP) { - connection->inputState.removeFallbackKey(originalKeyCode); - } - - if (handled || !dispatchEntry->hasForegroundTarget()) { - // If the application handles the original key for which we previously - // generated a fallback or if the window is not a foreground window, - // then cancel the associated fallback key, if any. - if (fallbackKeyCode != -1) { - // Dispatch the unhandled key to the policy with the cancel flag. -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Unhandled key event: Asking policy to cancel fallback action. " - "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", - keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, - keyEntry->policyFlags); -#endif - KeyEvent event; - initializeKeyEvent(&event, keyEntry); - event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED); - - mLock.unlock(); - - mPolicy->dispatchUnhandledKey(connection->inputWindowHandle, - &event, keyEntry->policyFlags, &event); - - mLock.lock(); - - // Cancel the fallback key. - if (fallbackKeyCode != AKEYCODE_UNKNOWN) { - CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS, - "application handled the original non-fallback key " - "or is no longer a foreground target, " - "canceling previously dispatched fallback key"); - options.keyCode = fallbackKeyCode; - synthesizeCancelationEventsForConnectionLocked(connection, options); - } - connection->inputState.removeFallbackKey(originalKeyCode); - } - } else { - // If the application did not handle a non-fallback key, first check - // that we are in a good state to perform unhandled key event processing - // Then ask the policy what to do with it. - bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN - && keyEntry->repeatCount == 0; - if (fallbackKeyCode == -1 && !initialDown) { -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Unhandled key event: Skipping unhandled key event processing " - "since this is not an initial down. " - "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", - originalKeyCode, keyEntry->action, keyEntry->repeatCount, - keyEntry->policyFlags); -#endif - return false; - } - - // Dispatch the unhandled key to the policy. -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Unhandled key event: Asking policy to perform fallback action. " - "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", - keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, - keyEntry->policyFlags); -#endif - KeyEvent event; - initializeKeyEvent(&event, keyEntry); - - mLock.unlock(); - - bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle, - &event, keyEntry->policyFlags, &event); - - mLock.lock(); - - if (connection->status != Connection::STATUS_NORMAL) { - connection->inputState.removeFallbackKey(originalKeyCode); - return false; - } - - // Latch the fallback keycode for this key on an initial down. - // The fallback keycode cannot change at any other point in the lifecycle. - if (initialDown) { - if (fallback) { - fallbackKeyCode = event.getKeyCode(); - } else { - fallbackKeyCode = AKEYCODE_UNKNOWN; - } - connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode); - } - - ALOG_ASSERT(fallbackKeyCode != -1); - - // Cancel the fallback key if the policy decides not to send it anymore. - // We will continue to dispatch the key to the policy but we will no - // longer dispatch a fallback key to the application. - if (fallbackKeyCode != AKEYCODE_UNKNOWN - && (!fallback || fallbackKeyCode != event.getKeyCode())) { -#if DEBUG_OUTBOUND_EVENT_DETAILS - if (fallback) { - ALOGD("Unhandled key event: Policy requested to send key %d" - "as a fallback for %d, but on the DOWN it had requested " - "to send %d instead. Fallback canceled.", - event.getKeyCode(), originalKeyCode, fallbackKeyCode); - } else { - ALOGD("Unhandled key event: Policy did not request fallback for %d, " - "but on the DOWN it had requested to send %d. " - "Fallback canceled.", - originalKeyCode, fallbackKeyCode); - } -#endif - - CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS, - "canceling fallback, policy no longer desires it"); - options.keyCode = fallbackKeyCode; - synthesizeCancelationEventsForConnectionLocked(connection, options); - - fallback = false; - fallbackKeyCode = AKEYCODE_UNKNOWN; - if (keyEntry->action != AKEY_EVENT_ACTION_UP) { - connection->inputState.setFallbackKey(originalKeyCode, - fallbackKeyCode); - } - } - -#if DEBUG_OUTBOUND_EVENT_DETAILS - { - String8 msg; - const KeyedVector<int32_t, int32_t>& fallbackKeys = - connection->inputState.getFallbackKeys(); - for (size_t i = 0; i < fallbackKeys.size(); i++) { - msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i), - fallbackKeys.valueAt(i)); - } - ALOGD("Unhandled key event: %d currently tracked fallback keys%s.", - fallbackKeys.size(), msg.string()); - } -#endif - - 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 = fallbackKeyCode; - keyEntry->scanCode = event.getScanCode(); - keyEntry->metaState = event.getMetaState(); - keyEntry->repeatCount = event.getRepeatCount(); - keyEntry->downTime = event.getDownTime(); - keyEntry->syntheticRepeat = false; - -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Unhandled key event: Dispatching fallback key. " - "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x", - originalKeyCode, fallbackKeyCode, keyEntry->metaState); -#endif - return true; // restart the event - } else { -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Unhandled key event: No fallback key."); -#endif - } - } - } - return false; -} - -bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection, - DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) { - return false; -} - -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::traceInboundQueueLengthLocked() { -#ifdef HAVE_ANDROID_OS - if (ATRACE_ENABLED()) { - ATRACE_INT("iq", mInboundQueue.count()); - } -#endif -} - -void InputDispatcher::traceOutboundQueueLengthLocked(const sp<Connection>& connection) { -#ifdef HAVE_ANDROID_OS - if (ATRACE_ENABLED()) { - char counterName[40]; - snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName()); - ATRACE_INT(counterName, connection->outboundQueue.count()); - } -#endif -} - -void InputDispatcher::traceWaitQueueLengthLocked(const sp<Connection>& connection) { -#ifdef HAVE_ANDROID_OS - if (ATRACE_ENABLED()) { - char counterName[40]; - snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName()); - ATRACE_INT(counterName, connection->waitQueue.count()); - } -#endif -} - -void InputDispatcher::dump(String8& dump) { - AutoMutex _l(mLock); - - dump.append("Input Dispatcher State:\n"); - dumpDispatchStateLocked(dump); - - if (!mLastANRState.isEmpty()) { - dump.append("\nInput Dispatcher State at time of last ANR:\n"); - dump.append(mLastANRState); - } -} - -void InputDispatcher::monitor() { - // Acquire and release the lock to ensure that the dispatcher has not deadlocked. - mLock.lock(); - mLooper->wake(); - mDispatcherIsAliveCondition.wait(mLock); - mLock.unlock(); -} - - -// --- InputDispatcher::Queue --- - -template <typename T> -uint32_t InputDispatcher::Queue<T>::count() const { - uint32_t result = 0; - for (const T* entry = head; entry; entry = entry->next) { - result += 1; - } - return result; -} - - -// --- InputDispatcher::InjectionState --- - -InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) : - refCount(1), - injectorPid(injectorPid), injectorUid(injectorUid), - injectionResult(INPUT_EVENT_INJECTION_PENDING), injectionIsAsync(false), - pendingForegroundDispatches(0) { -} - -InputDispatcher::InjectionState::~InjectionState() { -} - -void InputDispatcher::InjectionState::release() { - refCount -= 1; - if (refCount == 0) { - delete this; - } else { - ALOG_ASSERT(refCount > 0); - } -} - - -// --- InputDispatcher::EventEntry --- - -InputDispatcher::EventEntry::EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags) : - refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags), - injectionState(NULL), dispatchInProgress(false) { -} - -InputDispatcher::EventEntry::~EventEntry() { - releaseInjectionState(); -} - -void InputDispatcher::EventEntry::release() { - refCount -= 1; - if (refCount == 0) { - delete this; - } else { - ALOG_ASSERT(refCount > 0); - } -} - -void InputDispatcher::EventEntry::releaseInjectionState() { - if (injectionState) { - injectionState->release(); - injectionState = NULL; - } -} - - -// --- InputDispatcher::ConfigurationChangedEntry --- - -InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t eventTime) : - EventEntry(TYPE_CONFIGURATION_CHANGED, eventTime, 0) { -} - -InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() { -} - -void InputDispatcher::ConfigurationChangedEntry::appendDescription(String8& msg) const { - msg.append("ConfigurationChangedEvent()"); -} - - -// --- InputDispatcher::DeviceResetEntry --- - -InputDispatcher::DeviceResetEntry::DeviceResetEntry(nsecs_t eventTime, int32_t deviceId) : - EventEntry(TYPE_DEVICE_RESET, eventTime, 0), - deviceId(deviceId) { -} - -InputDispatcher::DeviceResetEntry::~DeviceResetEntry() { -} - -void InputDispatcher::DeviceResetEntry::appendDescription(String8& msg) const { - msg.appendFormat("DeviceResetEvent(deviceId=%d)", deviceId); -} - - -// --- InputDispatcher::KeyEntry --- - -InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime, - int32_t deviceId, uint32_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) : - EventEntry(TYPE_KEY, eventTime, policyFlags), - deviceId(deviceId), source(source), action(action), flags(flags), - keyCode(keyCode), scanCode(scanCode), metaState(metaState), - repeatCount(repeatCount), downTime(downTime), - syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN), - interceptKeyWakeupTime(0) { -} - -InputDispatcher::KeyEntry::~KeyEntry() { -} - -void InputDispatcher::KeyEntry::appendDescription(String8& msg) const { - msg.appendFormat("KeyEvent(action=%d, deviceId=%d, source=0x%08x)", - action, deviceId, source); -} - -void InputDispatcher::KeyEntry::recycle() { - releaseInjectionState(); - - dispatchInProgress = false; - syntheticRepeat = false; - interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; - interceptKeyWakeupTime = 0; -} - - -// --- InputDispatcher::MotionEntry --- - -InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, - int32_t metaState, int32_t buttonState, - int32_t edgeFlags, float xPrecision, float yPrecision, - nsecs_t downTime, int32_t displayId, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) : - EventEntry(TYPE_MOTION, eventTime, policyFlags), - eventTime(eventTime), - deviceId(deviceId), source(source), action(action), flags(flags), - metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags), - xPrecision(xPrecision), yPrecision(yPrecision), - downTime(downTime), displayId(displayId), pointerCount(pointerCount) { - for (uint32_t i = 0; i < pointerCount; i++) { - this->pointerProperties[i].copyFrom(pointerProperties[i]); - this->pointerCoords[i].copyFrom(pointerCoords[i]); - } -} - -InputDispatcher::MotionEntry::~MotionEntry() { -} - -void InputDispatcher::MotionEntry::appendDescription(String8& msg) const { - msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x, displayId=%d)", - action, deviceId, source, displayId); -} - - -// --- InputDispatcher::DispatchEntry --- - -volatile int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic; - -InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry, - int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) : - seq(nextSeq()), - eventEntry(eventEntry), targetFlags(targetFlags), - xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor), - deliveryTime(0), resolvedAction(0), resolvedFlags(0) { - eventEntry->refCount += 1; -} - -InputDispatcher::DispatchEntry::~DispatchEntry() { - eventEntry->release(); -} - -uint32_t InputDispatcher::DispatchEntry::nextSeq() { - // Sequence number 0 is reserved and will never be returned. - uint32_t seq; - do { - seq = android_atomic_inc(&sNextSeqAtomic); - } while (!seq); - return seq; -} - - -// --- InputDispatcher::InputState --- - -InputDispatcher::InputState::InputState() { -} - -InputDispatcher::InputState::~InputState() { -} - -bool InputDispatcher::InputState::isNeutral() const { - return mKeyMementos.isEmpty() && mMotionMementos.isEmpty(); -} - -bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source, - int32_t displayId) const { - for (size_t i = 0; i < mMotionMementos.size(); i++) { - const MotionMemento& memento = mMotionMementos.itemAt(i); - if (memento.deviceId == deviceId - && memento.source == source - && memento.displayId == displayId - && memento.hovering) { - return true; - } - } - return false; -} - -bool InputDispatcher::InputState::trackKey(const KeyEntry* entry, - int32_t action, int32_t flags) { - switch (action) { - case AKEY_EVENT_ACTION_UP: { - if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) { - for (size_t i = 0; i < mFallbackKeys.size(); ) { - if (mFallbackKeys.valueAt(i) == entry->keyCode) { - mFallbackKeys.removeItemsAt(i); - } else { - i += 1; - } - } - } - ssize_t index = findKeyMemento(entry); - if (index >= 0) { - mKeyMementos.removeAt(index); - return true; - } - /* FIXME: We can't just drop the key up event because that prevents creating - * popup windows that are automatically shown when a key is held and then - * dismissed when the key is released. The problem is that the popup will - * not have received the original key down, so the key up will be considered - * to be inconsistent with its observed state. We could perhaps handle this - * by synthesizing a key down but that will cause other problems. - * - * So for now, allow inconsistent key up events to be dispatched. - * -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, " - "keyCode=%d, scanCode=%d", - entry->deviceId, entry->source, entry->keyCode, entry->scanCode); -#endif - return false; - */ - return true; - } - - case AKEY_EVENT_ACTION_DOWN: { - ssize_t index = findKeyMemento(entry); - if (index >= 0) { - mKeyMementos.removeAt(index); - } - addKeyMemento(entry, flags); - return true; - } - - default: - return true; - } -} - -bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry, - int32_t action, int32_t flags) { - int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK; - switch (actionMasked) { - case AMOTION_EVENT_ACTION_UP: - case AMOTION_EVENT_ACTION_CANCEL: { - ssize_t index = findMotionMemento(entry, false /*hovering*/); - if (index >= 0) { - mMotionMementos.removeAt(index); - return true; - } -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, " - "actionMasked=%d", - entry->deviceId, entry->source, actionMasked); -#endif - return false; - } - - case AMOTION_EVENT_ACTION_DOWN: { - ssize_t index = findMotionMemento(entry, false /*hovering*/); - if (index >= 0) { - mMotionMementos.removeAt(index); - } - addMotionMemento(entry, flags, false /*hovering*/); - return true; - } - - case AMOTION_EVENT_ACTION_POINTER_UP: - case AMOTION_EVENT_ACTION_POINTER_DOWN: - case AMOTION_EVENT_ACTION_MOVE: { - ssize_t index = findMotionMemento(entry, false /*hovering*/); - if (index >= 0) { - MotionMemento& memento = mMotionMementos.editItemAt(index); - memento.setPointers(entry); - return true; - } - if (actionMasked == AMOTION_EVENT_ACTION_MOVE - && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK - | AINPUT_SOURCE_CLASS_NAVIGATION))) { - // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP. - return true; - } -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Dropping inconsistent motion pointer up/down or move event: " - "deviceId=%d, source=%08x, actionMasked=%d", - entry->deviceId, entry->source, actionMasked); -#endif - return false; - } - - case AMOTION_EVENT_ACTION_HOVER_EXIT: { - ssize_t index = findMotionMemento(entry, true /*hovering*/); - if (index >= 0) { - mMotionMementos.removeAt(index); - return true; - } -#if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x", - entry->deviceId, entry->source); -#endif - return false; - } - - case AMOTION_EVENT_ACTION_HOVER_ENTER: - case AMOTION_EVENT_ACTION_HOVER_MOVE: { - ssize_t index = findMotionMemento(entry, true /*hovering*/); - if (index >= 0) { - mMotionMementos.removeAt(index); - } - addMotionMemento(entry, flags, true /*hovering*/); - return true; - } - - default: - return true; - } -} - -ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const { - for (size_t i = 0; i < mKeyMementos.size(); i++) { - const KeyMemento& memento = mKeyMementos.itemAt(i); - if (memento.deviceId == entry->deviceId - && memento.source == entry->source - && memento.keyCode == entry->keyCode - && memento.scanCode == entry->scanCode) { - return i; - } - } - return -1; -} - -ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry, - bool hovering) const { - for (size_t i = 0; i < mMotionMementos.size(); i++) { - const MotionMemento& memento = mMotionMementos.itemAt(i); - if (memento.deviceId == entry->deviceId - && memento.source == entry->source - && memento.displayId == entry->displayId - && memento.hovering == hovering) { - return i; - } - } - return -1; -} - -void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) { - mKeyMementos.push(); - KeyMemento& memento = mKeyMementos.editTop(); - memento.deviceId = entry->deviceId; - memento.source = entry->source; - memento.keyCode = entry->keyCode; - memento.scanCode = entry->scanCode; - memento.metaState = entry->metaState; - memento.flags = flags; - memento.downTime = entry->downTime; - memento.policyFlags = entry->policyFlags; -} - -void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, - int32_t flags, bool hovering) { - mMotionMementos.push(); - MotionMemento& memento = mMotionMementos.editTop(); - memento.deviceId = entry->deviceId; - memento.source = entry->source; - memento.flags = flags; - memento.xPrecision = entry->xPrecision; - memento.yPrecision = entry->yPrecision; - memento.downTime = entry->downTime; - memento.displayId = entry->displayId; - memento.setPointers(entry); - memento.hovering = hovering; - memento.policyFlags = entry->policyFlags; -} - -void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) { - pointerCount = entry->pointerCount; - for (uint32_t i = 0; i < entry->pointerCount; i++) { - pointerProperties[i].copyFrom(entry->pointerProperties[i]); - pointerCoords[i].copyFrom(entry->pointerCoords[i]); - } -} - -void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime, - Vector<EventEntry*>& outEvents, const CancelationOptions& options) { - for (size_t i = 0; i < mKeyMementos.size(); i++) { - const KeyMemento& memento = mKeyMementos.itemAt(i); - if (shouldCancelKey(memento, options)) { - outEvents.push(new KeyEntry(currentTime, - memento.deviceId, memento.source, memento.policyFlags, - AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED, - memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime)); - } - } - - for (size_t i = 0; i < mMotionMementos.size(); i++) { - const MotionMemento& memento = mMotionMementos.itemAt(i); - if (shouldCancelMotion(memento, options)) { - outEvents.push(new MotionEntry(currentTime, - memento.deviceId, memento.source, memento.policyFlags, - memento.hovering - ? AMOTION_EVENT_ACTION_HOVER_EXIT - : AMOTION_EVENT_ACTION_CANCEL, - memento.flags, 0, 0, 0, - memento.xPrecision, memento.yPrecision, memento.downTime, - memento.displayId, - memento.pointerCount, memento.pointerProperties, memento.pointerCoords)); - } - } -} - -void InputDispatcher::InputState::clear() { - mKeyMementos.clear(); - mMotionMementos.clear(); - mFallbackKeys.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 - && memento.displayId == otherMemento.displayId) { - other.mMotionMementos.removeAt(j); - } else { - j += 1; - } - } - other.mMotionMementos.push(memento); - } - } -} - -int32_t InputDispatcher::InputState::getFallbackKey(int32_t originalKeyCode) { - ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode); - return index >= 0 ? mFallbackKeys.valueAt(index) : -1; -} - -void InputDispatcher::InputState::setFallbackKey(int32_t originalKeyCode, - int32_t fallbackKeyCode) { - ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode); - if (index >= 0) { - mFallbackKeys.replaceValueAt(index, fallbackKeyCode); - } else { - mFallbackKeys.add(originalKeyCode, fallbackKeyCode); - } -} - -void InputDispatcher::InputState::removeFallbackKey(int32_t originalKeyCode) { - mFallbackKeys.removeItem(originalKeyCode); -} - -bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento, - const CancelationOptions& options) { - if (options.keyCode != -1 && memento.keyCode != options.keyCode) { - return false; - } - - if (options.deviceId != -1 && memento.deviceId != options.deviceId) { - return false; - } - - switch (options.mode) { - case CancelationOptions::CANCEL_ALL_EVENTS: - case CancelationOptions::CANCEL_NON_POINTER_EVENTS: - return true; - case CancelationOptions::CANCEL_FALLBACK_EVENTS: - return memento.flags & AKEY_EVENT_FLAG_FALLBACK; - default: - return false; - } -} - -bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento, - const CancelationOptions& options) { - if (options.deviceId != -1 && memento.deviceId != options.deviceId) { - return false; - } - - switch (options.mode) { - case CancelationOptions::CANCEL_ALL_EVENTS: - return true; - case CancelationOptions::CANCEL_POINTER_EVENTS: - return memento.source & AINPUT_SOURCE_CLASS_POINTER; - case CancelationOptions::CANCEL_NON_POINTER_EVENTS: - return !(memento.source & AINPUT_SOURCE_CLASS_POINTER); - default: - return false; - } -} - - -// --- InputDispatcher::Connection --- - -InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel, - const sp<InputWindowHandle>& inputWindowHandle, bool monitor) : - status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle), - monitor(monitor), - inputPublisher(inputChannel), inputPublisherBlocked(false) { -} - -InputDispatcher::Connection::~Connection() { -} - -const char* InputDispatcher::Connection::getWindowName() const { - if (inputWindowHandle != NULL) { - return inputWindowHandle->getName().string(); - } - if (monitor) { - return "monitor"; - } - return "?"; -} - -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::findWaitQueueEntry(uint32_t seq) { - for (DispatchEntry* entry = waitQueue.head; entry != NULL; entry = entry->next) { - if (entry->seq == seq) { - return entry; - } - } - return NULL; -} - - -// --- InputDispatcher::CommandEntry --- - -InputDispatcher::CommandEntry::CommandEntry(Command command) : - command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0), - seq(0), handled(false) { -} - -InputDispatcher::CommandEntry::~CommandEntry() { -} - - -// --- InputDispatcher::TouchState --- - -InputDispatcher::TouchState::TouchState() : - down(false), split(false), deviceId(-1), source(0), displayId(-1) { -} - -InputDispatcher::TouchState::~TouchState() { -} - -void InputDispatcher::TouchState::reset() { - down = false; - split = false; - deviceId = -1; - source = 0; - displayId = -1; - windows.clear(); -} - -void InputDispatcher::TouchState::copyFrom(const TouchState& other) { - down = other.down; - split = other.split; - deviceId = other.deviceId; - source = other.source; - displayId = other.displayId; - windows = other.windows; -} - -void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, - 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.windowHandle == windowHandle) { - touchedWindow.targetFlags |= targetFlags; - if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) { - touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS; - } - touchedWindow.pointerIds.value |= pointerIds.value; - return; - } - } - - windows.push(); - - TouchedWindow& touchedWindow = windows.editTop(); - touchedWindow.windowHandle = windowHandle; - touchedWindow.targetFlags = targetFlags; - touchedWindow.pointerIds = pointerIds; -} - -void InputDispatcher::TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) { - for (size_t i = 0; i < windows.size(); i++) { - if (windows.itemAt(i).windowHandle == windowHandle) { - windows.removeAt(i); - return; - } - } -} - -void InputDispatcher::TouchState::filterNonAsIsTouchWindows() { - for (size_t i = 0 ; i < windows.size(); ) { - TouchedWindow& window = windows.editItemAt(i); - if (window.targetFlags & (InputTarget::FLAG_DISPATCH_AS_IS - | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) { - window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK; - window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS; - i += 1; - } else { - windows.removeAt(i); - } - } -} - -sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const { - for (size_t i = 0; i < windows.size(); i++) { - const TouchedWindow& window = windows.itemAt(i); - if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { - return window.windowHandle; - } - } - return NULL; -} - -bool InputDispatcher::TouchState::isSlippery() const { - // Must have exactly one foreground window. - bool haveSlipperyForegroundWindow = false; - for (size_t i = 0; i < windows.size(); i++) { - const TouchedWindow& window = windows.itemAt(i); - if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { - if (haveSlipperyForegroundWindow - || !(window.windowHandle->getInfo()->layoutParamsFlags - & InputWindowInfo::FLAG_SLIPPERY)) { - return false; - } - haveSlipperyForegroundWindow = true; - } - } - return haveSlipperyForegroundWindow; -} - - -// --- 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/widget/gonk/libui/InputDispatcher.h b/widget/gonk/libui/InputDispatcher.h deleted file mode 100644 index 5453421f6..000000000 --- a/widget/gonk/libui/InputDispatcher.h +++ /dev/null @@ -1,1117 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UI_INPUT_DISPATCHER_H -#define _UI_INPUT_DISPATCHER_H - -#include "Input.h" -#include "InputTransport.h" -#include <utils/KeyedVector.h> -#include <utils/Vector.h> -#include <utils/threads.h> -#include <utils/Timers.h> -#include <utils/RefBase.h> -#include <utils/String8.h> -#include <utils/Looper.h> -#include <utils/BitSet.h> -#include <cutils/atomic.h> - -#include <stddef.h> -#include <unistd.h> -#include <limits.h> - -#include "InputWindow.h" -#include "InputApplication.h" -#include "InputListener.h" - - -namespace android { - -/* - * Constants used to report the outcome of input event injection. - */ -enum { - /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */ - INPUT_EVENT_INJECTION_PENDING = -1, - - /* Injection succeeded. */ - INPUT_EVENT_INJECTION_SUCCEEDED = 0, - - /* Injection failed because the injector did not have permission to inject - * into the application with input focus. */ - INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1, - - /* Injection failed because there were no available input targets. */ - INPUT_EVENT_INJECTION_FAILED = 2, - - /* Injection failed due to a timeout. */ - INPUT_EVENT_INJECTION_TIMED_OUT = 3 -}; - -/* - * Constants used to determine the input event injection synchronization mode. - */ -enum { - /* Injection is asynchronous and is assumed always to be successful. */ - INPUT_EVENT_INJECTION_SYNC_NONE = 0, - - /* Waits for previous events to be dispatched so that the input dispatcher can determine - * whether input event injection willbe permitted based on the current input focus. - * Does not wait for the input event to finish processing. */ - INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1, - - /* Waits for the input event to be completely processed. */ - INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2, -}; - - -/* - * An input target specifies how an input event is to be dispatched to a particular window - * including the window's input channel, control flags, a timeout, and an X / Y offset to - * be added to input event coordinates to compensate for the absolute position of the - * window area. - */ -struct InputTarget { - enum { - /* This flag indicates that the event is being delivered to a foreground application. */ - FLAG_FOREGROUND = 1 << 0, - - /* This flag indicates that the target of a MotionEvent is partly or wholly - * obscured by another visible window above it. The motion event should be - * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */ - FLAG_WINDOW_IS_OBSCURED = 1 << 1, - - /* This flag indicates that a motion event is being split across multiple windows. */ - FLAG_SPLIT = 1 << 2, - - /* This flag indicates that the pointer coordinates dispatched to the application - * will be zeroed out to avoid revealing information to an application. This is - * used in conjunction with FLAG_DISPATCH_AS_OUTSIDE to prevent apps not sharing - * the same UID from watching all touches. */ - FLAG_ZERO_COORDS = 1 << 3, - - /* This flag indicates that the event should be sent as is. - * Should always be set unless the event is to be transmuted. */ - FLAG_DISPATCH_AS_IS = 1 << 8, - - /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside - * of the area of this target and so should instead be delivered as an - * AMOTION_EVENT_ACTION_OUTSIDE to this target. */ - FLAG_DISPATCH_AS_OUTSIDE = 1 << 9, - - /* This flag indicates that a hover sequence is starting in the given window. - * The event is transmuted into ACTION_HOVER_ENTER. */ - FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10, - - /* This flag indicates that a hover event happened outside of a window which handled - * previous hover events, signifying the end of the current hover sequence for that - * window. - * The event is transmuted into ACTION_HOVER_ENTER. */ - FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11, - - /* This flag indicates that the event should be canceled. - * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips - * outside of a window. */ - FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12, - - /* This flag indicates that the event should be dispatched as an initial down. - * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips - * into a new window. */ - FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13, - - /* Mask for all dispatch modes. */ - FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS - | FLAG_DISPATCH_AS_OUTSIDE - | FLAG_DISPATCH_AS_HOVER_ENTER - | FLAG_DISPATCH_AS_HOVER_EXIT - | FLAG_DISPATCH_AS_SLIPPERY_EXIT - | FLAG_DISPATCH_AS_SLIPPERY_ENTER, - }; - - // The input channel to be targeted. - sp<InputChannel> inputChannel; - - // Flags for the input target. - int32_t flags; - - // The x and y offset to add to a MotionEvent as it is delivered. - // (ignored for KeyEvents) - float xOffset, yOffset; - - // Scaling factor to apply to MotionEvent as it is delivered. - // (ignored for KeyEvents) - float scaleFactor; - - // The subset of pointer ids to include in motion events dispatched to this input target - // if FLAG_SPLIT is set. - BitSet32 pointerIds; -}; - - -/* - * Input dispatcher configuration. - * - * Specifies various options that modify the behavior of the input dispatcher. - * The values provided here are merely defaults. The actual values will come from ViewConfiguration - * and are passed into the dispatcher during initialization. - */ -struct InputDispatcherConfiguration { - // The key repeat initial timeout. - nsecs_t keyRepeatTimeout; - - // The key repeat inter-key delay. - nsecs_t keyRepeatDelay; - - InputDispatcherConfiguration() : - keyRepeatTimeout(500 * 1000000LL), - keyRepeatDelay(50 * 1000000LL) { } -}; - - -/* - * Input dispatcher policy interface. - * - * The input reader policy is used by the input reader to interact with the Window Manager - * and other system components. - * - * The actual implementation is partially supported by callbacks into the DVM - * via JNI. This interface is also mocked in the unit tests. - */ -class InputDispatcherPolicyInterface : public virtual RefBase { -protected: - InputDispatcherPolicyInterface() { } - virtual ~InputDispatcherPolicyInterface() { } - -public: - /* Notifies the system that a configuration change has occurred. */ - virtual void notifyConfigurationChanged(nsecs_t when) = 0; - - /* Notifies the system that an application is not responding. - * Returns a new timeout to continue waiting, or 0 to abort dispatch. */ - virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, - const sp<InputWindowHandle>& inputWindowHandle) = 0; - - /* Notifies the system that an input channel is unrecoverably broken. */ - virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0; - - /* Gets the input dispatcher configuration. */ - virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0; - - /* Returns true if automatic key repeating is enabled. */ - virtual bool isKeyRepeatEnabled() = 0; - - /* Filters an input event. - * Return true to dispatch the event unmodified, false to consume the event. - * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED - * to injectInputEvent. - */ - virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0; - - /* Intercepts a key event immediately before queueing it. - * The policy can use this method as an opportunity to perform power management functions - * and early event preprocessing such as updating policy flags. - * - * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event - * should be dispatched to applications. - */ - virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0; - - /* Intercepts a touch, trackball or other motion event before queueing it. - * The policy can use this method as an opportunity to perform power management functions - * and early event preprocessing such as updating policy flags. - * - * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event - * should be dispatched to applications. - */ - virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0; - - /* Allows the policy a chance to intercept a key before dispatching. */ - virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle, - const KeyEvent* keyEvent, uint32_t policyFlags) = 0; - - /* Allows the policy a chance to perform default processing for an unhandled key. - * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */ - virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle, - const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0; - - /* Notifies the policy about switch events. - */ - virtual void notifySwitch(nsecs_t when, - uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) = 0; - - /* Poke user activity for an event dispatched to a window. */ - virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0; - - /* Checks whether a given application pid/uid has permission to inject input events - * into other applications. - * - * This method is special in that its implementation promises to be non-reentrant and - * is safe to call while holding other locks. (Most other methods make no such guarantees!) - */ - virtual bool checkInjectEventsPermissionNonReentrant( - int32_t injectorPid, int32_t injectorUid) = 0; -}; - - -/* Notifies the system about input events generated by the input reader. - * The dispatcher is expected to be mostly asynchronous. */ -class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface { -protected: - InputDispatcherInterface() { } - virtual ~InputDispatcherInterface() { } - -public: - /* Dumps the state of the input dispatcher. - * - * This method may be called on any thread (usually by the input manager). */ - virtual void dump(String8& dump) = 0; - - /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */ - virtual void monitor() = 0; - - /* Runs a single iteration of the dispatch loop. - * Nominally processes one queued event, a timeout, or a response from an input consumer. - * - * This method should only be called on the input dispatcher thread. - */ - virtual void dispatchOnce() = 0; - - /* Injects an input event and optionally waits for sync. - * The synchronization mode determines whether the method blocks while waiting for - * input injection to proceed. - * Returns one of the INPUT_EVENT_INJECTION_XXX constants. - * - * This method may be called on any thread (usually by the input manager). - */ - virtual int32_t injectInputEvent(const InputEvent* event, - int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, - uint32_t policyFlags) = 0; - - /* Sets the list of input windows. - * - * This method may be called on any thread (usually by the input manager). - */ - virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0; - - /* Sets the focused application. - * - * This method may be called on any thread (usually by the input manager). - */ - virtual void setFocusedApplication( - const sp<InputApplicationHandle>& inputApplicationHandle) = 0; - - /* Sets the input dispatching mode. - * - * This method may be called on any thread (usually by the input manager). - */ - virtual void setInputDispatchMode(bool enabled, bool frozen) = 0; - - /* Sets whether input event filtering is enabled. - * When enabled, incoming input events are sent to the policy's filterInputEvent - * method instead of being dispatched. The filter is expected to use - * injectInputEvent to inject the events it would like to have dispatched. - * It should include POLICY_FLAG_FILTERED in the policy flags during injection. - */ - virtual void setInputFilterEnabled(bool enabled) = 0; - - /* Transfers touch focus from the window associated with one channel to the - * window associated with the other channel. - * - * Returns true on success. False if the window did not actually have touch focus. - */ - virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel, - const sp<InputChannel>& toChannel) = 0; - - /* Registers or unregister input channels that may be used as targets for input events. - * If monitor is true, the channel will receive a copy of all input events. - * - * These methods may be called on any thread (usually by the input manager). - */ - virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, - const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0; - virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0; -}; - -/* Dispatches events to input targets. Some functions of the input dispatcher, such as - * identifying input targets, are controlled by a separate policy object. - * - * IMPORTANT INVARIANT: - * Because the policy can potentially block or cause re-entrance into the input dispatcher, - * the input dispatcher never calls into the policy while holding its internal locks. - * The implementation is also carefully designed to recover from scenarios such as an - * input channel becoming unregistered while identifying input targets or processing timeouts. - * - * Methods marked 'Locked' must be called with the lock acquired. - * - * Methods marked 'LockedInterruptible' must be called with the lock acquired but - * may during the course of their execution release the lock, call into the policy, and - * then reacquire the lock. The caller is responsible for recovering gracefully. - * - * A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa. - */ -class InputDispatcher : public InputDispatcherInterface { -protected: - virtual ~InputDispatcher(); - -public: - explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy); - - virtual void dump(String8& dump); - virtual void monitor(); - - virtual void dispatchOnce(); - - virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args); - virtual void notifyKey(const NotifyKeyArgs* args); - virtual void notifyMotion(const NotifyMotionArgs* args); - virtual void notifySwitch(const NotifySwitchArgs* args); - virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args); - - virtual int32_t injectInputEvent(const InputEvent* event, - int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, - uint32_t policyFlags); - - virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles); - virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle); - virtual void setInputDispatchMode(bool enabled, bool frozen); - virtual void setInputFilterEnabled(bool enabled); - - virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel, - const sp<InputChannel>& toChannel); - - virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, - const sp<InputWindowHandle>& inputWindowHandle, bool monitor); - virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel); - -private: - template <typename T> - struct Link { - T* next; - T* prev; - - protected: - inline Link() : next(NULL), prev(NULL) { } - }; - - struct InjectionState { - mutable int32_t refCount; - - int32_t injectorPid; - int32_t injectorUid; - int32_t injectionResult; // initially INPUT_EVENT_INJECTION_PENDING - bool injectionIsAsync; // set to true if injection is not waiting for the result - int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress - - InjectionState(int32_t injectorPid, int32_t injectorUid); - void release(); - - private: - ~InjectionState(); - }; - - struct EventEntry : Link<EventEntry> { - enum { - TYPE_CONFIGURATION_CHANGED, - TYPE_DEVICE_RESET, - TYPE_KEY, - TYPE_MOTION - }; - - mutable int32_t refCount; - int32_t type; - nsecs_t eventTime; - uint32_t policyFlags; - InjectionState* injectionState; - - bool dispatchInProgress; // initially false, set to true while dispatching - - inline bool isInjected() const { return injectionState != NULL; } - - void release(); - - virtual void appendDescription(String8& msg) const = 0; - - protected: - EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags); - virtual ~EventEntry(); - void releaseInjectionState(); - }; - - struct ConfigurationChangedEntry : EventEntry { - ConfigurationChangedEntry(nsecs_t eventTime); - virtual void appendDescription(String8& msg) const; - - protected: - virtual ~ConfigurationChangedEntry(); - }; - - struct DeviceResetEntry : EventEntry { - int32_t deviceId; - - DeviceResetEntry(nsecs_t eventTime, int32_t deviceId); - virtual void appendDescription(String8& msg) const; - - protected: - virtual ~DeviceResetEntry(); - }; - - struct KeyEntry : EventEntry { - int32_t deviceId; - uint32_t source; - int32_t action; - int32_t flags; - int32_t keyCode; - int32_t scanCode; - int32_t metaState; - int32_t repeatCount; - nsecs_t downTime; - - bool syntheticRepeat; // set to true for synthetic key repeats - - enum InterceptKeyResult { - INTERCEPT_KEY_RESULT_UNKNOWN, - INTERCEPT_KEY_RESULT_SKIP, - INTERCEPT_KEY_RESULT_CONTINUE, - INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER, - }; - InterceptKeyResult interceptKeyResult; // set based on the interception result - nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER - - KeyEntry(nsecs_t eventTime, - int32_t deviceId, uint32_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); - virtual void appendDescription(String8& msg) const; - void recycle(); - - protected: - virtual ~KeyEntry(); - }; - - struct MotionEntry : EventEntry { - nsecs_t eventTime; - int32_t deviceId; - uint32_t source; - int32_t action; - int32_t flags; - int32_t metaState; - int32_t buttonState; - int32_t edgeFlags; - float xPrecision; - float yPrecision; - nsecs_t downTime; - int32_t displayId; - uint32_t pointerCount; - PointerProperties pointerProperties[MAX_POINTERS]; - PointerCoords pointerCoords[MAX_POINTERS]; - - MotionEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, - int32_t action, int32_t flags, - int32_t metaState, int32_t buttonState, int32_t edgeFlags, - float xPrecision, float yPrecision, - nsecs_t downTime, int32_t displayId, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); - virtual void appendDescription(String8& msg) const; - - protected: - virtual ~MotionEntry(); - }; - - // Tracks the progress of dispatching a particular event to a particular connection. - struct DispatchEntry : Link<DispatchEntry> { - const uint32_t seq; // unique sequence number, never 0 - - EventEntry* eventEntry; // the event to dispatch - int32_t targetFlags; - float xOffset; - float yOffset; - float scaleFactor; - nsecs_t deliveryTime; // time when the event was actually delivered - - // Set to the resolved action and flags when the event is enqueued. - int32_t resolvedAction; - int32_t resolvedFlags; - - DispatchEntry(EventEntry* eventEntry, - int32_t targetFlags, float xOffset, float yOffset, float scaleFactor); - ~DispatchEntry(); - - inline bool hasForegroundTarget() const { - return targetFlags & InputTarget::FLAG_FOREGROUND; - } - - inline bool isSplit() const { - return targetFlags & InputTarget::FLAG_SPLIT; - } - - private: - static volatile int32_t sNextSeqAtomic; - - static uint32_t nextSeq(); - }; - - // A command entry captures state and behavior for an action to be performed in the - // dispatch loop after the initial processing has taken place. It is essentially - // a kind of continuation used to postpone sensitive policy interactions to a point - // in the dispatch loop where it is safe to release the lock (generally after finishing - // the critical parts of the dispatch cycle). - // - // The special thing about commands is that they can voluntarily release and reacquire - // the dispatcher lock at will. Initially when the command starts running, the - // dispatcher lock is held. However, if the command needs to call into the policy to - // do some work, it can release the lock, do the work, then reacquire the lock again - // before returning. - // - // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch - // never calls into the policy while holding its lock. - // - // Commands are implicitly 'LockedInterruptible'. - struct CommandEntry; - typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry); - - class Connection; - struct CommandEntry : Link<CommandEntry> { - CommandEntry(Command command); - ~CommandEntry(); - - Command command; - - // parameters for the command (usage varies by command) - sp<Connection> connection; - nsecs_t eventTime; - KeyEntry* keyEntry; - sp<InputApplicationHandle> inputApplicationHandle; - sp<InputWindowHandle> inputWindowHandle; - int32_t userActivityEventType; - uint32_t seq; - bool handled; - }; - - // Generic queue implementation. - template <typename T> - struct Queue { - T* head; - T* tail; - - inline Queue() : head(NULL), tail(NULL) { - } - - inline bool isEmpty() const { - return !head; - } - - inline void enqueueAtTail(T* entry) { - entry->prev = tail; - if (tail) { - tail->next = entry; - } else { - head = entry; - } - entry->next = NULL; - tail = entry; - } - - inline void enqueueAtHead(T* entry) { - entry->next = head; - if (head) { - head->prev = entry; - } else { - tail = entry; - } - entry->prev = NULL; - head = entry; - } - - inline void dequeue(T* entry) { - if (entry->prev) { - entry->prev->next = entry->next; - } else { - head = entry->next; - } - if (entry->next) { - entry->next->prev = entry->prev; - } else { - tail = entry->prev; - } - } - - inline T* dequeueAtHead() { - T* entry = head; - head = entry->next; - if (head) { - head->prev = NULL; - } else { - tail = NULL; - } - return entry; - } - - uint32_t count() const; - }; - - /* Specifies which events are to be canceled and why. */ - struct CancelationOptions { - enum Mode { - CANCEL_ALL_EVENTS = 0, - CANCEL_POINTER_EVENTS = 1, - CANCEL_NON_POINTER_EVENTS = 2, - CANCEL_FALLBACK_EVENTS = 3, - }; - - // The criterion to use to determine which events should be canceled. - Mode mode; - - // Descriptive reason for the cancelation. - const char* reason; - - // The specific keycode of the key event to cancel, or -1 to cancel any key event. - int32_t keyCode; - - // The specific device id of events to cancel, or -1 to cancel events from any device. - int32_t deviceId; - - CancelationOptions(Mode mode, const char* reason) : - mode(mode), reason(reason), keyCode(-1), deviceId(-1) { } - }; - - /* Tracks dispatched key and motion event state so that cancelation events can be - * synthesized when events are dropped. */ - class InputState { - public: - InputState(); - ~InputState(); - - // Returns true if there is no state to be canceled. - bool isNeutral() const; - - // Returns true if the specified source is known to have received a hover enter - // motion event. - bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const; - - // Records tracking information for a key event that has just been published. - // Returns true if the event should be delivered, false if it is inconsistent - // and should be skipped. - bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags); - - // Records tracking information for a motion event that has just been published. - // Returns true if the event should be delivered, false if it is inconsistent - // and should be skipped. - bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags); - - // Synthesizes cancelation events for the current state and resets the tracked state. - void synthesizeCancelationEvents(nsecs_t currentTime, - Vector<EventEntry*>& outEvents, const CancelationOptions& options); - - // Clears the current state. - void clear(); - - // Copies pointer-related parts of the input state to another instance. - void copyPointerStateTo(InputState& other) const; - - // Gets the fallback key associated with a keycode. - // Returns -1 if none. - // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy. - int32_t getFallbackKey(int32_t originalKeyCode); - - // Sets the fallback key for a particular keycode. - void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode); - - // Removes the fallback key for a particular keycode. - void removeFallbackKey(int32_t originalKeyCode); - - inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const { - return mFallbackKeys; - } - - private: - struct KeyMemento { - int32_t deviceId; - uint32_t source; - int32_t keyCode; - int32_t scanCode; - int32_t metaState; - int32_t flags; - nsecs_t downTime; - uint32_t policyFlags; - }; - - struct MotionMemento { - int32_t deviceId; - uint32_t source; - int32_t flags; - float xPrecision; - float yPrecision; - nsecs_t downTime; - int32_t displayId; - uint32_t pointerCount; - PointerProperties pointerProperties[MAX_POINTERS]; - PointerCoords pointerCoords[MAX_POINTERS]; - bool hovering; - uint32_t policyFlags; - - void setPointers(const MotionEntry* entry); - }; - - Vector<KeyMemento> mKeyMementos; - Vector<MotionMemento> mMotionMementos; - KeyedVector<int32_t, int32_t> mFallbackKeys; - - ssize_t findKeyMemento(const KeyEntry* entry) const; - ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const; - - void addKeyMemento(const KeyEntry* entry, int32_t flags); - void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering); - - static bool shouldCancelKey(const KeyMemento& memento, - const CancelationOptions& options); - static bool shouldCancelMotion(const MotionMemento& memento, - const CancelationOptions& options); - }; - - /* Manages the dispatch state associated with a single input channel. */ - class Connection : public RefBase { - protected: - virtual ~Connection(); - - public: - enum Status { - // Everything is peachy. - STATUS_NORMAL, - // An unrecoverable communication error has occurred. - STATUS_BROKEN, - // The input channel has been unregistered. - STATUS_ZOMBIE - }; - - Status status; - sp<InputChannel> inputChannel; // never null - sp<InputWindowHandle> inputWindowHandle; // may be null - bool monitor; - InputPublisher inputPublisher; - InputState inputState; - - // True if the socket is full and no further events can be published until - // the application consumes some of the input. - bool inputPublisherBlocked; - - // Queue of events that need to be published to the connection. - Queue<DispatchEntry> outboundQueue; - - // Queue of events that have been published to the connection but that have not - // yet received a "finished" response from the application. - Queue<DispatchEntry> waitQueue; - - explicit Connection(const sp<InputChannel>& inputChannel, - const sp<InputWindowHandle>& inputWindowHandle, bool monitor); - - inline const char* getInputChannelName() const { return inputChannel->getName().string(); } - - const char* getWindowName() const; - const char* getStatusLabel() const; - - DispatchEntry* findWaitQueueEntry(uint32_t seq); - }; - - enum DropReason { - DROP_REASON_NOT_DROPPED = 0, - DROP_REASON_POLICY = 1, - DROP_REASON_APP_SWITCH = 2, - DROP_REASON_DISABLED = 3, - DROP_REASON_BLOCKED = 4, - DROP_REASON_STALE = 5, - }; - - sp<InputDispatcherPolicyInterface> mPolicy; - InputDispatcherConfiguration mConfig; - - Mutex mLock; - - Condition mDispatcherIsAliveCondition; - - sp<Looper> mLooper; - - EventEntry* mPendingEvent; - Queue<EventEntry> mInboundQueue; - Queue<CommandEntry> mCommandQueue; - - void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime); - - // Enqueues an inbound event. Returns true if mLooper->wake() should be called. - bool enqueueInboundEventLocked(EventEntry* entry); - - // Cleans up input state when dropping an inbound event. - void dropInboundEventLocked(EventEntry* entry, DropReason dropReason); - - // App switch latency optimization. - bool mAppSwitchSawKeyDown; - nsecs_t mAppSwitchDueTime; - - static bool isAppSwitchKeyCode(int32_t keyCode); - bool isAppSwitchKeyEventLocked(KeyEntry* keyEntry); - bool isAppSwitchPendingLocked(); - void resetPendingAppSwitchLocked(bool handled); - - // Stale event latency optimization. - static bool isStaleEventLocked(nsecs_t currentTime, EventEntry* entry); - - // Blocked event latency optimization. Drops old events when the user intends - // to transfer focus to a new application. - EventEntry* mNextUnblockedEvent; - - sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y); - - // All registered connections mapped by channel file descriptor. - KeyedVector<int, sp<Connection> > mConnectionsByFd; - - ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel); - - // Input channels that will receive a copy of all input events. - Vector<sp<InputChannel> > mMonitoringChannels; - - // Event injection and synchronization. - Condition mInjectionResultAvailableCondition; - bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid); - void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult); - - Condition mInjectionSyncFinishedCondition; - void incrementPendingForegroundDispatchesLocked(EventEntry* entry); - void decrementPendingForegroundDispatchesLocked(EventEntry* entry); - - // Key repeat tracking. - struct KeyRepeatState { - KeyEntry* lastKeyEntry; // or null if no repeat - nsecs_t nextRepeatTime; - } mKeyRepeatState; - - void resetKeyRepeatLocked(); - KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime); - - // Deferred command processing. - bool haveCommandsLocked() const; - bool runCommandsLockedInterruptible(); - CommandEntry* postCommandLocked(Command command); - - // Input filter processing. - bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args); - bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args); - - // Inbound event processing. - void drainInboundQueueLocked(); - void releasePendingEventLocked(); - void releaseInboundEventLocked(EventEntry* entry); - - // Dispatch state. - bool mDispatchEnabled; - bool mDispatchFrozen; - bool mInputFilterEnabled; - - Vector<sp<InputWindowHandle> > mWindowHandles; - - sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const; - bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const; - - // Focus tracking for keys, trackball, etc. - sp<InputWindowHandle> mFocusedWindowHandle; - - // Focus tracking for touch. - struct TouchedWindow { - sp<InputWindowHandle> windowHandle; - int32_t targetFlags; - BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set - }; - struct TouchState { - bool down; - bool split; - int32_t deviceId; // id of the device that is currently down, others are rejected - uint32_t source; // source of the device that is current down, others are rejected - int32_t displayId; // id to the display that currently has a touch, others are rejected - Vector<TouchedWindow> windows; - - TouchState(); - ~TouchState(); - void reset(); - void copyFrom(const TouchState& other); - void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, - int32_t targetFlags, BitSet32 pointerIds); - void removeWindow(const sp<InputWindowHandle>& windowHandle); - void filterNonAsIsTouchWindows(); - sp<InputWindowHandle> getFirstForegroundWindowHandle() const; - bool isSlippery() const; - }; - - TouchState mTouchState; - TouchState mTempTouchState; - - // Focused application. - sp<InputApplicationHandle> mFocusedApplicationHandle; - - // Dispatcher state at time of last ANR. - String8 mLastANRState; - - // Dispatch inbound events. - bool dispatchConfigurationChangedLocked( - nsecs_t currentTime, ConfigurationChangedEntry* entry); - bool dispatchDeviceResetLocked( - nsecs_t currentTime, DeviceResetEntry* entry); - bool dispatchKeyLocked( - nsecs_t currentTime, KeyEntry* entry, - DropReason* dropReason, nsecs_t* nextWakeupTime); - bool dispatchMotionLocked( - nsecs_t currentTime, MotionEntry* entry, - DropReason* dropReason, nsecs_t* nextWakeupTime); - void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry, - const Vector<InputTarget>& inputTargets); - - void logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry); - void logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry); - - // Keeping track of ANR timeouts. - enum InputTargetWaitCause { - INPUT_TARGET_WAIT_CAUSE_NONE, - INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY, - INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY, - }; - - InputTargetWaitCause mInputTargetWaitCause; - nsecs_t mInputTargetWaitStartTime; - nsecs_t mInputTargetWaitTimeoutTime; - bool mInputTargetWaitTimeoutExpired; - sp<InputApplicationHandle> mInputTargetWaitApplicationHandle; - - // Contains the last window which received a hover event. - sp<InputWindowHandle> mLastHoverWindowHandle; - - // Finding targets for input events. - int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry, - const sp<InputApplicationHandle>& applicationHandle, - const sp<InputWindowHandle>& windowHandle, - nsecs_t* nextWakeupTime, const char* reason); - void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout, - const sp<InputChannel>& inputChannel); - nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime); - void resetANRTimeoutsLocked(); - - int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry, - Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime); - int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry, - Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime, - bool* outConflictingPointerActions); - - void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, - int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets); - void addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets); - - void pokeUserActivityLocked(const EventEntry* eventEntry); - bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, - const InjectionState* injectionState); - bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle, - int32_t x, int32_t y) const; - bool isWindowReadyForMoreInputLocked(nsecs_t currentTime, - const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry); - String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle, - const sp<InputWindowHandle>& windowHandle); - - // Manage the dispatch cycle for a single connection. - // These methods are deliberately not Interruptible because doing all of the work - // with the mutex held makes it easier to ensure that connection invariants are maintained. - // If needed, the methods post commands to run later once the critical bits are done. - void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, - EventEntry* eventEntry, const InputTarget* inputTarget); - void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection, - EventEntry* eventEntry, const InputTarget* inputTarget); - void enqueueDispatchEntryLocked(const sp<Connection>& connection, - EventEntry* eventEntry, const InputTarget* inputTarget, int32_t dispatchMode); - void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); - void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, - uint32_t seq, bool handled); - void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, - bool notify); - void drainDispatchQueueLocked(Queue<DispatchEntry>* queue); - void releaseDispatchEntryLocked(DispatchEntry* dispatchEntry); - static int handleReceiveCallback(int fd, int events, void* data); - - void synthesizeCancelationEventsForAllConnectionsLocked( - const CancelationOptions& options); - void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel, - const CancelationOptions& options); - void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection, - const CancelationOptions& options); - - // Splitting motion events across windows. - MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds); - - // Reset and drop everything the dispatcher is doing. - void resetAndDropEverythingLocked(const char* reason); - - // Dump state. - void dumpDispatchStateLocked(String8& dump); - void logDispatchStateLocked(); - - // Registration. - void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel); - status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify); - - // Add or remove a connection to the mActiveConnections vector. - void activateConnectionLocked(Connection* connection); - void deactivateConnectionLocked(Connection* connection); - - // Interesting events that we might like to log or tell the framework about. - void onDispatchCycleFinishedLocked( - nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled); - void onDispatchCycleBrokenLocked( - nsecs_t currentTime, const sp<Connection>& connection); - void onANRLocked( - nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle, - const sp<InputWindowHandle>& windowHandle, - nsecs_t eventTime, nsecs_t waitStartTime, const char* reason); - - // Outbound policy interactions. - void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry); - void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry); - void doNotifyANRLockedInterruptible(CommandEntry* commandEntry); - void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry); - void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry); - bool afterKeyEventLockedInterruptible(const sp<Connection>& connection, - DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled); - bool afterMotionEventLockedInterruptible(const sp<Connection>& connection, - DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled); - void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry); - void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry); - - // Statistics gathering. - void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry, - int32_t injectionResult, nsecs_t timeSpentWaitingForApplication); - void traceInboundQueueLengthLocked(); - void traceOutboundQueueLengthLocked(const sp<Connection>& connection); - void traceWaitQueueLengthLocked(const sp<Connection>& connection); -}; - -/* Enqueues and dispatches input events, endlessly. */ -class InputDispatcherThread : public Thread { -public: - explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher); - ~InputDispatcherThread(); - -private: - virtual bool threadLoop(); - - sp<InputDispatcherInterface> mDispatcher; -}; - -} // namespace android - -#endif // _UI_INPUT_DISPATCHER_H diff --git a/widget/gonk/libui/InputListener.cpp b/widget/gonk/libui/InputListener.cpp deleted file mode 100644 index 3b673f0ad..000000000 --- a/widget/gonk/libui/InputListener.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputListener" - -//#define LOG_NDEBUG 0 - -#include "InputListener.h" - -#include "cutils_log.h" - -namespace android { - -// --- NotifyConfigurationChangedArgs --- - -NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(nsecs_t eventTime) : - eventTime(eventTime) { -} - -NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs( - const NotifyConfigurationChangedArgs& other) : - eventTime(other.eventTime) { -} - -void NotifyConfigurationChangedArgs::notify(const sp<InputListenerInterface>& listener) const { - listener->notifyConfigurationChanged(this); -} - - -// --- NotifyKeyArgs --- - -NotifyKeyArgs::NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, - uint32_t policyFlags, - int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, - int32_t metaState, nsecs_t downTime) : - eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags), - action(action), flags(flags), keyCode(keyCode), scanCode(scanCode), - metaState(metaState), downTime(downTime) { -} - -NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) : - eventTime(other.eventTime), deviceId(other.deviceId), source(other.source), - policyFlags(other.policyFlags), - action(other.action), flags(other.flags), - keyCode(other.keyCode), scanCode(other.scanCode), - metaState(other.metaState), downTime(other.downTime) { -} - -void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const { - listener->notifyKey(this); -} - - -// --- NotifyMotionArgs --- - -NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, - uint32_t policyFlags, - int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, int32_t displayId, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, - float xPrecision, float yPrecision, nsecs_t downTime) : - eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags), - action(action), flags(flags), metaState(metaState), buttonState(buttonState), - edgeFlags(edgeFlags), displayId(displayId), pointerCount(pointerCount), - xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) { - for (uint32_t i = 0; i < pointerCount; i++) { - this->pointerProperties[i].copyFrom(pointerProperties[i]); - this->pointerCoords[i].copyFrom(pointerCoords[i]); - } -} - -NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) : - eventTime(other.eventTime), deviceId(other.deviceId), source(other.source), - policyFlags(other.policyFlags), - action(other.action), flags(other.flags), - metaState(other.metaState), buttonState(other.buttonState), - edgeFlags(other.edgeFlags), displayId(other.displayId), - pointerCount(other.pointerCount), - xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) { - for (uint32_t i = 0; i < pointerCount; i++) { - pointerProperties[i].copyFrom(other.pointerProperties[i]); - pointerCoords[i].copyFrom(other.pointerCoords[i]); - } -} - -void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const { - listener->notifyMotion(this); -} - - -// --- NotifySwitchArgs --- - -NotifySwitchArgs::NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags, - uint32_t switchValues, uint32_t switchMask) : - eventTime(eventTime), policyFlags(policyFlags), - switchValues(switchValues), switchMask(switchMask) { -} - -NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) : - eventTime(other.eventTime), policyFlags(other.policyFlags), - switchValues(other.switchValues), switchMask(other.switchMask) { -} - -void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const { - listener->notifySwitch(this); -} - - -// --- NotifyDeviceResetArgs --- - -NotifyDeviceResetArgs::NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId) : - eventTime(eventTime), deviceId(deviceId) { -} - -NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) : - eventTime(other.eventTime), deviceId(other.deviceId) { -} - -void NotifyDeviceResetArgs::notify(const sp<InputListenerInterface>& listener) const { - listener->notifyDeviceReset(this); -} - - -// --- QueuedInputListener --- - -QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) : - mInnerListener(innerListener) { -} - -QueuedInputListener::~QueuedInputListener() { - size_t count = mArgsQueue.size(); - for (size_t i = 0; i < count; i++) { - delete mArgsQueue[i]; - } -} - -void QueuedInputListener::notifyConfigurationChanged( - const NotifyConfigurationChangedArgs* args) { - mArgsQueue.push(new NotifyConfigurationChangedArgs(*args)); -} - -void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) { - mArgsQueue.push(new NotifyKeyArgs(*args)); -} - -void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) { - mArgsQueue.push(new NotifyMotionArgs(*args)); -} - -void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) { - mArgsQueue.push(new NotifySwitchArgs(*args)); -} - -void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) { - mArgsQueue.push(new NotifyDeviceResetArgs(*args)); -} - -void QueuedInputListener::flush() { - size_t count = mArgsQueue.size(); - for (size_t i = 0; i < count; i++) { - NotifyArgs* args = mArgsQueue[i]; - args->notify(mInnerListener); - delete args; - } - mArgsQueue.clear(); -} - - -} // namespace android diff --git a/widget/gonk/libui/InputListener.h b/widget/gonk/libui/InputListener.h deleted file mode 100644 index de799322f..000000000 --- a/widget/gonk/libui/InputListener.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UI_INPUT_LISTENER_H -#define _UI_INPUT_LISTENER_H - -#include "Input.h" -#include <utils/RefBase.h> -#include <utils/Vector.h> - -namespace android { - -class InputListenerInterface; - - -/* Superclass of all input event argument objects */ -struct NotifyArgs { - virtual ~NotifyArgs() { } - - virtual void notify(const sp<InputListenerInterface>& listener) const = 0; -}; - - -/* Describes a configuration change event. */ -struct NotifyConfigurationChangedArgs : public NotifyArgs { - nsecs_t eventTime; - - inline NotifyConfigurationChangedArgs() { } - - NotifyConfigurationChangedArgs(nsecs_t eventTime); - - NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other); - - virtual ~NotifyConfigurationChangedArgs() { } - - virtual void notify(const sp<InputListenerInterface>& listener) const; -}; - - -/* Describes a key event. */ -struct NotifyKeyArgs : public NotifyArgs { - nsecs_t eventTime; - int32_t deviceId; - uint32_t source; - uint32_t policyFlags; - int32_t action; - int32_t flags; - int32_t keyCode; - int32_t scanCode; - int32_t metaState; - nsecs_t downTime; - - inline NotifyKeyArgs() { } - - NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, - int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, - int32_t metaState, nsecs_t downTime); - - NotifyKeyArgs(const NotifyKeyArgs& other); - - virtual ~NotifyKeyArgs() { } - - virtual void notify(const sp<InputListenerInterface>& listener) const; -}; - - -/* Describes a motion event. */ -struct NotifyMotionArgs : public NotifyArgs { - nsecs_t eventTime; - int32_t deviceId; - uint32_t source; - uint32_t policyFlags; - int32_t action; - int32_t flags; - int32_t metaState; - int32_t buttonState; - int32_t edgeFlags; - int32_t displayId; - uint32_t pointerCount; - PointerProperties pointerProperties[MAX_POINTERS]; - PointerCoords pointerCoords[MAX_POINTERS]; - float xPrecision; - float yPrecision; - nsecs_t downTime; - - inline NotifyMotionArgs() { } - - NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, - int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, int32_t displayId, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, - float xPrecision, float yPrecision, nsecs_t downTime); - - NotifyMotionArgs(const NotifyMotionArgs& other); - - virtual ~NotifyMotionArgs() { } - - virtual void notify(const sp<InputListenerInterface>& listener) const; -}; - - -/* Describes a switch event. */ -struct NotifySwitchArgs : public NotifyArgs { - nsecs_t eventTime; - uint32_t policyFlags; - uint32_t switchValues; - uint32_t switchMask; - - inline NotifySwitchArgs() { } - - NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags, - uint32_t switchValues, uint32_t switchMask); - - NotifySwitchArgs(const NotifySwitchArgs& other); - - virtual ~NotifySwitchArgs() { } - - virtual void notify(const sp<InputListenerInterface>& listener) const; -}; - - -/* Describes a device reset event, such as when a device is added, - * reconfigured, or removed. */ -struct NotifyDeviceResetArgs : public NotifyArgs { - nsecs_t eventTime; - int32_t deviceId; - - inline NotifyDeviceResetArgs() { } - - NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId); - - NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other); - - virtual ~NotifyDeviceResetArgs() { } - - virtual void notify(const sp<InputListenerInterface>& listener) const; -}; - - -/* - * The interface used by the InputReader to notify the InputListener about input events. - */ -class InputListenerInterface : public virtual RefBase { -protected: - InputListenerInterface() { } - virtual ~InputListenerInterface() { } - -public: - virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0; - virtual void notifyKey(const NotifyKeyArgs* args) = 0; - virtual void notifyMotion(const NotifyMotionArgs* args) = 0; - virtual void notifySwitch(const NotifySwitchArgs* args) = 0; - virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0; -}; - - -/* - * An implementation of the listener interface that queues up and defers dispatch - * of decoded events until flushed. - */ -class QueuedInputListener : public InputListenerInterface { -protected: - virtual ~QueuedInputListener(); - -public: - QueuedInputListener(const sp<InputListenerInterface>& innerListener); - - virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args); - virtual void notifyKey(const NotifyKeyArgs* args); - virtual void notifyMotion(const NotifyMotionArgs* args); - virtual void notifySwitch(const NotifySwitchArgs* args); - virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args); - - void flush(); - -private: - sp<InputListenerInterface> mInnerListener; - Vector<NotifyArgs*> mArgsQueue; -}; - -} // namespace android - -#endif // _UI_INPUT_LISTENER_H diff --git a/widget/gonk/libui/InputManager.cpp b/widget/gonk/libui/InputManager.cpp deleted file mode 100644 index 91af056bf..000000000 --- a/widget/gonk/libui/InputManager.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputManager" - -//#define LOG_NDEBUG 0 - -#include "InputManager.h" - -#include "cutils_log.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) { - ALOGE("Could not start InputDispatcher thread due to error %d.", result); - return result; - } - - result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); - if (result) { - ALOGE("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) { - ALOGW("Could not stop InputReader thread due to error %d.", result); - } - - result = mDispatcherThread->requestExitAndWait(); - if (result) { - ALOGW("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/widget/gonk/libui/InputManager.h b/widget/gonk/libui/InputManager.h deleted file mode 100644 index 15a5176ec..000000000 --- a/widget/gonk/libui/InputManager.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UI_INPUT_MANAGER_H -#define _UI_INPUT_MANAGER_H - -/** - * Native input manager. - */ - -#include "EventHub.h" -#include "InputReader.h" -#include "InputDispatcher.h" - -#include "Input.h" -#include "InputTransport.h" -#include <utils/Errors.h> -#include <utils/Vector.h> -#include <utils/Timers.h> -#include <utils/RefBase.h> -#include <utils/String8.h> - -namespace android { - -/* - * The input manager is the core of the system event processing. - * - * The input manager uses two threads. - * - * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events, - * applies policy, and posts messages to a queue managed by the DispatcherThread. - * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the - * queue and asynchronously dispatches them to applications. - * - * By design, the InputReaderThread class and InputDispatcherThread class do not share any - * internal state. Moreover, all communication is done one way from the InputReaderThread - * into the InputDispatcherThread and never the reverse. Both classes may interact with the - * InputDispatchPolicy, however. - * - * The InputManager class never makes any calls into Java itself. Instead, the - * InputDispatchPolicy is responsible for performing all external interactions with the - * system, including calling DVM services. - */ -class InputManagerInterface : public virtual RefBase { -protected: - InputManagerInterface() { } - virtual ~InputManagerInterface() { } - -public: - /* Starts the input manager threads. */ - virtual status_t start() = 0; - - /* Stops the input manager threads and waits for them to exit. */ - virtual status_t stop() = 0; - - /* Gets the input reader. */ - virtual sp<InputReaderInterface> getReader() = 0; - - /* Gets the input dispatcher. */ - virtual sp<InputDispatcherInterface> getDispatcher() = 0; -}; - -class InputManager : public InputManagerInterface { -protected: - virtual ~InputManager(); - -public: - InputManager( - const sp<EventHubInterface>& eventHub, - const sp<InputReaderPolicyInterface>& readerPolicy, - const sp<InputDispatcherPolicyInterface>& dispatcherPolicy); - - // (used for testing purposes) - InputManager( - const sp<InputReaderInterface>& reader, - const sp<InputDispatcherInterface>& dispatcher); - - virtual status_t start(); - virtual status_t stop(); - - virtual sp<InputReaderInterface> getReader(); - virtual sp<InputDispatcherInterface> getDispatcher(); - -private: - sp<InputReaderInterface> mReader; - sp<InputReaderThread> mReaderThread; - - sp<InputDispatcherInterface> mDispatcher; - sp<InputDispatcherThread> mDispatcherThread; - - void initialize(); -}; - -} // namespace android - -#endif // _UI_INPUT_MANAGER_H diff --git a/widget/gonk/libui/InputReader.cpp b/widget/gonk/libui/InputReader.cpp deleted file mode 100644 index 3699569aa..000000000 --- a/widget/gonk/libui/InputReader.cpp +++ /dev/null @@ -1,6510 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputReader" - -//#define LOG_NDEBUG 0 -#include "cutils_log.h" - -// 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 - -// Log debug messages about gesture detection. -#define DEBUG_GESTURES 0 - -// Log debug messages about the vibrator. -#define DEBUG_VIBRATOR 0 - -#include "InputReader.h" - -#include "Keyboard.h" -#include "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 " " -#define INDENT5 " " - -namespace android { - -// --- Constants --- - -// Maximum number of slots supported when using the slot-based Multitouch Protocol B. -static const size_t MAX_SLOTS = 32; - -// --- 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 distance(float x1, float y1, float x2, float y2) { - return hypotf(x1 - x2, y1 - y2); -} - -inline static int32_t signExtendNybble(int32_t value) { - return value >= 8 ? value - 16 : value; -} - -static inline const char* toString(bool value) { - return value ? "true" : "false"; -} - -static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation, - const int32_t map[][4], size_t mapSize) { - if (orientation != DISPLAY_ORIENTATION_0) { - for (size_t i = 0; i < mapSize; i++) { - if (value == map[i][0]) { - return map[i][orientation]; - } - } - } - return value; -} - -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 size_t keyCodeRotationMapSize = - sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]); - -static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) { - return rotateValueUsingRotationMap(keyCode, orientation, - keyCodeRotationMap, keyCodeRotationMapSize); -} - -static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) { - float temp; - switch (orientation) { - case DISPLAY_ORIENTATION_90: - temp = *deltaX; - *deltaX = *deltaY; - *deltaY = -temp; - break; - - case DISPLAY_ORIENTATION_180: - *deltaX = -*deltaX; - *deltaY = -*deltaY; - break; - - case DISPLAY_ORIENTATION_270: - temp = *deltaX; - *deltaX = -*deltaY; - *deltaY = temp; - break; - } -} - -static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) { - return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0; -} - -// Returns true if the pointer should be reported as being down given the specified -// button states. This determines whether the event is reported as a touch event. -static bool isPointerDown(int32_t buttonState) { - return buttonState & - (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY - | AMOTION_EVENT_BUTTON_TERTIARY); -} - -static float calculateCommonVector(float a, float b) { - if (a > 0 && b > 0) { - return a < b ? a : b; - } else if (a < 0 && b < 0) { - return a > b ? a : b; - } else { - return 0; - } -} - -static void synthesizeButtonKey(InputReaderContext* context, int32_t action, - nsecs_t when, int32_t deviceId, uint32_t source, - uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState, - int32_t buttonState, int32_t keyCode) { - if ( - (action == AKEY_EVENT_ACTION_DOWN - && !(lastButtonState & buttonState) - && (currentButtonState & buttonState)) - || (action == AKEY_EVENT_ACTION_UP - && (lastButtonState & buttonState) - && !(currentButtonState & buttonState))) { - NotifyKeyArgs args(when, deviceId, source, policyFlags, - action, 0, keyCode, 0, context->getGlobalMetaState(), when); - context->getListener()->notifyKey(&args); - } -} - -static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, - nsecs_t when, int32_t deviceId, uint32_t source, - uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) { - synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, - lastButtonState, currentButtonState, - AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK); - synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, - lastButtonState, currentButtonState, - AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD); -} - - -// --- InputReaderConfiguration --- - -bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const { - const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay; - if (viewport.displayId >= 0) { - *outViewport = viewport; - return true; - } - return false; -} - -void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) { - DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay; - v = viewport; -} - - -// --- InputReader --- - -InputReader::InputReader(const sp<EventHubInterface>& eventHub, - const sp<InputReaderPolicyInterface>& policy, - const sp<InputListenerInterface>& listener) : - mContext(this), mEventHub(eventHub), mPolicy(policy), - mGlobalMetaState(0), mGeneration(1), - mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), - mConfigurationChangesToRefresh(0) { - mQueuedListener = new QueuedInputListener(listener); - - { // acquire lock - AutoMutex _l(mLock); - - refreshConfigurationLocked(0); - updateGlobalMetaStateLocked(); - } // release lock -} - -InputReader::~InputReader() { - for (size_t i = 0; i < mDevices.size(); i++) { - delete mDevices.valueAt(i); - } -} - -void InputReader::loopOnce() { - int32_t oldGeneration; - int32_t timeoutMillis; - bool inputDevicesChanged = false; - Vector<InputDeviceInfo> inputDevices; - { // acquire lock - AutoMutex _l(mLock); - - oldGeneration = mGeneration; - timeoutMillis = -1; - - uint32_t changes = mConfigurationChangesToRefresh; - if (changes) { - mConfigurationChangesToRefresh = 0; - timeoutMillis = 0; - refreshConfigurationLocked(changes); - } else if (mNextTimeout != LLONG_MAX) { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); - } - } // release lock - - size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); - - { // acquire lock - AutoMutex _l(mLock); - mReaderIsAliveCondition.broadcast(); - - if (count) { - processEventsLocked(mEventBuffer, count); - } - - if (mNextTimeout != LLONG_MAX) { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - if (now >= mNextTimeout) { -#if DEBUG_RAW_EVENTS - ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f); -#endif - mNextTimeout = LLONG_MAX; - timeoutExpiredLocked(now); - } - } - - if (oldGeneration != mGeneration) { - inputDevicesChanged = true; - getInputDevicesLocked(inputDevices); - } - } // release lock - - // Send out a message that the describes the changed input devices. - if (inputDevicesChanged) { - mPolicy->notifyInputDevicesChanged(inputDevices); - } - - // Flush queued events out to the listener. - // This must happen outside of the lock because the listener could potentially call - // back into the InputReader's methods, such as getScanCodeState, or become blocked - // on another thread similarly waiting to acquire the InputReader lock thereby - // resulting in a deadlock. This situation is actually quite plausible because the - // listener is actually the input dispatcher, which calls into the window manager, - // which occasionally calls into the input reader. - mQueuedListener->flush(); -} - -void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) { - for (const RawEvent* rawEvent = rawEvents; count;) { - int32_t type = rawEvent->type; - size_t batchSize = 1; - if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) { - int32_t deviceId = rawEvent->deviceId; - while (batchSize < count) { - if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT - || rawEvent[batchSize].deviceId != deviceId) { - break; - } - batchSize += 1; - } -#if DEBUG_RAW_EVENTS - ALOGD("BatchSize: %d Count: %d", batchSize, count); -#endif - processEventsForDeviceLocked(deviceId, rawEvent, batchSize); - } else { - switch (rawEvent->type) { - case EventHubInterface::DEVICE_ADDED: - addDeviceLocked(rawEvent->when, rawEvent->deviceId); - break; - case EventHubInterface::DEVICE_REMOVED: - removeDeviceLocked(rawEvent->when, rawEvent->deviceId); - break; - case EventHubInterface::FINISHED_DEVICE_SCAN: - handleConfigurationChangedLocked(rawEvent->when); - break; - default: - ALOG_ASSERT(false); // can't happen - break; - } - } - count -= batchSize; - rawEvent += batchSize; - } -} - -void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) { - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex >= 0) { - ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId); - return; - } - - InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId); - uint32_t classes = mEventHub->getDeviceClasses(deviceId); - - InputDevice* device = createDeviceLocked(deviceId, identifier, classes); - device->configure(when, &mConfig, 0); - device->reset(when); - - if (device->isIgnored()) { - ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, - identifier.name.string()); - } else { - ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, - identifier.name.string(), device->getSources()); - } - - mDevices.add(deviceId, device); - bumpGenerationLocked(); -} - -void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) { - InputDevice* device = NULL; - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex < 0) { - ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId); - return; - } - - device = mDevices.valueAt(deviceIndex); - mDevices.removeItemsAt(deviceIndex, 1); - bumpGenerationLocked(); - - if (device->isIgnored()) { - ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)", - device->getId(), device->getName().string()); - } else { - ALOGI("Device removed: id=%d, name='%s', sources=0x%08x", - device->getId(), device->getName().string(), device->getSources()); - } - - device->reset(when); - delete device; -} - -InputDevice* InputReader::createDeviceLocked(int32_t deviceId, - const InputDeviceIdentifier& identifier, uint32_t classes) { - InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(), - identifier, classes); - - // External devices. - if (classes & INPUT_DEVICE_CLASS_EXTERNAL) { - device->setExternal(true); - } - - // Switch-like devices. - if (classes & INPUT_DEVICE_CLASS_SWITCH) { - device->addMapper(new SwitchInputMapper(device)); - } - - // Vibrator-like devices. - if (classes & INPUT_DEVICE_CLASS_VIBRATOR) { - device->addMapper(new VibratorInputMapper(device)); - } - - // Keyboard-like devices. - uint32_t keyboardSource = 0; - int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC; - if (classes & INPUT_DEVICE_CLASS_KEYBOARD) { - keyboardSource |= AINPUT_SOURCE_KEYBOARD; - } - if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) { - keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC; - } - if (classes & INPUT_DEVICE_CLASS_DPAD) { - keyboardSource |= AINPUT_SOURCE_DPAD; - } - if (classes & INPUT_DEVICE_CLASS_GAMEPAD) { - keyboardSource |= AINPUT_SOURCE_GAMEPAD; - } - - if (keyboardSource != 0) { - device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType)); - } - - // Cursor-like devices. - if (classes & INPUT_DEVICE_CLASS_CURSOR) { - device->addMapper(new CursorInputMapper(device)); - } - - // Touchscreens and touchpad devices. - if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) { - device->addMapper(new MultiTouchInputMapper(device)); - } else if (classes & INPUT_DEVICE_CLASS_TOUCH) { - device->addMapper(new SingleTouchInputMapper(device)); - } - - // Joystick-like devices. - if (classes & INPUT_DEVICE_CLASS_JOYSTICK) { - device->addMapper(new JoystickInputMapper(device)); - } - - return device; -} - -void InputReader::processEventsForDeviceLocked(int32_t deviceId, - const RawEvent* rawEvents, size_t count) { - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex < 0) { - ALOGW("Discarding event for unknown deviceId %d.", deviceId); - return; - } - - InputDevice* device = mDevices.valueAt(deviceIndex); - if (device->isIgnored()) { - //ALOGD("Discarding event for ignored deviceId %d.", deviceId); - return; - } - - device->process(rawEvents, count); -} - -void InputReader::timeoutExpiredLocked(nsecs_t when) { - for (size_t i = 0; i < mDevices.size(); i++) { - InputDevice* device = mDevices.valueAt(i); - if (!device->isIgnored()) { - device->timeoutExpired(when); - } - } -} - -void InputReader::handleConfigurationChangedLocked(nsecs_t when) { - // Reset global meta state because it depends on the list of all configured devices. - updateGlobalMetaStateLocked(); - - // Enqueue configuration changed. - NotifyConfigurationChangedArgs args(when); - mQueuedListener->notifyConfigurationChanged(&args); -} - -void InputReader::refreshConfigurationLocked(uint32_t changes) { - mPolicy->getReaderConfiguration(&mConfig); - mEventHub->setExcludedDevices(mConfig.excludedDeviceNames); - - if (changes) { - ALOGI("Reconfiguring input devices. changes=0x%08x", changes); - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - - if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) { - mEventHub->requestReopenDevices(); - } else { - for (size_t i = 0; i < mDevices.size(); i++) { - InputDevice* device = mDevices.valueAt(i); - device->configure(now, &mConfig, changes); - } - } - } -} - -void InputReader::updateGlobalMetaStateLocked() { - mGlobalMetaState = 0; - - for (size_t i = 0; i < mDevices.size(); i++) { - InputDevice* device = mDevices.valueAt(i); - mGlobalMetaState |= device->getMetaState(); - } -} - -int32_t InputReader::getGlobalMetaStateLocked() { - return mGlobalMetaState; -} - -void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) { - mDisableVirtualKeysTimeout = time; -} - -bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now, - InputDevice* device, int32_t keyCode, int32_t scanCode) { - if (now < mDisableVirtualKeysTimeout) { - ALOGI("Dropping virtual key from device %s because virtual keys are " - "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d", - device->getName().string(), - (mDisableVirtualKeysTimeout - now) * 0.000001, - keyCode, scanCode); - return true; - } else { - return false; - } -} - -void InputReader::fadePointerLocked() { - for (size_t i = 0; i < mDevices.size(); i++) { - InputDevice* device = mDevices.valueAt(i); - device->fadePointer(); - } -} - -void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) { - if (when < mNextTimeout) { - mNextTimeout = when; - mEventHub->wake(); - } -} - -int32_t InputReader::bumpGenerationLocked() { - return ++mGeneration; -} - -void InputReader::getInputDevices(Vector<InputDeviceInfo>& outInputDevices) { - AutoMutex _l(mLock); - getInputDevicesLocked(outInputDevices); -} - -void InputReader::getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices) { - outInputDevices.clear(); - - size_t numDevices = mDevices.size(); - for (size_t i = 0; i < numDevices; i++) { - InputDevice* device = mDevices.valueAt(i); - if (!device->isIgnored()) { - outInputDevices.push(); - device->getDeviceInfo(&outInputDevices.editTop()); - } - } -} - -int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask, - int32_t keyCode) { - AutoMutex _l(mLock); - - return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState); -} - -int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask, - int32_t scanCode) { - AutoMutex _l(mLock); - - return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState); -} - -int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) { - AutoMutex _l(mLock); - - return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState); -} - -int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code, - GetStateFunc getStateFunc) { - 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)) { - // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that - // value. Otherwise, return AKEY_STATE_UP as long as one device reports it. - int32_t currentResult = (device->*getStateFunc)(sourceMask, code); - if (currentResult >= AKEY_STATE_DOWN) { - return currentResult; - } else if (currentResult == AKEY_STATE_UP) { - result = currentResult; - } - } - } - } - return result; -} - -bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask, - size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) { - AutoMutex _l(mLock); - - memset(outFlags, 0, numCodes); - return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags); -} - -bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, - size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) { - 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; -} - -void InputReader::requestRefreshConfiguration(uint32_t changes) { - AutoMutex _l(mLock); - - if (changes) { - bool needWake = !mConfigurationChangesToRefresh; - mConfigurationChangesToRefresh |= changes; - - if (needWake) { - mEventHub->wake(); - } - } -} - -void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, - ssize_t repeat, int32_t token) { - AutoMutex _l(mLock); - - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex >= 0) { - InputDevice* device = mDevices.valueAt(deviceIndex); - device->vibrate(pattern, patternSize, repeat, token); - } -} - -void InputReader::cancelVibrate(int32_t deviceId, int32_t token) { - AutoMutex _l(mLock); - - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex >= 0) { - InputDevice* device = mDevices.valueAt(deviceIndex); - device->cancelVibrate(token); - } -} - -void InputReader::dump(String8& dump) { - AutoMutex _l(mLock); - - mEventHub->dump(dump); - dump.append("\n"); - - dump.append("Input Reader State:\n"); - - for (size_t i = 0; i < mDevices.size(); i++) { - mDevices.valueAt(i)->dump(dump); - } - - dump.append(INDENT "Configuration:\n"); - dump.append(INDENT2 "ExcludedDeviceNames: ["); - for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) { - if (i != 0) { - dump.append(", "); - } - dump.append(mConfig.excludedDeviceNames.itemAt(i).string()); - } - dump.append("]\n"); - dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n", - mConfig.virtualKeyQuietTime * 0.000001f); - - dump.appendFormat(INDENT2 "PointerVelocityControlParameters: " - "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n", - mConfig.pointerVelocityControlParameters.scale, - mConfig.pointerVelocityControlParameters.lowThreshold, - mConfig.pointerVelocityControlParameters.highThreshold, - mConfig.pointerVelocityControlParameters.acceleration); - - dump.appendFormat(INDENT2 "WheelVelocityControlParameters: " - "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n", - mConfig.wheelVelocityControlParameters.scale, - mConfig.wheelVelocityControlParameters.lowThreshold, - mConfig.wheelVelocityControlParameters.highThreshold, - mConfig.wheelVelocityControlParameters.acceleration); - - dump.appendFormat(INDENT2 "PointerGesture:\n"); - dump.appendFormat(INDENT3 "Enabled: %s\n", - toString(mConfig.pointerGesturesEnabled)); - dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n", - mConfig.pointerGestureQuietInterval * 0.000001f); - dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n", - mConfig.pointerGestureDragMinSwitchSpeed); - dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n", - mConfig.pointerGestureTapInterval * 0.000001f); - dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n", - mConfig.pointerGestureTapDragInterval * 0.000001f); - dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n", - mConfig.pointerGestureTapSlop); - dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n", - mConfig.pointerGestureMultitouchSettleInterval * 0.000001f); - dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n", - mConfig.pointerGestureMultitouchMinDistance); - dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n", - mConfig.pointerGestureSwipeTransitionAngleCosine); - dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n", - mConfig.pointerGestureSwipeMaxWidthRatio); - dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n", - mConfig.pointerGestureMovementSpeedRatio); - dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n", - mConfig.pointerGestureZoomSpeedRatio); -} - -void InputReader::monitor() { - // Acquire and release the lock to ensure that the reader has not deadlocked. - mLock.lock(); - mEventHub->wake(); - mReaderIsAliveCondition.wait(mLock); - mLock.unlock(); - - // Check the EventHub - mEventHub->monitor(); -} - - -// --- InputReader::ContextImpl --- - -InputReader::ContextImpl::ContextImpl(InputReader* reader) : - mReader(reader) { -} - -void InputReader::ContextImpl::updateGlobalMetaState() { - // lock is already held by the input loop - mReader->updateGlobalMetaStateLocked(); -} - -int32_t InputReader::ContextImpl::getGlobalMetaState() { - // lock is already held by the input loop - return mReader->getGlobalMetaStateLocked(); -} - -void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) { - // lock is already held by the input loop - mReader->disableVirtualKeysUntilLocked(time); -} - -bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now, - InputDevice* device, int32_t keyCode, int32_t scanCode) { - // lock is already held by the input loop - return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode); -} - -void InputReader::ContextImpl::fadePointer() { - // lock is already held by the input loop - mReader->fadePointerLocked(); -} - -void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) { - // lock is already held by the input loop - mReader->requestTimeoutAtTimeLocked(when); -} - -int32_t InputReader::ContextImpl::bumpGeneration() { - // lock is already held by the input loop - return mReader->bumpGenerationLocked(); -} - -InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() { - return mReader->mPolicy.get(); -} - -InputListenerInterface* InputReader::ContextImpl::getListener() { - return mReader->mQueuedListener.get(); -} - -EventHubInterface* InputReader::ContextImpl::getEventHub() { - return mReader->mEventHub.get(); -} - - -// --- 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, int32_t generation, - const InputDeviceIdentifier& identifier, uint32_t classes) : - mContext(context), mId(id), mGeneration(generation), - mIdentifier(identifier), mClasses(classes), - mSources(0), mIsExternal(false), mDropUntilNextSync(false) { -} - -InputDevice::~InputDevice() { - size_t numMappers = mMappers.size(); - for (size_t i = 0; i < numMappers; i++) { - delete mMappers[i]; - } - mMappers.clear(); -} - -void InputDevice::dump(String8& dump) { - InputDeviceInfo deviceInfo; - getDeviceInfo(& deviceInfo); - - dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(), - deviceInfo.getDisplayName().string()); - dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration); - dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal)); - dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources()); - dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType()); - - const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); - if (!ranges.isEmpty()) { - dump.append(INDENT2 "Motion Ranges:\n"); - for (size_t i = 0; i < ranges.size(); i++) { - const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); - const char* label = getAxisLabel(range.axis); - char name[32]; - if (label) { - strncpy(name, label, sizeof(name)); - name[sizeof(name) - 1] = '\0'; - } else { - snprintf(name, sizeof(name), "%d", range.axis); - } - dump.appendFormat(INDENT3 "%s: source=0x%08x, " - "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n", - name, range.source, range.min, range.max, range.flat, range.fuzz, - range.resolution); - } - } - - 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(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) { - mSources = 0; - - if (!isIgnored()) { - if (!changes) { // first time only - mContext->getEventHub()->getConfiguration(mId, &mConfiguration); - } - - if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) { - if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) { - sp<KeyCharacterMap> keyboardLayout = - mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier.descriptor); - if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) { - bumpGeneration(); - } - } - } - - if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) { - if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) { - String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier); - if (mAlias != alias) { - mAlias = alias; - bumpGeneration(); - } - } - } - - size_t numMappers = mMappers.size(); - for (size_t i = 0; i < numMappers; i++) { - InputMapper* mapper = mMappers[i]; - mapper->configure(when, config, changes); - mSources |= mapper->getSources(); - } - } -} - -void InputDevice::reset(nsecs_t when) { - size_t numMappers = mMappers.size(); - for (size_t i = 0; i < numMappers; i++) { - InputMapper* mapper = mMappers[i]; - mapper->reset(when); - } - - mContext->updateGlobalMetaState(); - - notifyReset(when); -} - -void InputDevice::process(const RawEvent* rawEvents, size_t count) { - // Process all of the events in order for each mapper. - // We cannot simply ask each mapper to process them in bulk because mappers may - // have side-effects that must be interleaved. For example, joystick movement events and - // gamepad button presses are handled by different mappers but they should be dispatched - // in the order received. - size_t numMappers = mMappers.size(); - for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { -#if DEBUG_RAW_EVENTS - ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld", - rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, - rawEvent->when); -#endif - - if (mDropUntilNextSync) { - if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - mDropUntilNextSync = false; -#if DEBUG_RAW_EVENTS - ALOGD("Recovered from input event buffer overrun."); -#endif - } else { -#if DEBUG_RAW_EVENTS - ALOGD("Dropped input event while waiting for next input sync."); -#endif - } - } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) { - ALOGI("Detected input event buffer overrun for device %s.", getName().string()); - mDropUntilNextSync = true; - reset(rawEvent->when); - } else { - for (size_t i = 0; i < numMappers; i++) { - InputMapper* mapper = mMappers[i]; - mapper->process(rawEvent); - } - } - } -} - -void InputDevice::timeoutExpired(nsecs_t when) { - size_t numMappers = mMappers.size(); - for (size_t i = 0; i < numMappers; i++) { - InputMapper* mapper = mMappers[i]; - mapper->timeoutExpired(when); - } -} - -void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) { - outDeviceInfo->initialize(mId, mGeneration, mIdentifier, mAlias, mIsExternal); - - 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)) { - // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that - // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it. - int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code); - if (currentResult >= AKEY_STATE_DOWN) { - return currentResult; - } else if (currentResult == AKEY_STATE_UP) { - result = currentResult; - } - } - } - 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; -} - -void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, - int32_t token) { - size_t numMappers = mMappers.size(); - for (size_t i = 0; i < numMappers; i++) { - InputMapper* mapper = mMappers[i]; - mapper->vibrate(pattern, patternSize, repeat, token); - } -} - -void InputDevice::cancelVibrate(int32_t token) { - size_t numMappers = mMappers.size(); - for (size_t i = 0; i < numMappers; i++) { - InputMapper* mapper = mMappers[i]; - mapper->cancelVibrate(token); - } -} - -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; -} - -void InputDevice::fadePointer() { - size_t numMappers = mMappers.size(); - for (size_t i = 0; i < numMappers; i++) { - InputMapper* mapper = mMappers[i]; - mapper->fadePointer(); - } -} - -void InputDevice::bumpGeneration() { - mGeneration = mContext->bumpGeneration(); -} - -void InputDevice::notifyReset(nsecs_t when) { - NotifyDeviceResetArgs args(when, mId); - mContext->getListener()->notifyDeviceReset(&args); -} - - -// --- CursorButtonAccumulator --- - -CursorButtonAccumulator::CursorButtonAccumulator() { - clearButtons(); -} - -void CursorButtonAccumulator::reset(InputDevice* device) { - mBtnLeft = device->isKeyPressed(BTN_LEFT); - mBtnRight = device->isKeyPressed(BTN_RIGHT); - mBtnMiddle = device->isKeyPressed(BTN_MIDDLE); - mBtnBack = device->isKeyPressed(BTN_BACK); - mBtnSide = device->isKeyPressed(BTN_SIDE); - mBtnForward = device->isKeyPressed(BTN_FORWARD); - mBtnExtra = device->isKeyPressed(BTN_EXTRA); - mBtnTask = device->isKeyPressed(BTN_TASK); -} - -void CursorButtonAccumulator::clearButtons() { - mBtnLeft = 0; - mBtnRight = 0; - mBtnMiddle = 0; - mBtnBack = 0; - mBtnSide = 0; - mBtnForward = 0; - mBtnExtra = 0; - mBtnTask = 0; -} - -void CursorButtonAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_KEY) { - switch (rawEvent->code) { - case BTN_LEFT: - mBtnLeft = rawEvent->value; - break; - case BTN_RIGHT: - mBtnRight = rawEvent->value; - break; - case BTN_MIDDLE: - mBtnMiddle = rawEvent->value; - break; - case BTN_BACK: - mBtnBack = rawEvent->value; - break; - case BTN_SIDE: - mBtnSide = rawEvent->value; - break; - case BTN_FORWARD: - mBtnForward = rawEvent->value; - break; - case BTN_EXTRA: - mBtnExtra = rawEvent->value; - break; - case BTN_TASK: - mBtnTask = rawEvent->value; - break; - } - } -} - -uint32_t CursorButtonAccumulator::getButtonState() const { - uint32_t result = 0; - if (mBtnLeft) { - result |= AMOTION_EVENT_BUTTON_PRIMARY; - } - if (mBtnRight) { - result |= AMOTION_EVENT_BUTTON_SECONDARY; - } - if (mBtnMiddle) { - result |= AMOTION_EVENT_BUTTON_TERTIARY; - } - if (mBtnBack || mBtnSide) { - result |= AMOTION_EVENT_BUTTON_BACK; - } - if (mBtnForward || mBtnExtra) { - result |= AMOTION_EVENT_BUTTON_FORWARD; - } - return result; -} - - -// --- CursorMotionAccumulator --- - -CursorMotionAccumulator::CursorMotionAccumulator() { - clearRelativeAxes(); -} - -void CursorMotionAccumulator::reset(InputDevice* device) { - clearRelativeAxes(); -} - -void CursorMotionAccumulator::clearRelativeAxes() { - mRelX = 0; - mRelY = 0; -} - -void CursorMotionAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_REL) { - switch (rawEvent->code) { - case REL_X: - mRelX = rawEvent->value; - break; - case REL_Y: - mRelY = rawEvent->value; - break; - } - } -} - -void CursorMotionAccumulator::finishSync() { - clearRelativeAxes(); -} - - -// --- CursorScrollAccumulator --- - -CursorScrollAccumulator::CursorScrollAccumulator() : - mHaveRelWheel(false), mHaveRelHWheel(false) { - clearRelativeAxes(); -} - -void CursorScrollAccumulator::configure(InputDevice* device) { - mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL); - mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL); -} - -void CursorScrollAccumulator::reset(InputDevice* device) { - clearRelativeAxes(); -} - -void CursorScrollAccumulator::clearRelativeAxes() { - mRelWheel = 0; - mRelHWheel = 0; -} - -void CursorScrollAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_REL) { - switch (rawEvent->code) { - case REL_WHEEL: - mRelWheel = rawEvent->value; - break; - case REL_HWHEEL: - mRelHWheel = rawEvent->value; - break; - } - } -} - -void CursorScrollAccumulator::finishSync() { - clearRelativeAxes(); -} - - -// --- TouchButtonAccumulator --- - -TouchButtonAccumulator::TouchButtonAccumulator() : - mHaveBtnTouch(false), mHaveStylus(false) { - clearButtons(); -} - -void TouchButtonAccumulator::configure(InputDevice* device) { - mHaveBtnTouch = device->hasKey(BTN_TOUCH); - mHaveStylus = device->hasKey(BTN_TOOL_PEN) - || device->hasKey(BTN_TOOL_RUBBER) - || device->hasKey(BTN_TOOL_BRUSH) - || device->hasKey(BTN_TOOL_PENCIL) - || device->hasKey(BTN_TOOL_AIRBRUSH); -} - -void TouchButtonAccumulator::reset(InputDevice* device) { - mBtnTouch = device->isKeyPressed(BTN_TOUCH); - mBtnStylus = device->isKeyPressed(BTN_STYLUS); - mBtnStylus2 = device->isKeyPressed(BTN_STYLUS); - mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER); - mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN); - mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER); - mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH); - mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL); - mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH); - mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE); - mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS); - mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP); - mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP); - mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP); -} - -void TouchButtonAccumulator::clearButtons() { - mBtnTouch = 0; - mBtnStylus = 0; - mBtnStylus2 = 0; - mBtnToolFinger = 0; - mBtnToolPen = 0; - mBtnToolRubber = 0; - mBtnToolBrush = 0; - mBtnToolPencil = 0; - mBtnToolAirbrush = 0; - mBtnToolMouse = 0; - mBtnToolLens = 0; - mBtnToolDoubleTap = 0; - mBtnToolTripleTap = 0; - mBtnToolQuadTap = 0; -} - -void TouchButtonAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_KEY) { - switch (rawEvent->code) { - case BTN_TOUCH: - mBtnTouch = rawEvent->value; - break; - case BTN_STYLUS: - mBtnStylus = rawEvent->value; - break; - case BTN_STYLUS2: - mBtnStylus2 = rawEvent->value; - break; - case BTN_TOOL_FINGER: - mBtnToolFinger = rawEvent->value; - break; - case BTN_TOOL_PEN: - mBtnToolPen = rawEvent->value; - break; - case BTN_TOOL_RUBBER: - mBtnToolRubber = rawEvent->value; - break; - case BTN_TOOL_BRUSH: - mBtnToolBrush = rawEvent->value; - break; - case BTN_TOOL_PENCIL: - mBtnToolPencil = rawEvent->value; - break; - case BTN_TOOL_AIRBRUSH: - mBtnToolAirbrush = rawEvent->value; - break; - case BTN_TOOL_MOUSE: - mBtnToolMouse = rawEvent->value; - break; - case BTN_TOOL_LENS: - mBtnToolLens = rawEvent->value; - break; - case BTN_TOOL_DOUBLETAP: - mBtnToolDoubleTap = rawEvent->value; - break; - case BTN_TOOL_TRIPLETAP: - mBtnToolTripleTap = rawEvent->value; - break; - case BTN_TOOL_QUADTAP: - mBtnToolQuadTap = rawEvent->value; - break; - } - } -} - -uint32_t TouchButtonAccumulator::getButtonState() const { - uint32_t result = 0; - if (mBtnStylus) { - result |= AMOTION_EVENT_BUTTON_SECONDARY; - } - if (mBtnStylus2) { - result |= AMOTION_EVENT_BUTTON_TERTIARY; - } - return result; -} - -int32_t TouchButtonAccumulator::getToolType() const { - if (mBtnToolMouse || mBtnToolLens) { - return AMOTION_EVENT_TOOL_TYPE_MOUSE; - } - if (mBtnToolRubber) { - return AMOTION_EVENT_TOOL_TYPE_ERASER; - } - if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) { - return AMOTION_EVENT_TOOL_TYPE_STYLUS; - } - if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) { - return AMOTION_EVENT_TOOL_TYPE_FINGER; - } - return AMOTION_EVENT_TOOL_TYPE_UNKNOWN; -} - -bool TouchButtonAccumulator::isToolActive() const { - return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber - || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush - || mBtnToolMouse || mBtnToolLens - || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap; -} - -bool TouchButtonAccumulator::isHovering() const { - return mHaveBtnTouch && !mBtnTouch; -} - -bool TouchButtonAccumulator::hasStylus() const { - return mHaveStylus; -} - - -// --- RawPointerAxes --- - -RawPointerAxes::RawPointerAxes() { - clear(); -} - -void RawPointerAxes::clear() { - x.clear(); - y.clear(); - pressure.clear(); - touchMajor.clear(); - touchMinor.clear(); - toolMajor.clear(); - toolMinor.clear(); - orientation.clear(); - distance.clear(); - tiltX.clear(); - tiltY.clear(); - trackingId.clear(); - slot.clear(); -} - - -// --- RawPointerData --- - -RawPointerData::RawPointerData() { - clear(); -} - -void RawPointerData::clear() { - pointerCount = 0; - clearIdBits(); -} - -void RawPointerData::copyFrom(const RawPointerData& other) { - pointerCount = other.pointerCount; - hoveringIdBits = other.hoveringIdBits; - touchingIdBits = other.touchingIdBits; - - for (uint32_t i = 0; i < pointerCount; i++) { - pointers[i] = other.pointers[i]; - - int id = pointers[i].id; - idToIndex[id] = other.idToIndex[id]; - } -} - -void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const { - float x = 0, y = 0; - uint32_t count = touchingIdBits.count(); - if (count) { - for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - const Pointer& pointer = pointerForId(id); - x += pointer.x; - y += pointer.y; - } - x /= count; - y /= count; - } - *outX = x; - *outY = y; -} - - -// --- CookedPointerData --- - -CookedPointerData::CookedPointerData() { - clear(); -} - -void CookedPointerData::clear() { - pointerCount = 0; - hoveringIdBits.clear(); - touchingIdBits.clear(); -} - -void CookedPointerData::copyFrom(const CookedPointerData& other) { - pointerCount = other.pointerCount; - hoveringIdBits = other.hoveringIdBits; - touchingIdBits = other.touchingIdBits; - - for (uint32_t i = 0; i < pointerCount; i++) { - pointerProperties[i].copyFrom(other.pointerProperties[i]); - pointerCoords[i].copyFrom(other.pointerCoords[i]); - - int id = pointerProperties[i].id; - idToIndex[id] = other.idToIndex[id]; - } -} - - -// --- SingleTouchMotionAccumulator --- - -SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() { - clearAbsoluteAxes(); -} - -void SingleTouchMotionAccumulator::reset(InputDevice* device) { - mAbsX = device->getAbsoluteAxisValue(ABS_X); - mAbsY = device->getAbsoluteAxisValue(ABS_Y); - mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE); - mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH); - mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE); - mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X); - mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y); -} - -void SingleTouchMotionAccumulator::clearAbsoluteAxes() { - mAbsX = 0; - mAbsY = 0; - mAbsPressure = 0; - mAbsToolWidth = 0; - mAbsDistance = 0; - mAbsTiltX = 0; - mAbsTiltY = 0; -} - -void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_ABS) { - switch (rawEvent->code) { - case ABS_X: - mAbsX = rawEvent->value; - break; - case ABS_Y: - mAbsY = rawEvent->value; - break; - case ABS_PRESSURE: - mAbsPressure = rawEvent->value; - break; - case ABS_TOOL_WIDTH: - mAbsToolWidth = rawEvent->value; - break; - case ABS_DISTANCE: - mAbsDistance = rawEvent->value; - break; - case ABS_TILT_X: - mAbsTiltX = rawEvent->value; - break; - case ABS_TILT_Y: - mAbsTiltY = rawEvent->value; - break; - } - } -} - - -// --- MultiTouchMotionAccumulator --- - -MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() : - mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false), - mHaveStylus(false) { -} - -MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() { - delete[] mSlots; -} - -void MultiTouchMotionAccumulator::configure(InputDevice* device, - size_t slotCount, bool usingSlotsProtocol) { - mSlotCount = slotCount; - mUsingSlotsProtocol = usingSlotsProtocol; - mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE); - - delete[] mSlots; - mSlots = new Slot[slotCount]; -} - -void MultiTouchMotionAccumulator::reset(InputDevice* device) { - // Unfortunately there is no way to read the initial contents of the slots. - // So when we reset the accumulator, we must assume they are all zeroes. - if (mUsingSlotsProtocol) { - // Query the driver for the current slot index and use it as the initial slot - // before we start reading events from the device. It is possible that the - // current slot index will not be the same as it was when the first event was - // written into the evdev buffer, which means the input mapper could start - // out of sync with the initial state of the events in the evdev buffer. - // In the extremely unlikely case that this happens, the data from - // two slots will be confused until the next ABS_MT_SLOT event is received. - // This can cause the touch point to "jump", but at least there will be - // no stuck touches. - int32_t initialSlot; - status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(), - ABS_MT_SLOT, &initialSlot); - if (status) { - ALOGD("Could not retrieve current multitouch slot index. status=%d", status); - initialSlot = -1; - } - clearSlots(initialSlot); - } else { - clearSlots(-1); - } -} - -void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) { - if (mSlots) { - for (size_t i = 0; i < mSlotCount; i++) { - mSlots[i].clear(); - } - } - mCurrentSlot = initialSlot; -} - -void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_ABS) { -#if DEBUG_POINTERS - bool newSlot = false; -#endif - if (mUsingSlotsProtocol) { - if (rawEvent->code == ABS_MT_SLOT) { - mCurrentSlot = rawEvent->value; -#if DEBUG_POINTERS - newSlot = true; -#endif - } - } else if (mCurrentSlot < 0) { - mCurrentSlot = 0; - } - - if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) { -#if DEBUG_POINTERS - if (newSlot) { - ALOGW("MultiTouch device emitted invalid slot index %d but it " - "should be between 0 and %d; ignoring this slot.", - mCurrentSlot, mSlotCount - 1); - } -#endif - } else { - Slot* slot = &mSlots[mCurrentSlot]; - - switch (rawEvent->code) { - case ABS_MT_POSITION_X: - slot->mInUse = true; - slot->mAbsMTPositionX = rawEvent->value; - break; - case ABS_MT_POSITION_Y: - slot->mInUse = true; - slot->mAbsMTPositionY = rawEvent->value; - break; - case ABS_MT_TOUCH_MAJOR: - slot->mInUse = true; - slot->mAbsMTTouchMajor = rawEvent->value; - break; - case ABS_MT_TOUCH_MINOR: - slot->mInUse = true; - slot->mAbsMTTouchMinor = rawEvent->value; - slot->mHaveAbsMTTouchMinor = true; - break; - case ABS_MT_WIDTH_MAJOR: - slot->mInUse = true; - slot->mAbsMTWidthMajor = rawEvent->value; - break; - case ABS_MT_WIDTH_MINOR: - slot->mInUse = true; - slot->mAbsMTWidthMinor = rawEvent->value; - slot->mHaveAbsMTWidthMinor = true; - break; - case ABS_MT_ORIENTATION: - slot->mInUse = true; - slot->mAbsMTOrientation = rawEvent->value; - break; - case ABS_MT_TRACKING_ID: - if (mUsingSlotsProtocol && rawEvent->value < 0) { - // The slot is no longer in use but it retains its previous contents, - // which may be reused for subsequent touches. - slot->mInUse = false; - } else { - slot->mInUse = true; - slot->mAbsMTTrackingId = rawEvent->value; - } - break; - case ABS_MT_PRESSURE: - slot->mInUse = true; - slot->mAbsMTPressure = rawEvent->value; - break; - case ABS_MT_DISTANCE: - slot->mInUse = true; - slot->mAbsMTDistance = rawEvent->value; - break; - case ABS_MT_TOOL_TYPE: - slot->mInUse = true; - slot->mAbsMTToolType = rawEvent->value; - slot->mHaveAbsMTToolType = true; - break; - } - } - } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) { - // MultiTouch Sync: The driver has returned all data for *one* of the pointers. - mCurrentSlot += 1; - } -} - -void MultiTouchMotionAccumulator::finishSync() { - if (!mUsingSlotsProtocol) { - clearSlots(-1); - } -} - -bool MultiTouchMotionAccumulator::hasStylus() const { - return mHaveStylus; -} - - -// --- MultiTouchMotionAccumulator::Slot --- - -MultiTouchMotionAccumulator::Slot::Slot() { - clear(); -} - -void MultiTouchMotionAccumulator::Slot::clear() { - mInUse = false; - mHaveAbsMTTouchMinor = false; - mHaveAbsMTWidthMinor = false; - mHaveAbsMTToolType = false; - mAbsMTPositionX = 0; - mAbsMTPositionY = 0; - mAbsMTTouchMajor = 0; - mAbsMTTouchMinor = 0; - mAbsMTWidthMajor = 0; - mAbsMTWidthMinor = 0; - mAbsMTOrientation = 0; - mAbsMTTrackingId = -1; - mAbsMTPressure = 0; - mAbsMTDistance = 0; - mAbsMTToolType = 0; -} - -int32_t MultiTouchMotionAccumulator::Slot::getToolType() const { - if (mHaveAbsMTToolType) { - switch (mAbsMTToolType) { - case MT_TOOL_FINGER: - return AMOTION_EVENT_TOOL_TYPE_FINGER; - case MT_TOOL_PEN: - return AMOTION_EVENT_TOOL_TYPE_STYLUS; - } - } - return AMOTION_EVENT_TOOL_TYPE_UNKNOWN; -} - - -// --- 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(nsecs_t when, - const InputReaderConfiguration* config, uint32_t changes) { -} - -void InputMapper::reset(nsecs_t when) { -} - -void InputMapper::timeoutExpired(nsecs_t when) { -} - -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; -} - -void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, - int32_t token) { -} - -void InputMapper::cancelVibrate(int32_t token) { -} - -int32_t InputMapper::getMetaState() { - return 0; -} - -void InputMapper::fadePointer() { -} - -status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) { - return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo); -} - -void InputMapper::bumpGeneration() { - mDevice->bumpGeneration(); -} - -void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump, - const RawAbsoluteAxisInfo& axis, const char* name) { - if (axis.valid) { - dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n", - name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution); - } else { - dump.appendFormat(INDENT4 "%s: unknown range\n", name); - } -} - - -// --- SwitchInputMapper --- - -SwitchInputMapper::SwitchInputMapper(InputDevice* device) : - InputMapper(device), mUpdatedSwitchValues(0), mUpdatedSwitchMask(0) { -} - -SwitchInputMapper::~SwitchInputMapper() { -} - -uint32_t SwitchInputMapper::getSources() { - return AINPUT_SOURCE_SWITCH; -} - -void SwitchInputMapper::process(const RawEvent* rawEvent) { - switch (rawEvent->type) { - case EV_SW: - processSwitch(rawEvent->code, rawEvent->value); - break; - - case EV_SYN: - if (rawEvent->code == SYN_REPORT) { - sync(rawEvent->when); - } - } -} - -void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) { - if (switchCode >= 0 && switchCode < 32) { - if (switchValue) { - mUpdatedSwitchValues |= 1 << switchCode; - } - mUpdatedSwitchMask |= 1 << switchCode; - } -} - -void SwitchInputMapper::sync(nsecs_t when) { - if (mUpdatedSwitchMask) { - NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask); - getListener()->notifySwitch(&args); - - mUpdatedSwitchValues = 0; - mUpdatedSwitchMask = 0; - } -} - -int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) { - return getEventHub()->getSwitchState(getDeviceId(), switchCode); -} - - -// --- VibratorInputMapper --- - -VibratorInputMapper::VibratorInputMapper(InputDevice* device) : - InputMapper(device), mVibrating(false) { -} - -VibratorInputMapper::~VibratorInputMapper() { -} - -uint32_t VibratorInputMapper::getSources() { - return 0; -} - -void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { - InputMapper::populateDeviceInfo(info); - - info->setVibrator(true); -} - -void VibratorInputMapper::process(const RawEvent* rawEvent) { - // TODO: Handle FF_STATUS, although it does not seem to be widely supported. -} - -void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, - int32_t token) { -#if DEBUG_VIBRATOR - String8 patternStr; - for (size_t i = 0; i < patternSize; i++) { - if (i != 0) { - patternStr.append(", "); - } - patternStr.appendFormat("%lld", pattern[i]); - } - ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d", - getDeviceId(), patternStr.string(), repeat, token); -#endif - - mVibrating = true; - memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t)); - mPatternSize = patternSize; - mRepeat = repeat; - mToken = token; - mIndex = -1; - - nextStep(); -} - -void VibratorInputMapper::cancelVibrate(int32_t token) { -#if DEBUG_VIBRATOR - ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token); -#endif - - if (mVibrating && mToken == token) { - stopVibrating(); - } -} - -void VibratorInputMapper::timeoutExpired(nsecs_t when) { - if (mVibrating) { - if (when >= mNextStepTime) { - nextStep(); - } else { - getContext()->requestTimeoutAtTime(mNextStepTime); - } - } -} - -void VibratorInputMapper::nextStep() { - mIndex += 1; - if (size_t(mIndex) >= mPatternSize) { - if (mRepeat < 0) { - // We are done. - stopVibrating(); - return; - } - mIndex = mRepeat; - } - - bool vibratorOn = mIndex & 1; - nsecs_t duration = mPattern[mIndex]; - if (vibratorOn) { -#if DEBUG_VIBRATOR - ALOGD("nextStep: sending vibrate deviceId=%d, duration=%lld", - getDeviceId(), duration); -#endif - getEventHub()->vibrate(getDeviceId(), duration); - } else { -#if DEBUG_VIBRATOR - ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId()); -#endif - getEventHub()->cancelVibrate(getDeviceId()); - } - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - mNextStepTime = now + duration; - getContext()->requestTimeoutAtTime(mNextStepTime); -#if DEBUG_VIBRATOR - ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f); -#endif -} - -void VibratorInputMapper::stopVibrating() { - mVibrating = false; -#if DEBUG_VIBRATOR - ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId()); -#endif - getEventHub()->cancelVibrate(getDeviceId()); -} - -void VibratorInputMapper::dump(String8& dump) { - dump.append(INDENT2 "Vibrator Input Mapper:\n"); - dump.appendFormat(INDENT3 "Vibrating: %s\n", toString(mVibrating)); -} - - -// --- KeyboardInputMapper --- - -KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, - uint32_t source, int32_t keyboardType) : - InputMapper(device), mSource(source), - mKeyboardType(keyboardType) { -} - -KeyboardInputMapper::~KeyboardInputMapper() { -} - -uint32_t KeyboardInputMapper::getSources() { - return mSource; -} - -void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { - InputMapper::populateDeviceInfo(info); - - info->setKeyboardType(mKeyboardType); - info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId())); -} - -void KeyboardInputMapper::dump(String8& dump) { - dump.append(INDENT2 "Keyboard Input Mapper:\n"); - dumpParameters(dump); - dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType); - dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation); - dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size()); - dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState); - dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime); -} - - -void KeyboardInputMapper::configure(nsecs_t when, - const InputReaderConfiguration* config, uint32_t changes) { - InputMapper::configure(when, config, changes); - - if (!changes) { // first time only - // Configure basic parameters. - configureParameters(); - } - - if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { - if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { - DisplayViewport v; - if (config->getDisplayInfo(false /*external*/, &v)) { - mOrientation = v.orientation; - } else { - mOrientation = DISPLAY_ORIENTATION_0; - } - } else { - mOrientation = DISPLAY_ORIENTATION_0; - } - } -} - -void KeyboardInputMapper::configureParameters() { - mParameters.orientationAware = false; - getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"), - mParameters.orientationAware); - - mParameters.hasAssociatedDisplay = false; - if (mParameters.orientationAware) { - mParameters.hasAssociatedDisplay = true; - } -} - -void KeyboardInputMapper::dumpParameters(String8& dump) { - dump.append(INDENT3 "Parameters:\n"); - dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n", - toString(mParameters.hasAssociatedDisplay)); - dump.appendFormat(INDENT4 "OrientationAware: %s\n", - toString(mParameters.orientationAware)); -} - -void KeyboardInputMapper::reset(nsecs_t when) { - mMetaState = AMETA_NONE; - mDownTime = 0; - mKeyDowns.clear(); - mCurrentHidUsage = 0; - - resetLedState(); - - InputMapper::reset(when); -} - -void KeyboardInputMapper::process(const RawEvent* rawEvent) { - switch (rawEvent->type) { - case EV_KEY: { - int32_t scanCode = rawEvent->code; - int32_t usageCode = mCurrentHidUsage; - mCurrentHidUsage = 0; - - if (isKeyboardOrGamepadKey(scanCode)) { - int32_t keyCode; - uint32_t flags; - if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) { - keyCode = AKEYCODE_UNKNOWN; - flags = 0; - } - processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags); - } - break; - } - case EV_MSC: { - if (rawEvent->code == MSC_SCAN) { - mCurrentHidUsage = rawEvent->value; - } - break; - } - case EV_SYN: { - if (rawEvent->code == SYN_REPORT) { - mCurrentHidUsage = 0; - } - } - } -} - -bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) { - return scanCode < BTN_MOUSE - || scanCode >= KEY_OK - || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE) - || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI); -} - -void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, - int32_t scanCode, uint32_t policyFlags) { - - if (down) { - // Rotate key codes according to orientation if needed. - if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { - keyCode = rotateKeyCode(keyCode, mOrientation); - } - - // Add key down. - ssize_t keyDownIndex = findKeyDown(scanCode); - if (keyDownIndex >= 0) { - // key repeat, be sure to use same keycode as before in case of rotation - keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode; - } else { - // key down - if ((policyFlags & POLICY_FLAG_VIRTUAL) - && mContext->shouldDropVirtualKey(when, - getDevice(), keyCode, scanCode)) { - return; - } - - mKeyDowns.push(); - KeyDown& keyDown = mKeyDowns.editTop(); - keyDown.keyCode = keyCode; - keyDown.scanCode = scanCode; - } - - mDownTime = when; - } else { - // Remove key down. - ssize_t keyDownIndex = findKeyDown(scanCode); - if (keyDownIndex >= 0) { - // key up, be sure to use same keycode as before in case of rotation - keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode; - mKeyDowns.removeAt(size_t(keyDownIndex)); - } else { - // key was not actually down - ALOGI("Dropping key up from device %s because the key was not down. " - "keyCode=%d, scanCode=%d", - getDeviceName().string(), keyCode, scanCode); - return; - } - } - - bool metaStateChanged = false; - int32_t oldMetaState = mMetaState; - int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState); - if (oldMetaState != newMetaState) { - mMetaState = newMetaState; - metaStateChanged = true; - updateLedState(false); - } - - nsecs_t downTime = mDownTime; - - // Key down on external an keyboard should wake the device. - // We don't do this for internal keyboards to prevent them from waking up in your pocket. - // For internal keyboards, the key layout file should specify the policy flags for - // each wake key individually. - // TODO: Use the input device configuration to control this behavior more finely. - if (down && getDevice()->isExternal() - && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) { - policyFlags |= POLICY_FLAG_WAKE_DROPPED; - } - - if (metaStateChanged) { - getContext()->updateGlobalMetaState(); - } - - if (down && !isMetaKey(keyCode)) { - getContext()->fadePointer(); - } - - NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags, - down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, - AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime); - getListener()->notifyKey(&args); -} - -ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) { - size_t n = mKeyDowns.size(); - for (size_t i = 0; i < n; i++) { - if (mKeyDowns[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() { - return mMetaState; -} - -void KeyboardInputMapper::resetLedState() { - initializeLedState(mCapsLockLedState, LED_CAPSL); - initializeLedState(mNumLockLedState, LED_NUML); - initializeLedState(mScrollLockLedState, LED_SCROLLL); - - updateLedState(true); -} - -void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) { - ledState.avail = getEventHub()->hasLed(getDeviceId(), led); - ledState.on = false; -} - -void KeyboardInputMapper::updateLedState(bool reset) { - updateLedStateForModifier(mCapsLockLedState, LED_CAPSL, - AMETA_CAPS_LOCK_ON, reset); - updateLedStateForModifier(mNumLockLedState, LED_NUML, - AMETA_NUM_LOCK_ON, reset); - updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL, - AMETA_SCROLL_LOCK_ON, reset); -} - -void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, - int32_t led, int32_t modifier, bool reset) { - if (ledState.avail) { - bool desiredState = (mMetaState & modifier) != 0; - if (reset || ledState.on != desiredState) { - getEventHub()->setLedState(getDeviceId(), led, desiredState); - ledState.on = desiredState; - } - } -} - - -// --- CursorInputMapper --- - -CursorInputMapper::CursorInputMapper(InputDevice* device) : - InputMapper(device) { -} - -CursorInputMapper::~CursorInputMapper() { -} - -uint32_t CursorInputMapper::getSources() { - return mSource; -} - -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(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f); - } - } else { - info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f); - } - info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); - - if (mCursorScrollAccumulator.haveRelativeVWheel()) { - info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f); - } - if (mCursorScrollAccumulator.haveRelativeHWheel()) { - info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f); - } -} - -void CursorInputMapper::dump(String8& dump) { - dump.append(INDENT2 "Cursor Input Mapper:\n"); - dumpParameters(dump); - dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale); - dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale); - dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision); - dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision); - dump.appendFormat(INDENT3 "HaveVWheel: %s\n", - toString(mCursorScrollAccumulator.haveRelativeVWheel())); - dump.appendFormat(INDENT3 "HaveHWheel: %s\n", - toString(mCursorScrollAccumulator.haveRelativeHWheel())); - dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale); - dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale); - dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation); - dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState); - dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState))); - dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime); -} - -void CursorInputMapper::configure(nsecs_t when, - const InputReaderConfiguration* config, uint32_t changes) { - InputMapper::configure(when, config, changes); - - if (!changes) { // first time only - mCursorScrollAccumulator.configure(getDevice()); - - // Configure basic parameters. - configureParameters(); - - // Configure device mode. - switch (mParameters.mode) { - case Parameters::MODE_POINTER: - mSource = AINPUT_SOURCE_MOUSE; - mXPrecision = 1.0f; - mYPrecision = 1.0f; - mXScale = 1.0f; - mYScale = 1.0f; - mPointerController = getPolicy()->obtainPointerController(getDeviceId()); - break; - case Parameters::MODE_NAVIGATION: - mSource = AINPUT_SOURCE_TRACKBALL; - mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; - mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; - mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; - mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; - break; - } - - mVWheelScale = 1.0f; - mHWheelScale = 1.0f; - } - - if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { - mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters); - mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters); - mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters); - } - - if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { - if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { - DisplayViewport v; - if (config->getDisplayInfo(false /*external*/, &v)) { - mOrientation = v.orientation; - } else { - mOrientation = DISPLAY_ORIENTATION_0; - } - } else { - mOrientation = DISPLAY_ORIENTATION_0; - } - bumpGeneration(); - } -} - -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") { - ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string()); - } - } - - mParameters.orientationAware = false; - getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"), - mParameters.orientationAware); - - mParameters.hasAssociatedDisplay = false; - if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) { - mParameters.hasAssociatedDisplay = true; - } -} - -void CursorInputMapper::dumpParameters(String8& dump) { - dump.append(INDENT3 "Parameters:\n"); - dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n", - toString(mParameters.hasAssociatedDisplay)); - - 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: - ALOG_ASSERT(false); - } - - dump.appendFormat(INDENT4 "OrientationAware: %s\n", - toString(mParameters.orientationAware)); -} - -void CursorInputMapper::reset(nsecs_t when) { - mButtonState = 0; - mDownTime = 0; - - mPointerVelocityControl.reset(); - mWheelXVelocityControl.reset(); - mWheelYVelocityControl.reset(); - - mCursorButtonAccumulator.reset(getDevice()); - mCursorMotionAccumulator.reset(getDevice()); - mCursorScrollAccumulator.reset(getDevice()); - - InputMapper::reset(when); -} - -void CursorInputMapper::process(const RawEvent* rawEvent) { - mCursorButtonAccumulator.process(rawEvent); - mCursorMotionAccumulator.process(rawEvent); - mCursorScrollAccumulator.process(rawEvent); - - if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - sync(rawEvent->when); - } -} - -void CursorInputMapper::sync(nsecs_t when) { - int32_t lastButtonState = mButtonState; - int32_t currentButtonState = mCursorButtonAccumulator.getButtonState(); - mButtonState = currentButtonState; - - bool wasDown = isPointerDown(lastButtonState); - bool down = isPointerDown(currentButtonState); - bool downChanged; - if (!wasDown && down) { - mDownTime = when; - downChanged = true; - } else if (wasDown && !down) { - downChanged = true; - } else { - downChanged = false; - } - nsecs_t downTime = mDownTime; - bool buttonsChanged = currentButtonState != lastButtonState; - bool buttonsPressed = currentButtonState & ~lastButtonState; - - float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale; - float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale; - bool moved = deltaX != 0 || deltaY != 0; - - // Rotate delta according to orientation if needed. - if (mParameters.orientationAware && mParameters.hasAssociatedDisplay - && (deltaX != 0.0f || deltaY != 0.0f)) { - rotateDelta(mOrientation, &deltaX, &deltaY); - } - - // Move the pointer. - PointerProperties pointerProperties; - pointerProperties.clear(); - pointerProperties.id = 0; - pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE; - - PointerCoords pointerCoords; - pointerCoords.clear(); - - float vscroll = mCursorScrollAccumulator.getRelativeVWheel(); - float hscroll = mCursorScrollAccumulator.getRelativeHWheel(); - bool scrolled = vscroll != 0 || hscroll != 0; - - mWheelYVelocityControl.move(when, NULL, &vscroll); - mWheelXVelocityControl.move(when, &hscroll, NULL); - - mPointerVelocityControl.move(when, &deltaX, &deltaY); - - int32_t displayId; - if (mPointerController != NULL) { - if (moved || scrolled || buttonsChanged) { - mPointerController->setPresentation( - PointerControllerInterface::PRESENTATION_POINTER); - - if (moved) { - mPointerController->move(deltaX, deltaY); - } - - if (buttonsChanged) { - mPointerController->setButtonState(currentButtonState); - } - - mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); - } - - float x, y; - mPointerController->getPosition(&x, &y); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); - displayId = ADISPLAY_ID_DEFAULT; - } else { - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); - displayId = ADISPLAY_ID_NONE; - } - - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); - - // Moving an external trackball or mouse should wake the device. - // We don't do this for internal cursor devices to prevent them from waking up - // the device in your pocket. - // TODO: Use the input device configuration to control this behavior more finely. - uint32_t policyFlags = 0; - if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) { - policyFlags |= POLICY_FLAG_WAKE_DROPPED; - } - - // Synthesize key down from buttons if needed. - synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource, - policyFlags, lastButtonState, currentButtonState); - - // Send motion event. - if (downChanged || moved || scrolled || buttonsChanged) { - int32_t metaState = mContext->getGlobalMetaState(); - int32_t motionEventAction; - if (downChanged) { - motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; - } else if (down || mPointerController == NULL) { - motionEventAction = AMOTION_EVENT_ACTION_MOVE; - } else { - motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE; - } - - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - motionEventAction, 0, metaState, currentButtonState, 0, - displayId, 1, &pointerProperties, &pointerCoords, - mXPrecision, mYPrecision, downTime); - getListener()->notifyMotion(&args); - - // Send hover move after UP to tell the application that the mouse is hovering now. - if (motionEventAction == AMOTION_EVENT_ACTION_UP - && mPointerController != NULL) { - NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_HOVER_MOVE, 0, - metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - displayId, 1, &pointerProperties, &pointerCoords, - mXPrecision, mYPrecision, downTime); - getListener()->notifyMotion(&hoverArgs); - } - - // Send scroll events. - if (scrolled) { - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - - NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState, - AMOTION_EVENT_EDGE_FLAG_NONE, - displayId, 1, &pointerProperties, &pointerCoords, - mXPrecision, mYPrecision, downTime); - getListener()->notifyMotion(&scrollArgs); - } - } - - // Synthesize key up from buttons if needed. - synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, - policyFlags, lastButtonState, currentButtonState); - - mCursorMotionAccumulator.finishSync(); - mCursorScrollAccumulator.finishSync(); -} - -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; - } -} - -void CursorInputMapper::fadePointer() { - if (mPointerController != NULL) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - } -} - - -// --- TouchInputMapper --- - -TouchInputMapper::TouchInputMapper(InputDevice* device) : - InputMapper(device), - mSource(0), mDeviceMode(DEVICE_MODE_DISABLED), - mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0), - mSurfaceOrientation(DISPLAY_ORIENTATION_0) { -} - -TouchInputMapper::~TouchInputMapper() { -} - -uint32_t TouchInputMapper::getSources() { - return mSource; -} - -void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { - InputMapper::populateDeviceInfo(info); - - if (mDeviceMode != DEVICE_MODE_DISABLED) { - info->addMotionRange(mOrientedRanges.x); - info->addMotionRange(mOrientedRanges.y); - info->addMotionRange(mOrientedRanges.pressure); - - if (mOrientedRanges.haveSize) { - info->addMotionRange(mOrientedRanges.size); - } - - if (mOrientedRanges.haveTouchSize) { - info->addMotionRange(mOrientedRanges.touchMajor); - info->addMotionRange(mOrientedRanges.touchMinor); - } - - if (mOrientedRanges.haveToolSize) { - info->addMotionRange(mOrientedRanges.toolMajor); - info->addMotionRange(mOrientedRanges.toolMinor); - } - - if (mOrientedRanges.haveOrientation) { - info->addMotionRange(mOrientedRanges.orientation); - } - - if (mOrientedRanges.haveDistance) { - info->addMotionRange(mOrientedRanges.distance); - } - - if (mOrientedRanges.haveTilt) { - info->addMotionRange(mOrientedRanges.tilt); - } - - if (mCursorScrollAccumulator.haveRelativeVWheel()) { - info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, - 0.0f); - } - if (mCursorScrollAccumulator.haveRelativeHWheel()) { - info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, - 0.0f); - } - if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) { - const InputDeviceInfo::MotionRange& x = mOrientedRanges.x; - const InputDeviceInfo::MotionRange& y = mOrientedRanges.y; - info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat, - x.fuzz, x.resolution); - info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat, - y.fuzz, y.resolution); - info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat, - x.fuzz, x.resolution); - info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat, - y.fuzz, y.resolution); - } - } -} - -void TouchInputMapper::dump(String8& dump) { - dump.append(INDENT2 "Touch Input Mapper:\n"); - dumpParameters(dump); - dumpVirtualKeys(dump); - dumpRawPointerAxes(dump); - dumpCalibration(dump); - dumpSurface(dump); - - dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n"); - dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate); - dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate); - dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale); - dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale); - dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision); - dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision); - dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale); - dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale); - dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale); - dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale); - dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale); - dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt)); - dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter); - dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale); - dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter); - dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale); - - dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState); - - dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n", - mLastRawPointerData.pointerCount); - for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) { - const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i]; - dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, " - "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, " - "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, " - "toolType=%d, isHovering=%s\n", i, - pointer.id, pointer.x, pointer.y, pointer.pressure, - pointer.touchMajor, pointer.touchMinor, - pointer.toolMajor, pointer.toolMinor, - pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance, - pointer.toolType, toString(pointer.isHovering)); - } - - dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n", - mLastCookedPointerData.pointerCount); - for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) { - const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i]; - const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i]; - dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, " - "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, " - "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, " - "toolType=%d, isHovering=%s\n", i, - pointerProperties.id, - pointerCoords.getX(), - pointerCoords.getY(), - pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), - pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), - pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), - pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), - pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), - pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), - pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT), - pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), - pointerProperties.toolType, - toString(mLastCookedPointerData.isHovering(i))); - } - - if (mDeviceMode == DEVICE_MODE_POINTER) { - dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n"); - dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n", - mPointerXMovementScale); - dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n", - mPointerYMovementScale); - dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n", - mPointerXZoomScale); - dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n", - mPointerYZoomScale); - dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n", - mPointerGestureMaxSwipeWidth); - } -} - -void TouchInputMapper::configure(nsecs_t when, - const InputReaderConfiguration* config, uint32_t changes) { - InputMapper::configure(when, config, changes); - - mConfig = *config; - - if (!changes) { // first time only - // Configure basic parameters. - configureParameters(); - - // Configure common accumulators. - mCursorScrollAccumulator.configure(getDevice()); - mTouchButtonAccumulator.configure(getDevice()); - - // Configure absolute axis information. - configureRawPointerAxes(); - - // Prepare input device calibration. - parseCalibration(); - resolveCalibration(); - } - - if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { - // Update pointer speed. - mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters); - mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters); - mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters); - } - - bool resetNeeded = false; - if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO - | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT - | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) { - // Configure device sources, surface dimensions, orientation and - // scaling factors. - configureSurface(when, &resetNeeded); - } - - if (changes && resetNeeded) { - // Send reset, unless this is the first time the device has been configured, - // in which case the reader will call reset itself after all mappers are ready. - getDevice()->notifyReset(when); - } -} - -void TouchInputMapper::configureParameters() { - // Use the pointer presentation mode for devices that do not support distinct - // multitouch. The spot-based presentation relies on being able to accurately - // locate two or more fingers on the touch pad. - mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT) - ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS; - - String8 gestureModeString; - if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"), - gestureModeString)) { - if (gestureModeString == "pointer") { - mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER; - } else if (gestureModeString == "spots") { - mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS; - } else if (gestureModeString != "default") { - ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string()); - } - } - - if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) { - // The device is a touch screen. - mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN; - } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) { - // The device is a pointing device like a track pad. - mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; - } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X) - || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) { - // The device is a cursor device with a touch pad attached. - // By default don't use the touch pad to move the pointer. - mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD; - } else { - // The device is a touch pad of unknown purpose. - mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; - } - - String8 deviceTypeString; - if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"), - deviceTypeString)) { - if (deviceTypeString == "touchScreen") { - mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN; - } else if (deviceTypeString == "touchPad") { - mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD; - } else if (deviceTypeString == "touchNavigation") { - mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION; - } else if (deviceTypeString == "pointer") { - mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; - } else if (deviceTypeString != "default") { - ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string()); - } - } - - mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN; - getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"), - mParameters.orientationAware); - - mParameters.hasAssociatedDisplay = false; - mParameters.associatedDisplayIsExternal = false; - if (mParameters.orientationAware - || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN - || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { - mParameters.hasAssociatedDisplay = true; - mParameters.associatedDisplayIsExternal = - mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN - && getDevice()->isExternal(); - } -} - -void TouchInputMapper::dumpParameters(String8& dump) { - dump.append(INDENT3 "Parameters:\n"); - - switch (mParameters.gestureMode) { - case Parameters::GESTURE_MODE_POINTER: - dump.append(INDENT4 "GestureMode: pointer\n"); - break; - case Parameters::GESTURE_MODE_SPOTS: - dump.append(INDENT4 "GestureMode: spots\n"); - break; - default: - assert(false); - } - - 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; - case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION: - dump.append(INDENT4 "DeviceType: touchNavigation\n"); - break; - case Parameters::DEVICE_TYPE_POINTER: - dump.append(INDENT4 "DeviceType: pointer\n"); - break; - default: - ALOG_ASSERT(false); - } - - dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n", - toString(mParameters.hasAssociatedDisplay), - toString(mParameters.associatedDisplayIsExternal)); - dump.appendFormat(INDENT4 "OrientationAware: %s\n", - toString(mParameters.orientationAware)); -} - -void TouchInputMapper::configureRawPointerAxes() { - mRawPointerAxes.clear(); -} - -void TouchInputMapper::dumpRawPointerAxes(String8& dump) { - dump.append(INDENT3 "Raw Touch Axes:\n"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId"); - dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot"); -} - -void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { - int32_t oldDeviceMode = mDeviceMode; - - // Determine device mode. - if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER - && mConfig.pointerGesturesEnabled) { - mSource = AINPUT_SOURCE_MOUSE; - mDeviceMode = DEVICE_MODE_POINTER; - if (hasStylus()) { - mSource |= AINPUT_SOURCE_STYLUS; - } - } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN - && mParameters.hasAssociatedDisplay) { - mSource = AINPUT_SOURCE_TOUCHSCREEN; - mDeviceMode = DEVICE_MODE_DIRECT; - if (hasStylus()) { - mSource |= AINPUT_SOURCE_STYLUS; - } - } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) { - mSource = AINPUT_SOURCE_TOUCH_NAVIGATION; - mDeviceMode = DEVICE_MODE_NAVIGATION; - } else { - mSource = AINPUT_SOURCE_TOUCHPAD; - mDeviceMode = DEVICE_MODE_UNSCALED; - } - - // Ensure we have valid X and Y axes. - if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) { - ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis! " - "The device will be inoperable.", getDeviceName().string()); - mDeviceMode = DEVICE_MODE_DISABLED; - return; - } - - // Raw width and height in the natural orientation. - int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; - int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; - - // Get associated display dimensions. - bool viewportChanged = false; - DisplayViewport newViewport; - if (mParameters.hasAssociatedDisplay) { - if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) { - ALOGI(INDENT "Touch device '%s' could not query the properties of its associated " - "display. The device will be inoperable until the display size " - "becomes available.", - getDeviceName().string()); - mDeviceMode = DEVICE_MODE_DISABLED; - return; - } - } else { - newViewport.setNonDisplayViewport(rawWidth, rawHeight); - } - if (mViewport != newViewport) { - mViewport = newViewport; - viewportChanged = true; - - if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { - // Convert rotated viewport to natural surface coordinates. - int32_t naturalLogicalWidth, naturalLogicalHeight; - int32_t naturalPhysicalWidth, naturalPhysicalHeight; - int32_t naturalPhysicalLeft, naturalPhysicalTop; - int32_t naturalDeviceWidth, naturalDeviceHeight; - switch (mViewport.orientation) { - case DISPLAY_ORIENTATION_90: - naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; - naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; - naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; - naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; - naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom; - naturalPhysicalTop = mViewport.physicalLeft; - naturalDeviceWidth = mViewport.deviceHeight; - naturalDeviceHeight = mViewport.deviceWidth; - break; - case DISPLAY_ORIENTATION_180: - naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; - naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; - naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; - naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; - naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight; - naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom; - naturalDeviceWidth = mViewport.deviceWidth; - naturalDeviceHeight = mViewport.deviceHeight; - break; - case DISPLAY_ORIENTATION_270: - naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; - naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; - naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; - naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; - naturalPhysicalLeft = mViewport.physicalTop; - naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight; - naturalDeviceWidth = mViewport.deviceHeight; - naturalDeviceHeight = mViewport.deviceWidth; - break; - case DISPLAY_ORIENTATION_0: - default: - naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; - naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; - naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; - naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; - naturalPhysicalLeft = mViewport.physicalLeft; - naturalPhysicalTop = mViewport.physicalTop; - naturalDeviceWidth = mViewport.deviceWidth; - naturalDeviceHeight = mViewport.deviceHeight; - break; - } - - mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; - mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; - mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; - mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; - - mSurfaceOrientation = mParameters.orientationAware ? - mViewport.orientation : DISPLAY_ORIENTATION_0; - } else { - mSurfaceWidth = rawWidth; - mSurfaceHeight = rawHeight; - mSurfaceLeft = 0; - mSurfaceTop = 0; - mSurfaceOrientation = DISPLAY_ORIENTATION_0; - } - } - - // If moving between pointer modes, need to reset some state. - bool deviceModeChanged = mDeviceMode != oldDeviceMode; - if (deviceModeChanged) { - mOrientedRanges.clear(); - } - - // Create pointer controller if needed. - if (mDeviceMode == DEVICE_MODE_POINTER || - (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) { - if (mPointerController == NULL) { - mPointerController = getPolicy()->obtainPointerController(getDeviceId()); - } - } else { - mPointerController.clear(); - } - - if (viewportChanged || deviceModeChanged) { - ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, " - "display id %d", - getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight, - mSurfaceOrientation, mDeviceMode, mViewport.displayId); - - // Configure X and Y factors. - mXScale = float(mSurfaceWidth) / rawWidth; - mYScale = float(mSurfaceHeight) / rawHeight; - mXTranslate = -mSurfaceLeft; - mYTranslate = -mSurfaceTop; - mXPrecision = 1.0f / mXScale; - mYPrecision = 1.0f / mYScale; - - mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X; - mOrientedRanges.x.source = mSource; - mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y; - mOrientedRanges.y.source = mSource; - - configureVirtualKeys(); - - // 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. - mGeometricScale = avg(mXScale, mYScale); - - // Size of diagonal axis. - float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight); - - // Size factors. - if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) { - if (mRawPointerAxes.touchMajor.valid - && mRawPointerAxes.touchMajor.maxValue != 0) { - mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue; - } else if (mRawPointerAxes.toolMajor.valid - && mRawPointerAxes.toolMajor.maxValue != 0) { - mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue; - } else { - mSizeScale = 0.0f; - } - - mOrientedRanges.haveTouchSize = true; - mOrientedRanges.haveToolSize = true; - mOrientedRanges.haveSize = true; - - mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR; - mOrientedRanges.touchMajor.source = mSource; - mOrientedRanges.touchMajor.min = 0; - mOrientedRanges.touchMajor.max = diagonalSize; - mOrientedRanges.touchMajor.flat = 0; - mOrientedRanges.touchMajor.fuzz = 0; - mOrientedRanges.touchMajor.resolution = 0; - - mOrientedRanges.touchMinor = mOrientedRanges.touchMajor; - mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR; - - mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR; - mOrientedRanges.toolMajor.source = mSource; - mOrientedRanges.toolMajor.min = 0; - mOrientedRanges.toolMajor.max = diagonalSize; - mOrientedRanges.toolMajor.flat = 0; - mOrientedRanges.toolMajor.fuzz = 0; - mOrientedRanges.toolMajor.resolution = 0; - - mOrientedRanges.toolMinor = mOrientedRanges.toolMajor; - mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR; - - mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE; - mOrientedRanges.size.source = mSource; - mOrientedRanges.size.min = 0; - mOrientedRanges.size.max = 1.0; - mOrientedRanges.size.flat = 0; - mOrientedRanges.size.fuzz = 0; - mOrientedRanges.size.resolution = 0; - } else { - mSizeScale = 0.0f; - } - - // Pressure factors. - mPressureScale = 0; - if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL - || mCalibration.pressureCalibration - == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) { - if (mCalibration.havePressureScale) { - mPressureScale = mCalibration.pressureScale; - } else if (mRawPointerAxes.pressure.valid - && mRawPointerAxes.pressure.maxValue != 0) { - mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue; - } - } - - mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE; - mOrientedRanges.pressure.source = mSource; - mOrientedRanges.pressure.min = 0; - mOrientedRanges.pressure.max = 1.0; - mOrientedRanges.pressure.flat = 0; - mOrientedRanges.pressure.fuzz = 0; - mOrientedRanges.pressure.resolution = 0; - - // Tilt - mTiltXCenter = 0; - mTiltXScale = 0; - mTiltYCenter = 0; - mTiltYScale = 0; - mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid; - if (mHaveTilt) { - mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue, - mRawPointerAxes.tiltX.maxValue); - mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue, - mRawPointerAxes.tiltY.maxValue); - mTiltXScale = M_PI / 180; - mTiltYScale = M_PI / 180; - - mOrientedRanges.haveTilt = true; - - mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT; - mOrientedRanges.tilt.source = mSource; - mOrientedRanges.tilt.min = 0; - mOrientedRanges.tilt.max = M_PI_2; - mOrientedRanges.tilt.flat = 0; - mOrientedRanges.tilt.fuzz = 0; - mOrientedRanges.tilt.resolution = 0; - } - - // Orientation - mOrientationScale = 0; - if (mHaveTilt) { - mOrientedRanges.haveOrientation = true; - - mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION; - mOrientedRanges.orientation.source = mSource; - mOrientedRanges.orientation.min = -M_PI; - mOrientedRanges.orientation.max = M_PI; - mOrientedRanges.orientation.flat = 0; - mOrientedRanges.orientation.fuzz = 0; - mOrientedRanges.orientation.resolution = 0; - } else if (mCalibration.orientationCalibration != - Calibration::ORIENTATION_CALIBRATION_NONE) { - if (mCalibration.orientationCalibration - == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) { - if (mRawPointerAxes.orientation.valid) { - if (mRawPointerAxes.orientation.maxValue > 0) { - mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue; - } else if (mRawPointerAxes.orientation.minValue < 0) { - mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue; - } else { - mOrientationScale = 0; - } - } - } - - mOrientedRanges.haveOrientation = true; - - mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION; - mOrientedRanges.orientation.source = mSource; - mOrientedRanges.orientation.min = -M_PI_2; - mOrientedRanges.orientation.max = M_PI_2; - mOrientedRanges.orientation.flat = 0; - mOrientedRanges.orientation.fuzz = 0; - mOrientedRanges.orientation.resolution = 0; - } - - // Distance - mDistanceScale = 0; - if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) { - if (mCalibration.distanceCalibration - == Calibration::DISTANCE_CALIBRATION_SCALED) { - if (mCalibration.haveDistanceScale) { - mDistanceScale = mCalibration.distanceScale; - } else { - mDistanceScale = 1.0f; - } - } - - mOrientedRanges.haveDistance = true; - - mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE; - mOrientedRanges.distance.source = mSource; - mOrientedRanges.distance.min = - mRawPointerAxes.distance.minValue * mDistanceScale; - mOrientedRanges.distance.max = - mRawPointerAxes.distance.maxValue * mDistanceScale; - mOrientedRanges.distance.flat = 0; - mOrientedRanges.distance.fuzz = - mRawPointerAxes.distance.fuzz * mDistanceScale; - mOrientedRanges.distance.resolution = 0; - } - - // Compute oriented precision, scales and ranges. - // Note that the maximum value reported is an inclusive maximum value so it is one - // unit less than the total width or height of surface. - switch (mSurfaceOrientation) { - case DISPLAY_ORIENTATION_90: - case DISPLAY_ORIENTATION_270: - mOrientedXPrecision = mYPrecision; - mOrientedYPrecision = mXPrecision; - - mOrientedRanges.x.min = mYTranslate; - mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1; - mOrientedRanges.x.flat = 0; - mOrientedRanges.x.fuzz = 0; - mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale; - - mOrientedRanges.y.min = mXTranslate; - mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1; - mOrientedRanges.y.flat = 0; - mOrientedRanges.y.fuzz = 0; - mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale; - break; - - default: - mOrientedXPrecision = mXPrecision; - mOrientedYPrecision = mYPrecision; - - mOrientedRanges.x.min = mXTranslate; - mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1; - mOrientedRanges.x.flat = 0; - mOrientedRanges.x.fuzz = 0; - mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale; - - mOrientedRanges.y.min = mYTranslate; - mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1; - mOrientedRanges.y.flat = 0; - mOrientedRanges.y.fuzz = 0; - mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale; - break; - } - - if (mDeviceMode == DEVICE_MODE_POINTER) { - // Compute pointer gesture detection parameters. - float rawDiagonal = hypotf(rawWidth, rawHeight); - float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight); - - // Scale movements such that one whole swipe of the touch pad covers a - // given area relative to the diagonal size of the display when no acceleration - // is applied. - // Assume that the touch pad has a square aspect ratio such that movements in - // X and Y of the same number of raw units cover the same physical distance. - mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio - * displayDiagonal / rawDiagonal; - mPointerYMovementScale = mPointerXMovementScale; - - // Scale zooms to cover a smaller range of the display than movements do. - // This value determines the area around the pointer that is affected by freeform - // pointer gestures. - mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio - * displayDiagonal / rawDiagonal; - mPointerYZoomScale = mPointerXZoomScale; - - // Max width between pointers to detect a swipe gesture is more than some fraction - // of the diagonal axis of the touch pad. Touches that are wider than this are - // translated into freeform gestures. - mPointerGestureMaxSwipeWidth = - mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal; - - // Abort current pointer usages because the state has changed. - abortPointerUsage(when, 0 /*policyFlags*/); - } - - // Inform the dispatcher about the changes. - *outResetNeeded = true; - bumpGeneration(); - } -} - -void TouchInputMapper::dumpSurface(String8& dump) { - dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, " - "logicalFrame=[%d, %d, %d, %d], " - "physicalFrame=[%d, %d, %d, %d], " - "deviceSize=[%d, %d]\n", - mViewport.displayId, mViewport.orientation, - mViewport.logicalLeft, mViewport.logicalTop, - mViewport.logicalRight, mViewport.logicalBottom, - mViewport.physicalLeft, mViewport.physicalTop, - mViewport.physicalRight, mViewport.physicalBottom, - mViewport.deviceWidth, mViewport.deviceHeight); - - dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth); - dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); - dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft); - dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop); - dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation); -} - -void TouchInputMapper::configureVirtualKeys() { - Vector<VirtualKeyDefinition> virtualKeyDefinitions; - getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions); - - mVirtualKeys.clear(); - - if (virtualKeyDefinitions.size() == 0) { - return; - } - - mVirtualKeys.setCapacity(virtualKeyDefinitions.size()); - - int32_t touchScreenLeft = mRawPointerAxes.x.minValue; - int32_t touchScreenTop = mRawPointerAxes.y.minValue; - int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; - int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; - - for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) { - const VirtualKeyDefinition& virtualKeyDefinition = - virtualKeyDefinitions[i]; - - mVirtualKeys.add(); - VirtualKey& virtualKey = mVirtualKeys.editTop(); - - virtualKey.scanCode = virtualKeyDefinition.scanCode; - int32_t keyCode; - uint32_t flags; - if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) { - ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring", - virtualKey.scanCode); - mVirtualKeys.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 / mSurfaceWidth + touchScreenLeft; - virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth) - * touchScreenWidth / mSurfaceWidth + touchScreenLeft; - virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight) - * touchScreenHeight / mSurfaceHeight + touchScreenTop; - virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) - * touchScreenHeight / mSurfaceHeight + touchScreenTop; - } -} - -void TouchInputMapper::dumpVirtualKeys(String8& dump) { - if (!mVirtualKeys.isEmpty()) { - dump.append(INDENT3 "Virtual Keys:\n"); - - for (size_t i = 0; i < mVirtualKeys.size(); i++) { - const VirtualKey& virtualKey = mVirtualKeys.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; - - // 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 == "geometric") { - out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC; - } else if (sizeCalibrationString == "diameter") { - out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER; - } else if (sizeCalibrationString == "box") { - out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX; - } else if (sizeCalibrationString == "area") { - out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA; - } else if (sizeCalibrationString != "default") { - ALOGW("Invalid value for touch.size.calibration: '%s'", - sizeCalibrationString.string()); - } - } - - out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"), - out.sizeScale); - out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"), - out.sizeBias); - out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"), - out.sizeIsSummed); - - // 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") { - ALOGW("Invalid value for touch.pressure.calibration: '%s'", - pressureCalibrationString.string()); - } - } - - out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"), - out.pressureScale); - - // 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 == "vector") { - out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR; - } else if (orientationCalibrationString != "default") { - ALOGW("Invalid value for touch.orientation.calibration: '%s'", - orientationCalibrationString.string()); - } - } - - // Distance - out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT; - String8 distanceCalibrationString; - if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) { - if (distanceCalibrationString == "none") { - out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE; - } else if (distanceCalibrationString == "scaled") { - out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED; - } else if (distanceCalibrationString != "default") { - ALOGW("Invalid value for touch.distance.calibration: '%s'", - distanceCalibrationString.string()); - } - } - - out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"), - out.distanceScale); - - out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT; - String8 coverageCalibrationString; - if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) { - if (coverageCalibrationString == "none") { - out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE; - } else if (coverageCalibrationString == "box") { - out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX; - } else if (coverageCalibrationString != "default") { - ALOGW("Invalid value for touch.coverage.calibration: '%s'", - coverageCalibrationString.string()); - } - } -} - -void TouchInputMapper::resolveCalibration() { - // Size - if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) { - if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) { - mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC; - } - } else { - mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE; - } - - // Pressure - if (mRawPointerAxes.pressure.valid) { - if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) { - mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL; - } - } else { - mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE; - } - - // Orientation - if (mRawPointerAxes.orientation.valid) { - if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) { - mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED; - } - } else { - mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE; - } - - // Distance - if (mRawPointerAxes.distance.valid) { - if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) { - mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED; - } - } else { - mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE; - } - - // Coverage - if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) { - mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE; - } -} - -void TouchInputMapper::dumpCalibration(String8& dump) { - dump.append(INDENT3 "Calibration:\n"); - - // Size - switch (mCalibration.sizeCalibration) { - case Calibration::SIZE_CALIBRATION_NONE: - dump.append(INDENT4 "touch.size.calibration: none\n"); - break; - case Calibration::SIZE_CALIBRATION_GEOMETRIC: - dump.append(INDENT4 "touch.size.calibration: geometric\n"); - break; - case Calibration::SIZE_CALIBRATION_DIAMETER: - dump.append(INDENT4 "touch.size.calibration: diameter\n"); - break; - case Calibration::SIZE_CALIBRATION_BOX: - dump.append(INDENT4 "touch.size.calibration: box\n"); - break; - case Calibration::SIZE_CALIBRATION_AREA: - dump.append(INDENT4 "touch.size.calibration: area\n"); - break; - default: - ALOG_ASSERT(false); - } - - if (mCalibration.haveSizeScale) { - dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n", - mCalibration.sizeScale); - } - - if (mCalibration.haveSizeBias) { - dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n", - mCalibration.sizeBias); - } - - if (mCalibration.haveSizeIsSummed) { - dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n", - toString(mCalibration.sizeIsSummed)); - } - - // 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: - ALOG_ASSERT(false); - } - - if (mCalibration.havePressureScale) { - dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n", - mCalibration.pressureScale); - } - - // 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; - case Calibration::ORIENTATION_CALIBRATION_VECTOR: - dump.append(INDENT4 "touch.orientation.calibration: vector\n"); - break; - default: - ALOG_ASSERT(false); - } - - // Distance - switch (mCalibration.distanceCalibration) { - case Calibration::DISTANCE_CALIBRATION_NONE: - dump.append(INDENT4 "touch.distance.calibration: none\n"); - break; - case Calibration::DISTANCE_CALIBRATION_SCALED: - dump.append(INDENT4 "touch.distance.calibration: scaled\n"); - break; - default: - ALOG_ASSERT(false); - } - - if (mCalibration.haveDistanceScale) { - dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n", - mCalibration.distanceScale); - } - - switch (mCalibration.coverageCalibration) { - case Calibration::COVERAGE_CALIBRATION_NONE: - dump.append(INDENT4 "touch.coverage.calibration: none\n"); - break; - case Calibration::COVERAGE_CALIBRATION_BOX: - dump.append(INDENT4 "touch.coverage.calibration: box\n"); - break; - default: - ALOG_ASSERT(false); - } -} - -void TouchInputMapper::reset(nsecs_t when) { - mCursorButtonAccumulator.reset(getDevice()); - mCursorScrollAccumulator.reset(getDevice()); - mTouchButtonAccumulator.reset(getDevice()); - - mPointerVelocityControl.reset(); - mWheelXVelocityControl.reset(); - mWheelYVelocityControl.reset(); - - mCurrentRawPointerData.clear(); - mLastRawPointerData.clear(); - mCurrentCookedPointerData.clear(); - mLastCookedPointerData.clear(); - mCurrentButtonState = 0; - mLastButtonState = 0; - mCurrentRawVScroll = 0; - mCurrentRawHScroll = 0; - mCurrentFingerIdBits.clear(); - mLastFingerIdBits.clear(); - mCurrentStylusIdBits.clear(); - mLastStylusIdBits.clear(); - mCurrentMouseIdBits.clear(); - mLastMouseIdBits.clear(); - mPointerUsage = POINTER_USAGE_NONE; - mSentHoverEnter = false; - mDownTime = 0; - - mCurrentVirtualKey.down = false; - - mPointerGesture.reset(); - mPointerSimple.reset(); - - if (mPointerController != NULL) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - mPointerController->clearSpots(); - } - - InputMapper::reset(when); -} - -void TouchInputMapper::process(const RawEvent* rawEvent) { - mCursorButtonAccumulator.process(rawEvent); - mCursorScrollAccumulator.process(rawEvent); - mTouchButtonAccumulator.process(rawEvent); - - if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - sync(rawEvent->when); - } -} - -void TouchInputMapper::sync(nsecs_t when) { - // Sync button state. - mCurrentButtonState = mTouchButtonAccumulator.getButtonState() - | mCursorButtonAccumulator.getButtonState(); - - // Sync scroll state. - mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel(); - mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel(); - mCursorScrollAccumulator.finishSync(); - - // Sync touch state. - bool havePointerIds = true; - mCurrentRawPointerData.clear(); - syncTouch(when, &havePointerIds); - -#if DEBUG_RAW_EVENTS - if (!havePointerIds) { - ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids", - mLastRawPointerData.pointerCount, - mCurrentRawPointerData.pointerCount); - } else { - ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, " - "hovering ids 0x%08x -> 0x%08x", - mLastRawPointerData.pointerCount, - mCurrentRawPointerData.pointerCount, - mLastRawPointerData.touchingIdBits.value, - mCurrentRawPointerData.touchingIdBits.value, - mLastRawPointerData.hoveringIdBits.value, - mCurrentRawPointerData.hoveringIdBits.value); - } -#endif - - // Reset state that we will compute below. - mCurrentFingerIdBits.clear(); - mCurrentStylusIdBits.clear(); - mCurrentMouseIdBits.clear(); - mCurrentCookedPointerData.clear(); - - if (mDeviceMode == DEVICE_MODE_DISABLED) { - // Drop all input if the device is disabled. - mCurrentRawPointerData.clear(); - mCurrentButtonState = 0; - } else { - // Preprocess pointer data. - if (!havePointerIds) { - assignPointerIds(); - } - - // Handle policy on initial down or hover events. - uint32_t policyFlags = 0; - bool initialDown = mLastRawPointerData.pointerCount == 0 - && mCurrentRawPointerData.pointerCount != 0; - bool buttonsPressed = mCurrentButtonState & ~mLastButtonState; - if (initialDown || buttonsPressed) { - // If this is a touch screen, hide the pointer on an initial down. - if (mDeviceMode == DEVICE_MODE_DIRECT) { - getContext()->fadePointer(); - } - - // Initial downs on external touch devices should wake the device. - // We don't do this for internal touch screens to prevent them from waking - // up in your pocket. - // TODO: Use the input device configuration to control this behavior more finely. - if (getDevice()->isExternal()) { - policyFlags |= POLICY_FLAG_WAKE_DROPPED; - } - } - - // Synthesize key down from raw buttons if needed. - synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource, - policyFlags, mLastButtonState, mCurrentButtonState); - - // Consume raw off-screen touches before cooking pointer data. - // If touches are consumed, subsequent code will not receive any pointer data. - if (consumeRawTouches(when, policyFlags)) { - mCurrentRawPointerData.clear(); - } - - // Cook pointer data. This call populates the mCurrentCookedPointerData structure - // with cooked pointer data that has the same ids and indices as the raw data. - // The following code can use either the raw or cooked data, as needed. - cookPointerData(); - - // Dispatch the touches either directly or by translation through a pointer on screen. - if (mDeviceMode == DEVICE_MODE_POINTER) { - for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); - if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS - || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) { - mCurrentStylusIdBits.markBit(id); - } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER - || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { - mCurrentFingerIdBits.markBit(id); - } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) { - mCurrentMouseIdBits.markBit(id); - } - } - for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); - if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS - || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) { - mCurrentStylusIdBits.markBit(id); - } - } - - // Stylus takes precedence over all tools, then mouse, then finger. - PointerUsage pointerUsage = mPointerUsage; - if (!mCurrentStylusIdBits.isEmpty()) { - mCurrentMouseIdBits.clear(); - mCurrentFingerIdBits.clear(); - pointerUsage = POINTER_USAGE_STYLUS; - } else if (!mCurrentMouseIdBits.isEmpty()) { - mCurrentFingerIdBits.clear(); - pointerUsage = POINTER_USAGE_MOUSE; - } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) { - pointerUsage = POINTER_USAGE_GESTURES; - } - - dispatchPointerUsage(when, policyFlags, pointerUsage); - } else { - if (mDeviceMode == DEVICE_MODE_DIRECT - && mConfig.showTouches && mPointerController != NULL) { - mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT); - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - - mPointerController->setButtonState(mCurrentButtonState); - mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords, - mCurrentCookedPointerData.idToIndex, - mCurrentCookedPointerData.touchingIdBits); - } - - dispatchHoverExit(when, policyFlags); - dispatchTouches(when, policyFlags); - dispatchHoverEnterAndMove(when, policyFlags); - } - - // Synthesize key up from raw buttons if needed. - synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, - policyFlags, mLastButtonState, mCurrentButtonState); - } - - // Copy current touch to last touch in preparation for the next cycle. - mLastRawPointerData.copyFrom(mCurrentRawPointerData); - mLastCookedPointerData.copyFrom(mCurrentCookedPointerData); - mLastButtonState = mCurrentButtonState; - mLastFingerIdBits = mCurrentFingerIdBits; - mLastStylusIdBits = mCurrentStylusIdBits; - mLastMouseIdBits = mCurrentMouseIdBits; - - // Clear some transient state. - mCurrentRawVScroll = 0; - mCurrentRawHScroll = 0; -} - -void TouchInputMapper::timeoutExpired(nsecs_t when) { - if (mDeviceMode == DEVICE_MODE_POINTER) { - if (mPointerUsage == POINTER_USAGE_GESTURES) { - dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/); - } - } -} - -bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) { - // Check for release of a virtual key. - if (mCurrentVirtualKey.down) { - if (mCurrentRawPointerData.touchingIdBits.isEmpty()) { - // Pointer went up while virtual key was down. - mCurrentVirtualKey.down = false; - if (!mCurrentVirtualKey.ignored) { -#if DEBUG_VIRTUAL_KEYS - ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d", - mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); -#endif - dispatchVirtualKey(when, policyFlags, - AKEY_EVENT_ACTION_UP, - AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); - } - return true; - } - - if (mCurrentRawPointerData.touchingIdBits.count() == 1) { - uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit(); - const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); - const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y); - if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) { - // Pointer is still within the space of the virtual key. - return true; - } - } - - // Pointer left virtual key area or another pointer also went down. - // Send key cancellation but do not consume the touch yet. - // This is useful when the user swipes through from the virtual key area - // into the main display surface. - mCurrentVirtualKey.down = false; - if (!mCurrentVirtualKey.ignored) { -#if DEBUG_VIRTUAL_KEYS - ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", - mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); -#endif - dispatchVirtualKey(when, policyFlags, - AKEY_EVENT_ACTION_UP, - AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY - | AKEY_EVENT_FLAG_CANCELED); - } - } - - if (mLastRawPointerData.touchingIdBits.isEmpty() - && !mCurrentRawPointerData.touchingIdBits.isEmpty()) { - // Pointer just went down. Check for virtual key press or off-screen touches. - uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit(); - const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); - if (!isPointInsideSurface(pointer.x, pointer.y)) { - // If exactly one pointer went down, check for virtual key hit. - // Otherwise we will drop the entire stroke. - if (mCurrentRawPointerData.touchingIdBits.count() == 1) { - const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y); - if (virtualKey) { - mCurrentVirtualKey.down = true; - mCurrentVirtualKey.downTime = when; - mCurrentVirtualKey.keyCode = virtualKey->keyCode; - mCurrentVirtualKey.scanCode = virtualKey->scanCode; - mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey( - when, getDevice(), virtualKey->keyCode, virtualKey->scanCode); - - if (!mCurrentVirtualKey.ignored) { -#if DEBUG_VIRTUAL_KEYS - ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d", - mCurrentVirtualKey.keyCode, - mCurrentVirtualKey.scanCode); -#endif - dispatchVirtualKey(when, policyFlags, - AKEY_EVENT_ACTION_DOWN, - AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); - } - } - } - return true; - } - } - - // Disable all virtual key touches that happen within a short time interval of the - // most recent touch within the screen area. The idea is to filter out stray - // virtual key presses when interacting with the touch screen. - // - // Problems we're trying to solve: - // - // 1. While scrolling a list or dragging the window shade, the user swipes down into a - // virtual key area that is implemented by a separate touch panel and accidentally - // triggers a virtual key. - // - // 2. While typing in the on screen keyboard, the user taps slightly outside the screen - // area and accidentally triggers a virtual key. This often happens when virtual keys - // are layed out below the screen near to where the on screen keyboard's space bar - // is displayed. - if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) { - mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime); - } - return false; -} - -void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, - int32_t keyEventAction, int32_t keyEventFlags) { - int32_t keyCode = mCurrentVirtualKey.keyCode; - int32_t scanCode = mCurrentVirtualKey.scanCode; - nsecs_t downTime = mCurrentVirtualKey.downTime; - int32_t metaState = mContext->getGlobalMetaState(); - policyFlags |= POLICY_FLAG_VIRTUAL; - - NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags, - keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime); - getListener()->notifyKey(&args); -} - -void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { - BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits; - BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits; - int32_t metaState = getContext()->getGlobalMetaState(); - int32_t buttonState = mCurrentButtonState; - - if (currentIdBits == lastIdBits) { - if (!currentIdBits.isEmpty()) { - // No pointer id changes so this is a move event. - // The listener takes care of batching moves so we don't have to deal with that here. - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, - AMOTION_EVENT_EDGE_FLAG_NONE, - mCurrentCookedPointerData.pointerProperties, - mCurrentCookedPointerData.pointerCoords, - mCurrentCookedPointerData.idToIndex, - currentIdBits, -1, - mOrientedXPrecision, mOrientedYPrecision, mDownTime); - } - } 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 moveIdBits(lastIdBits.value & currentIdBits.value); - BitSet32 dispatchedIdBits(lastIdBits.value); - - // Update last coordinates of pointers that have moved so that we observe the new - // pointer positions at the same time as other pointers that have just gone up. - bool moveNeeded = updateMovedPointers( - mCurrentCookedPointerData.pointerProperties, - mCurrentCookedPointerData.pointerCoords, - mCurrentCookedPointerData.idToIndex, - mLastCookedPointerData.pointerProperties, - mLastCookedPointerData.pointerCoords, - mLastCookedPointerData.idToIndex, - moveIdBits); - if (buttonState != mLastButtonState) { - moveNeeded = true; - } - - // Dispatch pointer up events. - while (!upIdBits.isEmpty()) { - uint32_t upId = upIdBits.clearFirstMarkedBit(); - - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0, - mLastCookedPointerData.pointerProperties, - mLastCookedPointerData.pointerCoords, - mLastCookedPointerData.idToIndex, - dispatchedIdBits, upId, - mOrientedXPrecision, mOrientedYPrecision, mDownTime); - dispatchedIdBits.clearBit(upId); - } - - // 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) { - ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value); - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0, - mCurrentCookedPointerData.pointerProperties, - mCurrentCookedPointerData.pointerCoords, - mCurrentCookedPointerData.idToIndex, - dispatchedIdBits, -1, - mOrientedXPrecision, mOrientedYPrecision, mDownTime); - } - - // Dispatch pointer down events using the new pointer locations. - while (!downIdBits.isEmpty()) { - uint32_t downId = downIdBits.clearFirstMarkedBit(); - dispatchedIdBits.markBit(downId); - - if (dispatchedIdBits.count() == 1) { - // First pointer is going down. Set down time. - mDownTime = when; - } - - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0, - mCurrentCookedPointerData.pointerProperties, - mCurrentCookedPointerData.pointerCoords, - mCurrentCookedPointerData.idToIndex, - dispatchedIdBits, downId, - mOrientedXPrecision, mOrientedYPrecision, mDownTime); - } - } -} - -void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) { - if (mSentHoverEnter && - (mCurrentCookedPointerData.hoveringIdBits.isEmpty() - || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) { - int32_t metaState = getContext()->getGlobalMetaState(); - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0, - mLastCookedPointerData.pointerProperties, - mLastCookedPointerData.pointerCoords, - mLastCookedPointerData.idToIndex, - mLastCookedPointerData.hoveringIdBits, -1, - mOrientedXPrecision, mOrientedYPrecision, mDownTime); - mSentHoverEnter = false; - } -} - -void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) { - if (mCurrentCookedPointerData.touchingIdBits.isEmpty() - && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) { - int32_t metaState = getContext()->getGlobalMetaState(); - if (!mSentHoverEnter) { - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0, - mCurrentCookedPointerData.pointerProperties, - mCurrentCookedPointerData.pointerCoords, - mCurrentCookedPointerData.idToIndex, - mCurrentCookedPointerData.hoveringIdBits, -1, - mOrientedXPrecision, mOrientedYPrecision, mDownTime); - mSentHoverEnter = true; - } - - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0, - mCurrentCookedPointerData.pointerProperties, - mCurrentCookedPointerData.pointerCoords, - mCurrentCookedPointerData.idToIndex, - mCurrentCookedPointerData.hoveringIdBits, -1, - mOrientedXPrecision, mOrientedYPrecision, mDownTime); - } -} - -void TouchInputMapper::cookPointerData() { - uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount; - - mCurrentCookedPointerData.clear(); - mCurrentCookedPointerData.pointerCount = currentPointerCount; - mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits; - mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits; - - // Walk through the the active pointers and map device coordinates onto - // surface coordinates and adjust for display orientation. - for (uint32_t i = 0; i < currentPointerCount; i++) { - const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i]; - - // Size - float touchMajor, touchMinor, toolMajor, toolMinor, size; - switch (mCalibration.sizeCalibration) { - case Calibration::SIZE_CALIBRATION_GEOMETRIC: - case Calibration::SIZE_CALIBRATION_DIAMETER: - case Calibration::SIZE_CALIBRATION_BOX: - case Calibration::SIZE_CALIBRATION_AREA: - if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) { - touchMajor = in.touchMajor; - touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor; - toolMajor = in.toolMajor; - toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor; - size = mRawPointerAxes.touchMinor.valid - ? avg(in.touchMajor, in.touchMinor) : in.touchMajor; - } else if (mRawPointerAxes.touchMajor.valid) { - toolMajor = touchMajor = in.touchMajor; - toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid - ? in.touchMinor : in.touchMajor; - size = mRawPointerAxes.touchMinor.valid - ? avg(in.touchMajor, in.touchMinor) : in.touchMajor; - } else if (mRawPointerAxes.toolMajor.valid) { - touchMajor = toolMajor = in.toolMajor; - touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid - ? in.toolMinor : in.toolMajor; - size = mRawPointerAxes.toolMinor.valid - ? avg(in.toolMajor, in.toolMinor) : in.toolMajor; - } else { - ALOG_ASSERT(false, "No touch or tool axes. " - "Size calibration should have been resolved to NONE."); - touchMajor = 0; - touchMinor = 0; - toolMajor = 0; - toolMinor = 0; - size = 0; - } - - if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) { - uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count(); - if (touchingCount > 1) { - touchMajor /= touchingCount; - touchMinor /= touchingCount; - toolMajor /= touchingCount; - toolMinor /= touchingCount; - size /= touchingCount; - } - } - - if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) { - touchMajor *= mGeometricScale; - touchMinor *= mGeometricScale; - toolMajor *= mGeometricScale; - toolMinor *= mGeometricScale; - } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) { - touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0; - touchMinor = touchMajor; - toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0; - toolMinor = toolMajor; - } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) { - touchMinor = touchMajor; - toolMinor = toolMajor; - } - - mCalibration.applySizeScaleAndBias(&touchMajor); - mCalibration.applySizeScaleAndBias(&touchMinor); - mCalibration.applySizeScaleAndBias(&toolMajor); - mCalibration.applySizeScaleAndBias(&toolMinor); - size *= mSizeScale; - break; - default: - touchMajor = 0; - touchMinor = 0; - toolMajor = 0; - toolMinor = 0; - size = 0; - break; - } - - // Pressure - float pressure; - switch (mCalibration.pressureCalibration) { - case Calibration::PRESSURE_CALIBRATION_PHYSICAL: - case Calibration::PRESSURE_CALIBRATION_AMPLITUDE: - pressure = in.pressure * mPressureScale; - break; - default: - pressure = in.isHovering ? 0 : 1; - break; - } - - // Tilt and Orientation - float tilt; - float orientation; - if (mHaveTilt) { - float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale; - float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale; - orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle)); - tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle)); - } else { - tilt = 0; - - switch (mCalibration.orientationCalibration) { - case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED: - orientation = in.orientation * mOrientationScale; - break; - case Calibration::ORIENTATION_CALIBRATION_VECTOR: { - int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4); - int32_t c2 = signExtendNybble(in.orientation & 0x0f); - if (c1 != 0 || c2 != 0) { - orientation = atan2f(c1, c2) * 0.5f; - float confidence = hypotf(c1, c2); - float scale = 1.0f + confidence / 16.0f; - touchMajor *= scale; - touchMinor /= scale; - toolMajor *= scale; - toolMinor /= scale; - } else { - orientation = 0; - } - break; - } - default: - orientation = 0; - } - } - - // Distance - float distance; - switch (mCalibration.distanceCalibration) { - case Calibration::DISTANCE_CALIBRATION_SCALED: - distance = in.distance * mDistanceScale; - break; - default: - distance = 0; - } - - // Coverage - int32_t rawLeft, rawTop, rawRight, rawBottom; - switch (mCalibration.coverageCalibration) { - case Calibration::COVERAGE_CALIBRATION_BOX: - rawLeft = (in.toolMinor & 0xffff0000) >> 16; - rawRight = in.toolMinor & 0x0000ffff; - rawBottom = in.toolMajor & 0x0000ffff; - rawTop = (in.toolMajor & 0xffff0000) >> 16; - break; - default: - rawLeft = rawTop = rawRight = rawBottom = 0; - break; - } - - // X, Y, and the bounding box for coverage information - // Adjust coords for surface orientation. - float x, y, left, top, right, bottom; - switch (mSurfaceOrientation) { - case DISPLAY_ORIENTATION_90: - x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; - y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; - left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; - right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate; - bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate; - top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate; - orientation -= M_PI_2; - if (orientation < - M_PI_2) { - orientation += M_PI; - } - break; - case DISPLAY_ORIENTATION_180: - x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; - y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; - left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate; - right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate; - bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; - top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; - break; - case DISPLAY_ORIENTATION_270: - x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; - y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; - right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; - bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - orientation += M_PI_2; - if (orientation > M_PI_2) { - orientation -= M_PI; - } - break; - default: - x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; - left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; - top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; - break; - } - - // Write output coords. - PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i]; - out.clear(); - out.setAxisValue(AMOTION_EVENT_AXIS_X, x); - out.setAxisValue(AMOTION_EVENT_AXIS_Y, y); - out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure); - out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size); - out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor); - out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor); - out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation); - out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt); - out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance); - if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) { - out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left); - out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top); - out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right); - out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom); - } else { - out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor); - out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor); - } - - // Write output properties. - PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i]; - uint32_t id = in.id; - properties.clear(); - properties.id = id; - properties.toolType = in.toolType; - - // Write id index. - mCurrentCookedPointerData.idToIndex[id] = i; - } -} - -void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, - PointerUsage pointerUsage) { - if (pointerUsage != mPointerUsage) { - abortPointerUsage(when, policyFlags); - mPointerUsage = pointerUsage; - } - - switch (mPointerUsage) { - case POINTER_USAGE_GESTURES: - dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); - break; - case POINTER_USAGE_STYLUS: - dispatchPointerStylus(when, policyFlags); - break; - case POINTER_USAGE_MOUSE: - dispatchPointerMouse(when, policyFlags); - break; - default: - break; - } -} - -void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) { - switch (mPointerUsage) { - case POINTER_USAGE_GESTURES: - abortPointerGestures(when, policyFlags); - break; - case POINTER_USAGE_STYLUS: - abortPointerStylus(when, policyFlags); - break; - case POINTER_USAGE_MOUSE: - abortPointerMouse(when, policyFlags); - break; - default: - break; - } - - mPointerUsage = POINTER_USAGE_NONE; -} - -void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, - bool isTimeout) { - // Update current gesture coordinates. - bool cancelPreviousGesture, finishPreviousGesture; - bool sendEvents = preparePointerGestures(when, - &cancelPreviousGesture, &finishPreviousGesture, isTimeout); - if (!sendEvents) { - return; - } - if (finishPreviousGesture) { - cancelPreviousGesture = false; - } - - // Update the pointer presentation and spots. - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT); - if (finishPreviousGesture || cancelPreviousGesture) { - mPointerController->clearSpots(); - } - mPointerController->setSpots(mPointerGesture.currentGestureCoords, - mPointerGesture.currentGestureIdToIndex, - mPointerGesture.currentGestureIdBits); - } else { - mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); - } - - // Show or hide the pointer if needed. - switch (mPointerGesture.currentGestureMode) { - case PointerGesture::NEUTRAL: - case PointerGesture::QUIET: - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS - && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE - || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) { - // Remind the user of where the pointer is after finishing a gesture with spots. - mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL); - } - break; - case PointerGesture::TAP: - case PointerGesture::TAP_DRAG: - case PointerGesture::BUTTON_CLICK_OR_DRAG: - case PointerGesture::HOVER: - case PointerGesture::PRESS: - // Unfade the pointer when the current gesture manipulates the - // area directly under the pointer. - mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); - break; - case PointerGesture::SWIPE: - case PointerGesture::FREEFORM: - // Fade the pointer when the current gesture manipulates a different - // area and there are spots to guide the user experience. - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - } else { - mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); - } - break; - } - - // Send events! - int32_t metaState = getContext()->getGlobalMetaState(); - int32_t buttonState = mCurrentButtonState; - - // Update last coordinates of pointers that have moved so that we observe the new - // pointer positions at the same time as other pointers that have just gone up. - bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP - || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG - || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG - || mPointerGesture.currentGestureMode == PointerGesture::PRESS - || mPointerGesture.currentGestureMode == PointerGesture::SWIPE - || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM; - bool moveNeeded = false; - if (down && !cancelPreviousGesture && !finishPreviousGesture - && !mPointerGesture.lastGestureIdBits.isEmpty() - && !mPointerGesture.currentGestureIdBits.isEmpty()) { - BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value - & mPointerGesture.lastGestureIdBits.value); - moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties, - mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, - mPointerGesture.lastGestureProperties, - mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, - movedGestureIdBits); - if (buttonState != mLastButtonState) { - moveNeeded = true; - } - } - - // Send motion events for all pointers that went up or were canceled. - BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits); - if (!dispatchedGestureIdBits.isEmpty()) { - if (cancelPreviousGesture) { - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState, - AMOTION_EVENT_EDGE_FLAG_NONE, - mPointerGesture.lastGestureProperties, - mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, - dispatchedGestureIdBits, -1, - 0, 0, mPointerGesture.downTime); - - dispatchedGestureIdBits.clear(); - } else { - BitSet32 upGestureIdBits; - if (finishPreviousGesture) { - upGestureIdBits = dispatchedGestureIdBits; - } else { - upGestureIdBits.value = dispatchedGestureIdBits.value - & ~mPointerGesture.currentGestureIdBits.value; - } - while (!upGestureIdBits.isEmpty()) { - uint32_t id = upGestureIdBits.clearFirstMarkedBit(); - - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_POINTER_UP, 0, - metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - mPointerGesture.lastGestureProperties, - mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, - dispatchedGestureIdBits, id, - 0, 0, mPointerGesture.downTime); - - dispatchedGestureIdBits.clearBit(id); - } - } - } - - // Send motion events for all pointers that moved. - if (moveNeeded) { - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - mPointerGesture.currentGestureProperties, - mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, - dispatchedGestureIdBits, -1, - 0, 0, mPointerGesture.downTime); - } - - // Send motion events for all pointers that went down. - if (down) { - BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value - & ~dispatchedGestureIdBits.value); - while (!downGestureIdBits.isEmpty()) { - uint32_t id = downGestureIdBits.clearFirstMarkedBit(); - dispatchedGestureIdBits.markBit(id); - - if (dispatchedGestureIdBits.count() == 1) { - mPointerGesture.downTime = when; - } - - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0, - mPointerGesture.currentGestureProperties, - mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, - dispatchedGestureIdBits, id, - 0, 0, mPointerGesture.downTime); - } - } - - // Send motion events for hover. - if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) { - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_HOVER_MOVE, 0, - metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - mPointerGesture.currentGestureProperties, - mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, - mPointerGesture.currentGestureIdBits, -1, - 0, 0, mPointerGesture.downTime); - } else if (dispatchedGestureIdBits.isEmpty() - && !mPointerGesture.lastGestureIdBits.isEmpty()) { - // Synthesize a hover move event after all pointers go up to indicate that - // the pointer is hovering again even if the user is not currently touching - // the touch pad. This ensures that a view will receive a fresh hover enter - // event after a tap. - float x, y; - mPointerController->getPosition(&x, &y); - - PointerProperties pointerProperties; - pointerProperties.clear(); - pointerProperties.id = 0; - pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; - - PointerCoords pointerCoords; - pointerCoords.clear(); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); - - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_HOVER_MOVE, 0, - metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - mViewport.displayId, 1, &pointerProperties, &pointerCoords, - 0, 0, mPointerGesture.downTime); - getListener()->notifyMotion(&args); - } - - // Update state. - mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode; - if (!down) { - mPointerGesture.lastGestureIdBits.clear(); - } else { - mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits; - for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - uint32_t index = mPointerGesture.currentGestureIdToIndex[id]; - mPointerGesture.lastGestureProperties[index].copyFrom( - mPointerGesture.currentGestureProperties[index]); - mPointerGesture.lastGestureCoords[index].copyFrom( - mPointerGesture.currentGestureCoords[index]); - mPointerGesture.lastGestureIdToIndex[id] = index; - } - } -} - -void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) { - // Cancel previously dispatches pointers. - if (!mPointerGesture.lastGestureIdBits.isEmpty()) { - int32_t metaState = getContext()->getGlobalMetaState(); - int32_t buttonState = mCurrentButtonState; - dispatchMotion(when, policyFlags, mSource, - AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState, - AMOTION_EVENT_EDGE_FLAG_NONE, - mPointerGesture.lastGestureProperties, - mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, - mPointerGesture.lastGestureIdBits, -1, - 0, 0, mPointerGesture.downTime); - } - - // Reset the current pointer gesture. - mPointerGesture.reset(); - mPointerVelocityControl.reset(); - - // Remove any current spots. - if (mPointerController != NULL) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - mPointerController->clearSpots(); - } -} - -bool TouchInputMapper::preparePointerGestures(nsecs_t when, - bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) { - *outCancelPreviousGesture = false; - *outFinishPreviousGesture = false; - - // Handle TAP timeout. - if (isTimeout) { -#if DEBUG_GESTURES - ALOGD("Gestures: Processing timeout"); -#endif - - if (mPointerGesture.lastGestureMode == PointerGesture::TAP) { - if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) { - // The tap/drag timeout has not yet expired. - getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime - + mConfig.pointerGestureTapDragInterval); - } else { - // The tap is finished. -#if DEBUG_GESTURES - ALOGD("Gestures: TAP finished"); -#endif - *outFinishPreviousGesture = true; - - mPointerGesture.activeGestureId = -1; - mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL; - mPointerGesture.currentGestureIdBits.clear(); - - mPointerVelocityControl.reset(); - return true; - } - } - - // We did not handle this timeout. - return false; - } - - const uint32_t currentFingerCount = mCurrentFingerIdBits.count(); - const uint32_t lastFingerCount = mLastFingerIdBits.count(); - - // Update the velocity tracker. - { - VelocityTracker::Position positions[MAX_POINTERS]; - uint32_t count = 0; - for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) { - uint32_t id = idBits.clearFirstMarkedBit(); - const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); - positions[count].x = pointer.x * mPointerXMovementScale; - positions[count].y = pointer.y * mPointerYMovementScale; - } - mPointerGesture.velocityTracker.addMovement(when, - mCurrentFingerIdBits, positions); - } - - // Pick a new active touch id if needed. - // Choose an arbitrary pointer that just went down, if there is one. - // Otherwise choose an arbitrary remaining pointer. - // This guarantees we always have an active touch id when there is at least one pointer. - // We keep the same active touch id for as long as possible. - int32_t lastActiveTouchId = mPointerGesture.activeTouchId; - int32_t activeTouchId = lastActiveTouchId; - if (activeTouchId < 0) { - if (!mCurrentFingerIdBits.isEmpty()) { - activeTouchId = mPointerGesture.activeTouchId = - mCurrentFingerIdBits.firstMarkedBit(); - mPointerGesture.firstTouchTime = when; - } - } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) { - if (!mCurrentFingerIdBits.isEmpty()) { - activeTouchId = mPointerGesture.activeTouchId = - mCurrentFingerIdBits.firstMarkedBit(); - } else { - activeTouchId = mPointerGesture.activeTouchId = -1; - } - } - - // Determine whether we are in quiet time. - bool isQuietTime = false; - if (activeTouchId < 0) { - mPointerGesture.resetQuietTime(); - } else { - isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval; - if (!isQuietTime) { - if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS - || mPointerGesture.lastGestureMode == PointerGesture::SWIPE - || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) - && currentFingerCount < 2) { - // Enter quiet time when exiting swipe or freeform state. - // This is to prevent accidentally entering the hover state and flinging the - // pointer when finishing a swipe and there is still one pointer left onscreen. - isQuietTime = true; - } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG - && currentFingerCount >= 2 - && !isPointerDown(mCurrentButtonState)) { - // Enter quiet time when releasing the button and there are still two or more - // fingers down. This may indicate that one finger was used to press the button - // but it has not gone up yet. - isQuietTime = true; - } - if (isQuietTime) { - mPointerGesture.quietTime = when; - } - } - } - - // Switch states based on button and pointer state. - if (isQuietTime) { - // Case 1: Quiet time. (QUIET) -#if DEBUG_GESTURES - ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime - + mConfig.pointerGestureQuietInterval - when) * 0.000001f); -#endif - if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) { - *outFinishPreviousGesture = true; - } - - mPointerGesture.activeGestureId = -1; - mPointerGesture.currentGestureMode = PointerGesture::QUIET; - mPointerGesture.currentGestureIdBits.clear(); - - mPointerVelocityControl.reset(); - } else if (isPointerDown(mCurrentButtonState)) { - // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG) - // The pointer follows the active touch point. - // Emit DOWN, MOVE, UP events at the pointer location. - // - // Only the active touch matters; other fingers are ignored. This policy helps - // to handle the case where the user places a second finger on the touch pad - // to apply the necessary force to depress an integrated button below the surface. - // We don't want the second finger to be delivered to applications. - // - // For this to work well, we need to make sure to track the pointer that is really - // active. If the user first puts one finger down to click then adds another - // finger to drag then the active pointer should switch to the finger that is - // being dragged. -#if DEBUG_GESTURES - ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, " - "currentFingerCount=%d", activeTouchId, currentFingerCount); -#endif - // Reset state when just starting. - if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) { - *outFinishPreviousGesture = true; - mPointerGesture.activeGestureId = 0; - } - - // Switch pointers if needed. - // Find the fastest pointer and follow it. - if (activeTouchId >= 0 && currentFingerCount > 1) { - int32_t bestId = -1; - float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed; - for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - float vx, vy; - if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) { - float speed = hypotf(vx, vy); - if (speed > bestSpeed) { - bestId = id; - bestSpeed = speed; - } - } - } - if (bestId >= 0 && bestId != activeTouchId) { - mPointerGesture.activeTouchId = activeTouchId = bestId; -#if DEBUG_GESTURES - ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, " - "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed); -#endif - } - } - - if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) { - const RawPointerData::Pointer& currentPointer = - mCurrentRawPointerData.pointerForId(activeTouchId); - const RawPointerData::Pointer& lastPointer = - mLastRawPointerData.pointerForId(activeTouchId); - float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale; - float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale; - - rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); - mPointerVelocityControl.move(when, &deltaX, &deltaY); - - // Move the pointer using a relative motion. - // When using spots, the click will occur at the position of the anchor - // spot and all other spots will move there. - mPointerController->move(deltaX, deltaY); - } else { - mPointerVelocityControl.reset(); - } - - float x, y; - mPointerController->getPosition(&x, &y); - - mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG; - mPointerGesture.currentGestureIdBits.clear(); - mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); - mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; - mPointerGesture.currentGestureProperties[0].clear(); - mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; - mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; - mPointerGesture.currentGestureCoords[0].clear(); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - } else if (currentFingerCount == 0) { - // Case 3. No fingers down and button is not pressed. (NEUTRAL) - if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) { - *outFinishPreviousGesture = true; - } - - // Watch for taps coming out of HOVER or TAP_DRAG mode. - // Checking for taps after TAP_DRAG allows us to detect double-taps. - bool tapped = false; - if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER - || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) - && lastFingerCount == 1) { - if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) { - float x, y; - mPointerController->getPosition(&x, &y); - if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop - && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) { -#if DEBUG_GESTURES - ALOGD("Gestures: TAP"); -#endif - - mPointerGesture.tapUpTime = when; - getContext()->requestTimeoutAtTime(when - + mConfig.pointerGestureTapDragInterval); - - mPointerGesture.activeGestureId = 0; - mPointerGesture.currentGestureMode = PointerGesture::TAP; - mPointerGesture.currentGestureIdBits.clear(); - mPointerGesture.currentGestureIdBits.markBit( - mPointerGesture.activeGestureId); - mPointerGesture.currentGestureIdToIndex[ - mPointerGesture.activeGestureId] = 0; - mPointerGesture.currentGestureProperties[0].clear(); - mPointerGesture.currentGestureProperties[0].id = - mPointerGesture.activeGestureId; - mPointerGesture.currentGestureProperties[0].toolType = - AMOTION_EVENT_TOOL_TYPE_FINGER; - mPointerGesture.currentGestureCoords[0].clear(); - mPointerGesture.currentGestureCoords[0].setAxisValue( - AMOTION_EVENT_AXIS_X, mPointerGesture.tapX); - mPointerGesture.currentGestureCoords[0].setAxisValue( - AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY); - mPointerGesture.currentGestureCoords[0].setAxisValue( - AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - - tapped = true; - } else { -#if DEBUG_GESTURES - ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f", - x - mPointerGesture.tapX, - y - mPointerGesture.tapY); -#endif - } - } else { -#if DEBUG_GESTURES - ALOGD("Gestures: Not a TAP, %0.3fms since down", - (when - mPointerGesture.tapDownTime) * 0.000001f); -#endif - } - } - - mPointerVelocityControl.reset(); - - if (!tapped) { -#if DEBUG_GESTURES - ALOGD("Gestures: NEUTRAL"); -#endif - mPointerGesture.activeGestureId = -1; - mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL; - mPointerGesture.currentGestureIdBits.clear(); - } - } else if (currentFingerCount == 1) { - // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG) - // The pointer follows the active touch point. - // When in HOVER, emit HOVER_MOVE events at the pointer location. - // When in TAP_DRAG, emit MOVE events at the pointer location. - ALOG_ASSERT(activeTouchId >= 0); - - mPointerGesture.currentGestureMode = PointerGesture::HOVER; - if (mPointerGesture.lastGestureMode == PointerGesture::TAP) { - if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) { - float x, y; - mPointerController->getPosition(&x, &y); - if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop - && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) { - mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG; - } else { -#if DEBUG_GESTURES - ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f", - x - mPointerGesture.tapX, - y - mPointerGesture.tapY); -#endif - } - } else { -#if DEBUG_GESTURES - ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up", - (when - mPointerGesture.tapUpTime) * 0.000001f); -#endif - } - } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) { - mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG; - } - - if (mLastFingerIdBits.hasBit(activeTouchId)) { - const RawPointerData::Pointer& currentPointer = - mCurrentRawPointerData.pointerForId(activeTouchId); - const RawPointerData::Pointer& lastPointer = - mLastRawPointerData.pointerForId(activeTouchId); - float deltaX = (currentPointer.x - lastPointer.x) - * mPointerXMovementScale; - float deltaY = (currentPointer.y - lastPointer.y) - * mPointerYMovementScale; - - rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); - mPointerVelocityControl.move(when, &deltaX, &deltaY); - - // Move the pointer using a relative motion. - // When using spots, the hover or drag will occur at the position of the anchor spot. - mPointerController->move(deltaX, deltaY); - } else { - mPointerVelocityControl.reset(); - } - - bool down; - if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) { -#if DEBUG_GESTURES - ALOGD("Gestures: TAP_DRAG"); -#endif - down = true; - } else { -#if DEBUG_GESTURES - ALOGD("Gestures: HOVER"); -#endif - if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) { - *outFinishPreviousGesture = true; - } - mPointerGesture.activeGestureId = 0; - down = false; - } - - float x, y; - mPointerController->getPosition(&x, &y); - - mPointerGesture.currentGestureIdBits.clear(); - mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); - mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; - mPointerGesture.currentGestureProperties[0].clear(); - mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; - mPointerGesture.currentGestureProperties[0].toolType = - AMOTION_EVENT_TOOL_TYPE_FINGER; - mPointerGesture.currentGestureCoords[0].clear(); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, - down ? 1.0f : 0.0f); - - if (lastFingerCount == 0 && currentFingerCount != 0) { - mPointerGesture.resetTap(); - mPointerGesture.tapDownTime = when; - mPointerGesture.tapX = x; - mPointerGesture.tapY = y; - } - } else { - // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM) - // We need to provide feedback for each finger that goes down so we cannot wait - // for the fingers to move before deciding what to do. - // - // The ambiguous case is deciding what to do when there are two fingers down but they - // have not moved enough to determine whether they are part of a drag or part of a - // freeform gesture, or just a press or long-press at the pointer location. - // - // When there are two fingers we start with the PRESS hypothesis and we generate a - // down at the pointer location. - // - // When the two fingers move enough or when additional fingers are added, we make - // a decision to transition into SWIPE or FREEFORM mode accordingly. - ALOG_ASSERT(activeTouchId >= 0); - - bool settled = when >= mPointerGesture.firstTouchTime - + mConfig.pointerGestureMultitouchSettleInterval; - if (mPointerGesture.lastGestureMode != PointerGesture::PRESS - && mPointerGesture.lastGestureMode != PointerGesture::SWIPE - && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) { - *outFinishPreviousGesture = true; - } else if (!settled && currentFingerCount > lastFingerCount) { - // Additional pointers have gone down but not yet settled. - // Reset the gesture. -#if DEBUG_GESTURES - ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, " - "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime - + mConfig.pointerGestureMultitouchSettleInterval - when) - * 0.000001f); -#endif - *outCancelPreviousGesture = true; - } else { - // Continue previous gesture. - mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode; - } - - if (*outFinishPreviousGesture || *outCancelPreviousGesture) { - mPointerGesture.currentGestureMode = PointerGesture::PRESS; - mPointerGesture.activeGestureId = 0; - mPointerGesture.referenceIdBits.clear(); - mPointerVelocityControl.reset(); - - // Use the centroid and pointer location as the reference points for the gesture. -#if DEBUG_GESTURES - ALOGD("Gestures: Using centroid as reference for MULTITOUCH, " - "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime - + mConfig.pointerGestureMultitouchSettleInterval - when) - * 0.000001f); -#endif - mCurrentRawPointerData.getCentroidOfTouchingPointers( - &mPointerGesture.referenceTouchX, - &mPointerGesture.referenceTouchY); - mPointerController->getPosition(&mPointerGesture.referenceGestureX, - &mPointerGesture.referenceGestureY); - } - - // Clear the reference deltas for fingers not yet included in the reference calculation. - for (BitSet32 idBits(mCurrentFingerIdBits.value - & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - mPointerGesture.referenceDeltas[id].dx = 0; - mPointerGesture.referenceDeltas[id].dy = 0; - } - mPointerGesture.referenceIdBits = mCurrentFingerIdBits; - - // Add delta for all fingers and calculate a common movement delta. - float commonDeltaX = 0, commonDeltaY = 0; - BitSet32 commonIdBits(mLastFingerIdBits.value - & mCurrentFingerIdBits.value); - for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { - bool first = (idBits == commonIdBits); - uint32_t id = idBits.clearFirstMarkedBit(); - const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id); - const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id); - PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; - delta.dx += cpd.x - lpd.x; - delta.dy += cpd.y - lpd.y; - - if (first) { - commonDeltaX = delta.dx; - commonDeltaY = delta.dy; - } else { - commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx); - commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy); - } - } - - // Consider transitions from PRESS to SWIPE or MULTITOUCH. - if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) { - float dist[MAX_POINTER_ID + 1]; - int32_t distOverThreshold = 0; - for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; - dist[id] = hypotf(delta.dx * mPointerXZoomScale, - delta.dy * mPointerYZoomScale); - if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) { - distOverThreshold += 1; - } - } - - // Only transition when at least two pointers have moved further than - // the minimum distance threshold. - if (distOverThreshold >= 2) { - if (currentFingerCount > 2) { - // There are more than two pointers, switch to FREEFORM. -#if DEBUG_GESTURES - ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", - currentFingerCount); -#endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } else { - // There are exactly two pointers. - BitSet32 idBits(mCurrentFingerIdBits); - uint32_t id1 = idBits.clearFirstMarkedBit(); - uint32_t id2 = idBits.firstMarkedBit(); - const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1); - const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2); - float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y); - if (mutualDistance > mPointerGestureMaxSwipeWidth) { - // There are two pointers but they are too far apart for a SWIPE, - // switch to FREEFORM. -#if DEBUG_GESTURES - ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f", - mutualDistance, mPointerGestureMaxSwipeWidth); -#endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } else { - // There are two pointers. Wait for both pointers to start moving - // before deciding whether this is a SWIPE or FREEFORM gesture. - float dist1 = dist[id1]; - float dist2 = dist[id2]; - if (dist1 >= mConfig.pointerGestureMultitouchMinDistance - && dist2 >= mConfig.pointerGestureMultitouchMinDistance) { - // Calculate the dot product of the displacement vectors. - // When the vectors are oriented in approximately the same direction, - // the angle betweeen them is near zero and the cosine of the angle - // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2). - PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1]; - PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2]; - float dx1 = delta1.dx * mPointerXZoomScale; - float dy1 = delta1.dy * mPointerYZoomScale; - float dx2 = delta2.dx * mPointerXZoomScale; - float dy2 = delta2.dy * mPointerYZoomScale; - float dot = dx1 * dx2 + dy1 * dy2; - float cosine = dot / (dist1 * dist2); // denominator always > 0 - if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) { - // Pointers are moving in the same direction. Switch to SWIPE. -#if DEBUG_GESTURES - ALOGD("Gestures: PRESS transitioned to SWIPE, " - "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " - "cosine %0.3f >= %0.3f", - dist1, mConfig.pointerGestureMultitouchMinDistance, - dist2, mConfig.pointerGestureMultitouchMinDistance, - cosine, mConfig.pointerGestureSwipeTransitionAngleCosine); -#endif - mPointerGesture.currentGestureMode = PointerGesture::SWIPE; - } else { - // Pointers are moving in different directions. Switch to FREEFORM. -#if DEBUG_GESTURES - ALOGD("Gestures: PRESS transitioned to FREEFORM, " - "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " - "cosine %0.3f < %0.3f", - dist1, mConfig.pointerGestureMultitouchMinDistance, - dist2, mConfig.pointerGestureMultitouchMinDistance, - cosine, mConfig.pointerGestureSwipeTransitionAngleCosine); -#endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } - } - } - } - } - } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) { - // Switch from SWIPE to FREEFORM if additional pointers go down. - // Cancel previous gesture. - if (currentFingerCount > 2) { -#if DEBUG_GESTURES - ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2", - currentFingerCount); -#endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } - } - - // Move the reference points based on the overall group motion of the fingers - // except in PRESS mode while waiting for a transition to occur. - if (mPointerGesture.currentGestureMode != PointerGesture::PRESS - && (commonDeltaX || commonDeltaY)) { - for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; - delta.dx = 0; - delta.dy = 0; - } - - mPointerGesture.referenceTouchX += commonDeltaX; - mPointerGesture.referenceTouchY += commonDeltaY; - - commonDeltaX *= mPointerXMovementScale; - commonDeltaY *= mPointerYMovementScale; - - rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY); - mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); - - mPointerGesture.referenceGestureX += commonDeltaX; - mPointerGesture.referenceGestureY += commonDeltaY; - } - - // Report gestures. - if (mPointerGesture.currentGestureMode == PointerGesture::PRESS - || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) { - // PRESS or SWIPE mode. -#if DEBUG_GESTURES - ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d," - "activeGestureId=%d, currentTouchPointerCount=%d", - activeTouchId, mPointerGesture.activeGestureId, currentFingerCount); -#endif - ALOG_ASSERT(mPointerGesture.activeGestureId >= 0); - - mPointerGesture.currentGestureIdBits.clear(); - mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); - mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; - mPointerGesture.currentGestureProperties[0].clear(); - mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; - mPointerGesture.currentGestureProperties[0].toolType = - AMOTION_EVENT_TOOL_TYPE_FINGER; - mPointerGesture.currentGestureCoords[0].clear(); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, - mPointerGesture.referenceGestureX); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, - mPointerGesture.referenceGestureY); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) { - // FREEFORM mode. -#if DEBUG_GESTURES - ALOGD("Gestures: FREEFORM activeTouchId=%d," - "activeGestureId=%d, currentTouchPointerCount=%d", - activeTouchId, mPointerGesture.activeGestureId, currentFingerCount); -#endif - ALOG_ASSERT(mPointerGesture.activeGestureId >= 0); - - mPointerGesture.currentGestureIdBits.clear(); - - BitSet32 mappedTouchIdBits; - BitSet32 usedGestureIdBits; - if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) { - // Initially, assign the active gesture id to the active touch point - // if there is one. No other touch id bits are mapped yet. - if (!*outCancelPreviousGesture) { - mappedTouchIdBits.markBit(activeTouchId); - usedGestureIdBits.markBit(mPointerGesture.activeGestureId); - mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] = - mPointerGesture.activeGestureId; - } else { - mPointerGesture.activeGestureId = -1; - } - } else { - // Otherwise, assume we mapped all touches from the previous frame. - // Reuse all mappings that are still applicable. - mappedTouchIdBits.value = mLastFingerIdBits.value - & mCurrentFingerIdBits.value; - usedGestureIdBits = mPointerGesture.lastGestureIdBits; - - // Check whether we need to choose a new active gesture id because the - // current went went up. - for (BitSet32 upTouchIdBits(mLastFingerIdBits.value - & ~mCurrentFingerIdBits.value); - !upTouchIdBits.isEmpty(); ) { - uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit(); - uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId]; - if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) { - mPointerGesture.activeGestureId = -1; - break; - } - } - } - -#if DEBUG_GESTURES - ALOGD("Gestures: FREEFORM follow up " - "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, " - "activeGestureId=%d", - mappedTouchIdBits.value, usedGestureIdBits.value, - mPointerGesture.activeGestureId); -#endif - - BitSet32 idBits(mCurrentFingerIdBits); - for (uint32_t i = 0; i < currentFingerCount; i++) { - uint32_t touchId = idBits.clearFirstMarkedBit(); - uint32_t gestureId; - if (!mappedTouchIdBits.hasBit(touchId)) { - gestureId = usedGestureIdBits.markFirstUnmarkedBit(); - mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId; -#if DEBUG_GESTURES - ALOGD("Gestures: FREEFORM " - "new mapping for touch id %d -> gesture id %d", - touchId, gestureId); -#endif - } else { - gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId]; -#if DEBUG_GESTURES - ALOGD("Gestures: FREEFORM " - "existing mapping for touch id %d -> gesture id %d", - touchId, gestureId); -#endif - } - mPointerGesture.currentGestureIdBits.markBit(gestureId); - mPointerGesture.currentGestureIdToIndex[gestureId] = i; - - const RawPointerData::Pointer& pointer = - mCurrentRawPointerData.pointerForId(touchId); - float deltaX = (pointer.x - mPointerGesture.referenceTouchX) - * mPointerXZoomScale; - float deltaY = (pointer.y - mPointerGesture.referenceTouchY) - * mPointerYZoomScale; - rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); - - mPointerGesture.currentGestureProperties[i].clear(); - mPointerGesture.currentGestureProperties[i].id = gestureId; - mPointerGesture.currentGestureProperties[i].toolType = - AMOTION_EVENT_TOOL_TYPE_FINGER; - mPointerGesture.currentGestureCoords[i].clear(); - mPointerGesture.currentGestureCoords[i].setAxisValue( - AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX); - mPointerGesture.currentGestureCoords[i].setAxisValue( - AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY); - mPointerGesture.currentGestureCoords[i].setAxisValue( - AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - } - - if (mPointerGesture.activeGestureId < 0) { - mPointerGesture.activeGestureId = - mPointerGesture.currentGestureIdBits.firstMarkedBit(); -#if DEBUG_GESTURES - ALOGD("Gestures: FREEFORM new " - "activeGestureId=%d", mPointerGesture.activeGestureId); -#endif - } - } - } - - mPointerController->setButtonState(mCurrentButtonState); - -#if DEBUG_GESTURES - ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, " - "currentGestureMode=%d, currentGestureIdBits=0x%08x, " - "lastGestureMode=%d, lastGestureIdBits=0x%08x", - toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture), - mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value, - mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value); - for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - uint32_t index = mPointerGesture.currentGestureIdToIndex[id]; - const PointerProperties& properties = mPointerGesture.currentGestureProperties[index]; - const PointerCoords& coords = mPointerGesture.currentGestureCoords[index]; - ALOGD(" currentGesture[%d]: index=%d, toolType=%d, " - "x=%0.3f, y=%0.3f, pressure=%0.3f", - id, index, properties.toolType, - coords.getAxisValue(AMOTION_EVENT_AXIS_X), - coords.getAxisValue(AMOTION_EVENT_AXIS_Y), - coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); - } - for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - uint32_t index = mPointerGesture.lastGestureIdToIndex[id]; - const PointerProperties& properties = mPointerGesture.lastGestureProperties[index]; - const PointerCoords& coords = mPointerGesture.lastGestureCoords[index]; - ALOGD(" lastGesture[%d]: index=%d, toolType=%d, " - "x=%0.3f, y=%0.3f, pressure=%0.3f", - id, index, properties.toolType, - coords.getAxisValue(AMOTION_EVENT_AXIS_X), - coords.getAxisValue(AMOTION_EVENT_AXIS_Y), - coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); - } -#endif - return true; -} - -void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) { - mPointerSimple.currentCoords.clear(); - mPointerSimple.currentProperties.clear(); - - bool down, hovering; - if (!mCurrentStylusIdBits.isEmpty()) { - uint32_t id = mCurrentStylusIdBits.firstMarkedBit(); - uint32_t index = mCurrentCookedPointerData.idToIndex[id]; - float x = mCurrentCookedPointerData.pointerCoords[index].getX(); - float y = mCurrentCookedPointerData.pointerCoords[index].getY(); - mPointerController->setPosition(x, y); - - hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id); - down = !hovering; - - mPointerController->getPosition(&x, &y); - mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]); - mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); - mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); - mPointerSimple.currentProperties.id = 0; - mPointerSimple.currentProperties.toolType = - mCurrentCookedPointerData.pointerProperties[index].toolType; - } else { - down = false; - hovering = false; - } - - dispatchPointerSimple(when, policyFlags, down, hovering); -} - -void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) { - abortPointerSimple(when, policyFlags); -} - -void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) { - mPointerSimple.currentCoords.clear(); - mPointerSimple.currentProperties.clear(); - - bool down, hovering; - if (!mCurrentMouseIdBits.isEmpty()) { - uint32_t id = mCurrentMouseIdBits.firstMarkedBit(); - uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id]; - if (mLastMouseIdBits.hasBit(id)) { - uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id]; - float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x - - mLastRawPointerData.pointers[lastIndex].x) - * mPointerXMovementScale; - float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y - - mLastRawPointerData.pointers[lastIndex].y) - * mPointerYMovementScale; - - rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); - mPointerVelocityControl.move(when, &deltaX, &deltaY); - - mPointerController->move(deltaX, deltaY); - } else { - mPointerVelocityControl.reset(); - } - - down = isPointerDown(mCurrentButtonState); - hovering = !down; - - float x, y; - mPointerController->getPosition(&x, &y); - mPointerSimple.currentCoords.copyFrom( - mCurrentCookedPointerData.pointerCoords[currentIndex]); - mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); - mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); - mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, - hovering ? 0.0f : 1.0f); - mPointerSimple.currentProperties.id = 0; - mPointerSimple.currentProperties.toolType = - mCurrentCookedPointerData.pointerProperties[currentIndex].toolType; - } else { - mPointerVelocityControl.reset(); - - down = false; - hovering = false; - } - - dispatchPointerSimple(when, policyFlags, down, hovering); -} - -void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) { - abortPointerSimple(when, policyFlags); - - mPointerVelocityControl.reset(); -} - -void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, - bool down, bool hovering) { - int32_t metaState = getContext()->getGlobalMetaState(); - - if (mPointerController != NULL) { - if (down || hovering) { - mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); - mPointerController->clearSpots(); - mPointerController->setButtonState(mCurrentButtonState); - mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); - } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - } - } - - if (mPointerSimple.down && !down) { - mPointerSimple.down = false; - - // Send up. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0, - mViewport.displayId, - 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, - mOrientedXPrecision, mOrientedYPrecision, - mPointerSimple.downTime); - getListener()->notifyMotion(&args); - } - - if (mPointerSimple.hovering && !hovering) { - mPointerSimple.hovering = false; - - // Send hover exit. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0, - mViewport.displayId, - 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, - mOrientedXPrecision, mOrientedYPrecision, - mPointerSimple.downTime); - getListener()->notifyMotion(&args); - } - - if (down) { - if (!mPointerSimple.down) { - mPointerSimple.down = true; - mPointerSimple.downTime = when; - - // Send down. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0, - mViewport.displayId, - 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, - mOrientedXPrecision, mOrientedYPrecision, - mPointerSimple.downTime); - getListener()->notifyMotion(&args); - } - - // Send move. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0, - mViewport.displayId, - 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, - mOrientedXPrecision, mOrientedYPrecision, - mPointerSimple.downTime); - getListener()->notifyMotion(&args); - } - - if (hovering) { - if (!mPointerSimple.hovering) { - mPointerSimple.hovering = true; - - // Send hover enter. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0, - mViewport.displayId, - 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, - mOrientedXPrecision, mOrientedYPrecision, - mPointerSimple.downTime); - getListener()->notifyMotion(&args); - } - - // Send hover move. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0, - mViewport.displayId, - 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, - mOrientedXPrecision, mOrientedYPrecision, - mPointerSimple.downTime); - getListener()->notifyMotion(&args); - } - - if (mCurrentRawVScroll || mCurrentRawHScroll) { - float vscroll = mCurrentRawVScroll; - float hscroll = mCurrentRawHScroll; - mWheelYVelocityControl.move(when, NULL, &vscroll); - mWheelXVelocityControl.move(when, &hscroll, NULL); - - // Send scroll. - PointerCoords pointerCoords; - pointerCoords.copyFrom(mPointerSimple.currentCoords); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0, - mViewport.displayId, - 1, &mPointerSimple.currentProperties, &pointerCoords, - mOrientedXPrecision, mOrientedYPrecision, - mPointerSimple.downTime); - getListener()->notifyMotion(&args); - } - - // Save state. - if (down || hovering) { - mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords); - mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties); - } else { - mPointerSimple.reset(); - } -} - -void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) { - mPointerSimple.currentCoords.clear(); - mPointerSimple.currentProperties.clear(); - - dispatchPointerSimple(when, policyFlags, false, false); -} - -void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, - int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, - const PointerProperties* properties, const PointerCoords* coords, - const uint32_t* idToIndex, BitSet32 idBits, - int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) { - PointerCoords pointerCoords[MAX_POINTERS]; - PointerProperties pointerProperties[MAX_POINTERS]; - uint32_t pointerCount = 0; - while (!idBits.isEmpty()) { - uint32_t id = idBits.clearFirstMarkedBit(); - uint32_t index = idToIndex[id]; - pointerProperties[pointerCount].copyFrom(properties[index]); - pointerCoords[pointerCount].copyFrom(coords[index]); - - if (changedId >= 0 && id == uint32_t(changedId)) { - action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; - } - - pointerCount += 1; - } - - ALOG_ASSERT(pointerCount != 0); - - if (changedId >= 0 && pointerCount == 1) { - // Replace initial down and final up action. - // We can compare the action without masking off the changed pointer index - // because we know the index is 0. - if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) { - action = AMOTION_EVENT_ACTION_DOWN; - } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) { - action = AMOTION_EVENT_ACTION_UP; - } else { - // Can't happen. - ALOG_ASSERT(false); - } - } - - NotifyMotionArgs args(when, getDeviceId(), source, policyFlags, - action, flags, metaState, buttonState, edgeFlags, - mViewport.displayId, pointerCount, pointerProperties, pointerCoords, - xPrecision, yPrecision, downTime); - getListener()->notifyMotion(&args); -} - -bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties, - const PointerCoords* inCoords, const uint32_t* inIdToIndex, - PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex, - BitSet32 idBits) const { - bool changed = false; - while (!idBits.isEmpty()) { - uint32_t id = idBits.clearFirstMarkedBit(); - uint32_t inIndex = inIdToIndex[id]; - uint32_t outIndex = outIdToIndex[id]; - - const PointerProperties& curInProperties = inProperties[inIndex]; - const PointerCoords& curInCoords = inCoords[inIndex]; - PointerProperties& curOutProperties = outProperties[outIndex]; - PointerCoords& curOutCoords = outCoords[outIndex]; - - if (curInProperties != curOutProperties) { - curOutProperties.copyFrom(curInProperties); - changed = true; - } - - if (curInCoords != curOutCoords) { - curOutCoords.copyFrom(curInCoords); - changed = true; - } - } - return changed; -} - -void TouchInputMapper::fadePointer() { - if (mPointerController != NULL) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - } -} - -bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { - return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue - && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue; -} - -const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit( - int32_t x, int32_t y) { - size_t numVirtualKeys = mVirtualKeys.size(); - for (size_t i = 0; i < numVirtualKeys; i++) { - const VirtualKey& virtualKey = mVirtualKeys[i]; - -#if DEBUG_VIRTUAL_KEYS - ALOGD("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::assignPointerIds() { - uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount; - uint32_t lastPointerCount = mLastRawPointerData.pointerCount; - - mCurrentRawPointerData.clearIdBits(); - - if (currentPointerCount == 0) { - // No pointers to assign. - return; - } - - if (lastPointerCount == 0) { - // All pointers are new. - for (uint32_t i = 0; i < currentPointerCount; i++) { - uint32_t id = i; - mCurrentRawPointerData.pointers[i].id = id; - mCurrentRawPointerData.idToIndex[id] = i; - mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i)); - } - return; - } - - if (currentPointerCount == 1 && lastPointerCount == 1 - && mCurrentRawPointerData.pointers[0].toolType - == mLastRawPointerData.pointers[0].toolType) { - // Only one pointer and no change in count so it must have the same id as before. - uint32_t id = mLastRawPointerData.pointers[0].id; - mCurrentRawPointerData.pointers[0].id = id; - mCurrentRawPointerData.idToIndex[id] = 0; - mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0)); - return; - } - - // 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. - // The pointers must have the same tool type but it is possible for them to - // transition from hovering to touching or vice-versa while retaining the same id. - 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++) { - const RawPointerData::Pointer& currentPointer = - mCurrentRawPointerData.pointers[currentPointerIndex]; - const RawPointerData::Pointer& lastPointer = - mLastRawPointerData.pointers[lastPointerIndex]; - if (currentPointer.toolType == lastPointer.toolType) { - int64_t deltaX = currentPointer.x - lastPointer.x; - int64_t deltaY = currentPointer.y - lastPointer.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 - ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize); - for (size_t i = 0; i < heapSize; i++) { - ALOGD(" 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); heapSize > 0 && i > 0; i--) { - while (heapSize > 0) { - 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). - 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 - ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize); - for (size_t i = 0; i < heapSize; i++) { - ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld", - i, heap[i].currentPointerIndex, heap[i].lastPointerIndex, - heap[i].distance); - } -#endif - } - - heapSize -= 1; - - 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 = mLastRawPointerData.pointers[lastPointerIndex].id; - mCurrentRawPointerData.pointers[currentPointerIndex].id = id; - mCurrentRawPointerData.idToIndex[id] = currentPointerIndex; - mCurrentRawPointerData.markIdBit(id, - mCurrentRawPointerData.isHovering(currentPointerIndex)); - usedIdBits.markBit(id); - -#if DEBUG_POINTER_ASSIGNMENT - ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld", - lastPointerIndex, currentPointerIndex, id, heap[0].distance); -#endif - break; - } - } - - // Assign fresh ids to pointers that were not matched in the process. - for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) { - uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit(); - uint32_t id = usedIdBits.markFirstUnmarkedBit(); - - mCurrentRawPointerData.pointers[currentPointerIndex].id = id; - mCurrentRawPointerData.idToIndex[id] = currentPointerIndex; - mCurrentRawPointerData.markIdBit(id, - mCurrentRawPointerData.isHovering(currentPointerIndex)); - -#if DEBUG_POINTER_ASSIGNMENT - ALOGD("assignPointerIds - assigned: cur=%d, id=%d", - currentPointerIndex, id); -#endif - } -} - -int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { - if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) { - return AKEY_STATE_VIRTUAL; - } - - size_t numVirtualKeys = mVirtualKeys.size(); - for (size_t i = 0; i < numVirtualKeys; i++) { - const VirtualKey& virtualKey = mVirtualKeys[i]; - if (virtualKey.keyCode == keyCode) { - return AKEY_STATE_UP; - } - } - - return AKEY_STATE_UNKNOWN; -} - -int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { - if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) { - return AKEY_STATE_VIRTUAL; - } - - size_t numVirtualKeys = mVirtualKeys.size(); - for (size_t i = 0; i < numVirtualKeys; i++) { - const VirtualKey& virtualKey = mVirtualKeys[i]; - if (virtualKey.scanCode == scanCode) { - return AKEY_STATE_UP; - } - } - - return AKEY_STATE_UNKNOWN; -} - -bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, - const int32_t* keyCodes, uint8_t* outFlags) { - size_t numVirtualKeys = mVirtualKeys.size(); - for (size_t i = 0; i < numVirtualKeys; i++) { - const VirtualKey& virtualKey = mVirtualKeys[i]; - - for (size_t i = 0; i < numCodes; i++) { - if (virtualKey.keyCode == keyCodes[i]) { - outFlags[i] = 1; - } - } - } - - return true; -} - - -// --- SingleTouchInputMapper --- - -SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) : - TouchInputMapper(device) { -} - -SingleTouchInputMapper::~SingleTouchInputMapper() { -} - -void SingleTouchInputMapper::reset(nsecs_t when) { - mSingleTouchMotionAccumulator.reset(getDevice()); - - TouchInputMapper::reset(when); -} - -void SingleTouchInputMapper::process(const RawEvent* rawEvent) { - TouchInputMapper::process(rawEvent); - - mSingleTouchMotionAccumulator.process(rawEvent); -} - -void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) { - if (mTouchButtonAccumulator.isToolActive()) { - mCurrentRawPointerData.pointerCount = 1; - mCurrentRawPointerData.idToIndex[0] = 0; - - bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE - && (mTouchButtonAccumulator.isHovering() - || (mRawPointerAxes.pressure.valid - && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0)); - mCurrentRawPointerData.markIdBit(0, isHovering); - - RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0]; - outPointer.id = 0; - outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX(); - outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY(); - outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure(); - outPointer.touchMajor = 0; - outPointer.touchMinor = 0; - outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth(); - outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth(); - outPointer.orientation = 0; - outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance(); - outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX(); - outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY(); - outPointer.toolType = mTouchButtonAccumulator.getToolType(); - if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { - outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; - } - outPointer.isHovering = isHovering; - } -} - -void SingleTouchInputMapper::configureRawPointerAxes() { - TouchInputMapper::configureRawPointerAxes(); - - getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x); - getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y); - getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure); - getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor); - getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance); - getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX); - getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY); -} - -bool SingleTouchInputMapper::hasStylus() const { - return mTouchButtonAccumulator.hasStylus(); -} - - -// --- MultiTouchInputMapper --- - -MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) : - TouchInputMapper(device) { -} - -MultiTouchInputMapper::~MultiTouchInputMapper() { -} - -void MultiTouchInputMapper::reset(nsecs_t when) { - mMultiTouchMotionAccumulator.reset(getDevice()); - - mPointerIdBits.clear(); - - TouchInputMapper::reset(when); -} - -void MultiTouchInputMapper::process(const RawEvent* rawEvent) { - TouchInputMapper::process(rawEvent); - - mMultiTouchMotionAccumulator.process(rawEvent); -} - -void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) { - size_t inCount = mMultiTouchMotionAccumulator.getSlotCount(); - size_t outCount = 0; - BitSet32 newPointerIdBits; - - for (size_t inIndex = 0; inIndex < inCount; inIndex++) { - const MultiTouchMotionAccumulator::Slot* inSlot = - mMultiTouchMotionAccumulator.getSlot(inIndex); - if (!inSlot->isInUse()) { - continue; - } - - if (outCount >= MAX_POINTERS) { -#if DEBUG_POINTERS - ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; " - "ignoring the rest.", - getDeviceName().string(), MAX_POINTERS); -#endif - break; // too many fingers! - } - - RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount]; - outPointer.x = inSlot->getX(); - outPointer.y = inSlot->getY(); - outPointer.pressure = inSlot->getPressure(); - outPointer.touchMajor = inSlot->getTouchMajor(); - outPointer.touchMinor = inSlot->getTouchMinor(); - outPointer.toolMajor = inSlot->getToolMajor(); - outPointer.toolMinor = inSlot->getToolMinor(); - outPointer.orientation = inSlot->getOrientation(); - outPointer.distance = inSlot->getDistance(); - outPointer.tiltX = 0; - outPointer.tiltY = 0; - - outPointer.toolType = inSlot->getToolType(); - if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { - outPointer.toolType = mTouchButtonAccumulator.getToolType(); - if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { - outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; - } - } - - bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE - && (mTouchButtonAccumulator.isHovering() - || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0)); - outPointer.isHovering = isHovering; - - // Assign pointer id using tracking id if available. - if (*outHavePointerIds) { - int32_t trackingId = inSlot->getTrackingId(); - int32_t id = -1; - if (trackingId >= 0) { - for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) { - uint32_t n = idBits.clearFirstMarkedBit(); - if (mPointerTrackingIdMap[n] == trackingId) { - id = n; - } - } - - if (id < 0 && !mPointerIdBits.isFull()) { - id = mPointerIdBits.markFirstUnmarkedBit(); - mPointerTrackingIdMap[id] = trackingId; - } - } - if (id < 0) { - *outHavePointerIds = false; - mCurrentRawPointerData.clearIdBits(); - newPointerIdBits.clear(); - } else { - outPointer.id = id; - mCurrentRawPointerData.idToIndex[id] = outCount; - mCurrentRawPointerData.markIdBit(id, isHovering); - newPointerIdBits.markBit(id); - } - } - - outCount += 1; - } - - mCurrentRawPointerData.pointerCount = outCount; - mPointerIdBits = newPointerIdBits; - - mMultiTouchMotionAccumulator.finishSync(); -} - -void MultiTouchInputMapper::configureRawPointerAxes() { - TouchInputMapper::configureRawPointerAxes(); - - getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x); - getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y); - getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor); - getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor); - getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor); - getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor); - getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation); - getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure); - getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance); - getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId); - getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot); - - if (mRawPointerAxes.trackingId.valid - && mRawPointerAxes.slot.valid - && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) { - size_t slotCount = mRawPointerAxes.slot.maxValue + 1; - if (slotCount > MAX_SLOTS) { - ALOGW("MultiTouch Device %s reported %d slots but the framework " - "only supports a maximum of %d slots at this time.", - getDeviceName().string(), slotCount, MAX_SLOTS); - slotCount = MAX_SLOTS; - } - mMultiTouchMotionAccumulator.configure(getDevice(), - slotCount, true /*usingSlotsProtocol*/); - } else { - mMultiTouchMotionAccumulator.configure(getDevice(), - MAX_POINTERS, false /*usingSlotsProtocol*/); - } -} - -bool MultiTouchInputMapper::hasStylus() const { - return mMultiTouchMotionAccumulator.hasStylus() - || mTouchButtonAccumulator.hasStylus(); -} - - -// --- JoystickInputMapper --- - -JoystickInputMapper::JoystickInputMapper(InputDevice* device) : - InputMapper(device) { -} - -JoystickInputMapper::~JoystickInputMapper() { -} - -uint32_t JoystickInputMapper::getSources() { - return AINPUT_SOURCE_JOYSTICK; -} - -void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) { - InputMapper::populateDeviceInfo(info); - - for (size_t i = 0; i < mAxes.size(); i++) { - const Axis& axis = mAxes.valueAt(i); - addMotionRange(axis.axisInfo.axis, axis, info); - - if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { - addMotionRange(axis.axisInfo.highAxis, axis, info); - - } - } -} - -void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis, - InputDeviceInfo* info) { - info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK, - axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution); - /* In order to ease the transition for developers from using the old axes - * to the newer, more semantically correct axes, we'll continue to register - * the old axes as duplicates of their corresponding new ones. */ - int32_t compatAxis = getCompatAxis(axisId); - if (compatAxis >= 0) { - info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK, - axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution); - } -} - -/* A mapping from axes the joystick actually has to the axes that should be - * artificially created for compatibility purposes. - * Returns -1 if no compatibility axis is needed. */ -int32_t JoystickInputMapper::getCompatAxis(int32_t axis) { - switch(axis) { - case AMOTION_EVENT_AXIS_LTRIGGER: - return AMOTION_EVENT_AXIS_BRAKE; - case AMOTION_EVENT_AXIS_RTRIGGER: - return AMOTION_EVENT_AXIS_GAS; - } - return -1; -} - -void JoystickInputMapper::dump(String8& dump) { - dump.append(INDENT2 "Joystick Input Mapper:\n"); - - dump.append(INDENT3 "Axes:\n"); - size_t numAxes = mAxes.size(); - for (size_t i = 0; i < numAxes; i++) { - const Axis& axis = mAxes.valueAt(i); - const char* label = getAxisLabel(axis.axisInfo.axis); - if (label) { - dump.appendFormat(INDENT4 "%s", label); - } else { - dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis); - } - if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { - label = getAxisLabel(axis.axisInfo.highAxis); - if (label) { - dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue); - } else { - dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis, - axis.axisInfo.splitValue); - } - } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) { - dump.append(" (invert)"); - } - - dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n", - axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution); - dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, " - "highScale=%0.5f, highOffset=%0.5f\n", - axis.scale, axis.offset, axis.highScale, axis.highOffset); - dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, " - "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n", - mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue, - axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution); - } -} - -void JoystickInputMapper::configure(nsecs_t when, - const InputReaderConfiguration* config, uint32_t changes) { - InputMapper::configure(when, config, changes); - - if (!changes) { // first time only - // Collect all axes. - for (int32_t abs = 0; abs <= ABS_MAX; abs++) { - if (!(getAbsAxisUsage(abs, getDevice()->getClasses()) - & INPUT_DEVICE_CLASS_JOYSTICK)) { - continue; // axis must be claimed by a different device - } - - RawAbsoluteAxisInfo rawAxisInfo; - getAbsoluteAxisInfo(abs, &rawAxisInfo); - if (rawAxisInfo.valid) { - // Map axis. - AxisInfo axisInfo; - bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo); - if (!explicitlyMapped) { - // Axis is not explicitly mapped, will choose a generic axis later. - axisInfo.mode = AxisInfo::MODE_NORMAL; - axisInfo.axis = -1; - } - - // Apply flat override. - int32_t rawFlat = axisInfo.flatOverride < 0 - ? rawAxisInfo.flat : axisInfo.flatOverride; - - // Calculate scaling factors and limits. - Axis axis; - if (axisInfo.mode == AxisInfo::MODE_SPLIT) { - float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue); - float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue); - axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, - scale, 0.0f, highScale, 0.0f, - 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale, - rawAxisInfo.resolution * scale); - } else if (isCenteredAxis(axisInfo.axis)) { - float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); - float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale; - axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, - scale, offset, scale, offset, - -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale, - rawAxisInfo.resolution * scale); - } else { - float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); - axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, - scale, 0.0f, scale, 0.0f, - 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale, - rawAxisInfo.resolution * scale); - } - - // To eliminate noise while the joystick is at rest, filter out small variations - // in axis values up front. - axis.filter = axis.flat * 0.25f; - - mAxes.add(abs, axis); - } - } - - // If there are too many axes, start dropping them. - // Prefer to keep explicitly mapped axes. - if (mAxes.size() > PointerCoords::MAX_AXES) { - ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.", - getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES); - pruneAxes(true); - pruneAxes(false); - } - - // Assign generic axis ids to remaining axes. - int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1; - size_t numAxes = mAxes.size(); - for (size_t i = 0; i < numAxes; i++) { - Axis& axis = mAxes.editValueAt(i); - if (axis.axisInfo.axis < 0) { - while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16 - && haveAxis(nextGenericAxisId)) { - nextGenericAxisId += 1; - } - - if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) { - axis.axisInfo.axis = nextGenericAxisId; - nextGenericAxisId += 1; - } else { - ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids " - "have already been assigned to other axes.", - getDeviceName().string(), mAxes.keyAt(i)); - mAxes.removeItemsAt(i--); - numAxes -= 1; - } - } - } - } -} - -bool JoystickInputMapper::haveAxis(int32_t axisId) { - size_t numAxes = mAxes.size(); - for (size_t i = 0; i < numAxes; i++) { - const Axis& axis = mAxes.valueAt(i); - if (axis.axisInfo.axis == axisId - || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT - && axis.axisInfo.highAxis == axisId)) { - return true; - } - } - return false; -} - -void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) { - size_t i = mAxes.size(); - while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) { - if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) { - continue; - } - ALOGI("Discarding joystick '%s' axis %d because there are too many axes.", - getDeviceName().string(), mAxes.keyAt(i)); - mAxes.removeItemsAt(i); - } -} - -bool JoystickInputMapper::isCenteredAxis(int32_t axis) { - switch (axis) { - case AMOTION_EVENT_AXIS_X: - case AMOTION_EVENT_AXIS_Y: - case AMOTION_EVENT_AXIS_Z: - case AMOTION_EVENT_AXIS_RX: - case AMOTION_EVENT_AXIS_RY: - case AMOTION_EVENT_AXIS_RZ: - case AMOTION_EVENT_AXIS_HAT_X: - case AMOTION_EVENT_AXIS_HAT_Y: - case AMOTION_EVENT_AXIS_ORIENTATION: - case AMOTION_EVENT_AXIS_RUDDER: - case AMOTION_EVENT_AXIS_WHEEL: - return true; - default: - return false; - } -} - -void JoystickInputMapper::reset(nsecs_t when) { - // Recenter all axes. - size_t numAxes = mAxes.size(); - for (size_t i = 0; i < numAxes; i++) { - Axis& axis = mAxes.editValueAt(i); - axis.resetValue(); - } - - InputMapper::reset(when); -} - -void JoystickInputMapper::process(const RawEvent* rawEvent) { - switch (rawEvent->type) { - case EV_ABS: { - ssize_t index = mAxes.indexOfKey(rawEvent->code); - if (index >= 0) { - Axis& axis = mAxes.editValueAt(index); - float newValue, highNewValue; - switch (axis.axisInfo.mode) { - case AxisInfo::MODE_INVERT: - newValue = (axis.rawAxisInfo.maxValue - rawEvent->value) - * axis.scale + axis.offset; - highNewValue = 0.0f; - break; - case AxisInfo::MODE_SPLIT: - if (rawEvent->value < axis.axisInfo.splitValue) { - newValue = (axis.axisInfo.splitValue - rawEvent->value) - * axis.scale + axis.offset; - highNewValue = 0.0f; - } else if (rawEvent->value > axis.axisInfo.splitValue) { - newValue = 0.0f; - highNewValue = (rawEvent->value - axis.axisInfo.splitValue) - * axis.highScale + axis.highOffset; - } else { - newValue = 0.0f; - highNewValue = 0.0f; - } - break; - default: - newValue = rawEvent->value * axis.scale + axis.offset; - highNewValue = 0.0f; - break; - } - axis.newValue = newValue; - axis.highNewValue = highNewValue; - } - break; - } - - case EV_SYN: - switch (rawEvent->code) { - case SYN_REPORT: - sync(rawEvent->when, false /*force*/); - break; - } - break; - } -} - -void JoystickInputMapper::sync(nsecs_t when, bool force) { - if (!filterAxes(force)) { - return; - } - - int32_t metaState = mContext->getGlobalMetaState(); - int32_t buttonState = 0; - - PointerProperties pointerProperties; - pointerProperties.clear(); - pointerProperties.id = 0; - pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN; - - PointerCoords pointerCoords; - pointerCoords.clear(); - - size_t numAxes = mAxes.size(); - for (size_t i = 0; i < numAxes; i++) { - const Axis& axis = mAxes.valueAt(i); - setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue); - if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { - setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis, - axis.highCurrentValue); - } - } - - // Moving a joystick axis should not wake the device because joysticks can - // be fairly noisy even when not in use. On the other hand, pushing a gamepad - // button will likely wake the device. - // TODO: Use the input device configuration to control this behavior more finely. - uint32_t policyFlags = 0; - - NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags, - AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0); - getListener()->notifyMotion(&args); -} - -void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords, - int32_t axis, float value) { - pointerCoords->setAxisValue(axis, value); - /* In order to ease the transition for developers from using the old axes - * to the newer, more semantically correct axes, we'll continue to produce - * values for the old axes as mirrors of the value of their corresponding - * new axes. */ - int32_t compatAxis = getCompatAxis(axis); - if (compatAxis >= 0) { - pointerCoords->setAxisValue(compatAxis, value); - } -} - -bool JoystickInputMapper::filterAxes(bool force) { - bool atLeastOneSignificantChange = force; - size_t numAxes = mAxes.size(); - for (size_t i = 0; i < numAxes; i++) { - Axis& axis = mAxes.editValueAt(i); - if (force || hasValueChangedSignificantly(axis.filter, - axis.newValue, axis.currentValue, axis.min, axis.max)) { - axis.currentValue = axis.newValue; - atLeastOneSignificantChange = true; - } - if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { - if (force || hasValueChangedSignificantly(axis.filter, - axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) { - axis.highCurrentValue = axis.highNewValue; - atLeastOneSignificantChange = true; - } - } - } - return atLeastOneSignificantChange; -} - -bool JoystickInputMapper::hasValueChangedSignificantly( - float filter, float newValue, float currentValue, float min, float max) { - if (newValue != currentValue) { - // Filter out small changes in value unless the value is converging on the axis - // bounds or center point. This is intended to reduce the amount of information - // sent to applications by particularly noisy joysticks (such as PS3). - if (fabs(newValue - currentValue) > filter - || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min) - || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max) - || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) { - return true; - } - } - return false; -} - -bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange( - float filter, float newValue, float currentValue, float thresholdValue) { - float newDistance = fabs(newValue - thresholdValue); - if (newDistance < filter) { - float oldDistance = fabs(currentValue - thresholdValue); - if (newDistance < oldDistance) { - return true; - } - } - return false; -} - -} // namespace android diff --git a/widget/gonk/libui/InputReader.h b/widget/gonk/libui/InputReader.h deleted file mode 100644 index 5c790fdb8..000000000 --- a/widget/gonk/libui/InputReader.h +++ /dev/null @@ -1,1811 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UI_INPUT_READER_H -#define _UI_INPUT_READER_H - -#include "EventHub.h" -#include "PointerController.h" -#include "InputListener.h" - -#include "Input.h" -#include "VelocityControl.h" -#include "VelocityTracker.h" -#include <utils/KeyedVector.h> -#include <utils/threads.h> -#include <utils/Timers.h> -#include <utils/RefBase.h> -#include <utils/String8.h> -#include <utils/BitSet.h> - -#include <stddef.h> -#include <unistd.h> - -// Maximum supported size of a vibration pattern. -// Must be at least 2. -#define MAX_VIBRATE_PATTERN_SIZE 100 - -// Maximum allowable delay value in a vibration pattern before -// which the delay will be truncated. -#define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL) - -namespace android { - -class InputDevice; -class InputMapper; - -/* - * Describes how coordinates are mapped on a physical display. - * See com.android.server.display.DisplayViewport. - */ -struct DisplayViewport { - int32_t displayId; // -1 if invalid - int32_t orientation; - int32_t logicalLeft; - int32_t logicalTop; - int32_t logicalRight; - int32_t logicalBottom; - int32_t physicalLeft; - int32_t physicalTop; - int32_t physicalRight; - int32_t physicalBottom; - int32_t deviceWidth; - int32_t deviceHeight; - - DisplayViewport() : - displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0), - logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0), - physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0), - deviceWidth(0), deviceHeight(0) { - } - - bool operator==(const DisplayViewport& other) const { - return displayId == other.displayId - && orientation == other.orientation - && logicalLeft == other.logicalLeft - && logicalTop == other.logicalTop - && logicalRight == other.logicalRight - && logicalBottom == other.logicalBottom - && physicalLeft == other.physicalLeft - && physicalTop == other.physicalTop - && physicalRight == other.physicalRight - && physicalBottom == other.physicalBottom - && deviceWidth == other.deviceWidth - && deviceHeight == other.deviceHeight; - } - - bool operator!=(const DisplayViewport& other) const { - return !(*this == other); - } - - inline bool isValid() const { - return displayId >= 0; - } - - void setNonDisplayViewport(int32_t width, int32_t height) { - displayId = ADISPLAY_ID_NONE; - orientation = DISPLAY_ORIENTATION_0; - logicalLeft = 0; - logicalTop = 0; - logicalRight = width; - logicalBottom = height; - physicalLeft = 0; - physicalTop = 0; - physicalRight = width; - physicalBottom = height; - deviceWidth = width; - deviceHeight = height; - } -}; - -/* - * Input reader configuration. - * - * Specifies various options that modify the behavior of the input reader. - */ -struct InputReaderConfiguration { - // Describes changes that have occurred. - enum { - // The pointer speed changed. - CHANGE_POINTER_SPEED = 1 << 0, - - // The pointer gesture control changed. - CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1, - - // The display size or orientation changed. - CHANGE_DISPLAY_INFO = 1 << 2, - - // The visible touches option changed. - CHANGE_SHOW_TOUCHES = 1 << 3, - - // The keyboard layouts must be reloaded. - CHANGE_KEYBOARD_LAYOUTS = 1 << 4, - - // The device name alias supplied by the may have changed for some devices. - CHANGE_DEVICE_ALIAS = 1 << 5, - - // All devices must be reopened. - CHANGE_MUST_REOPEN = 1 << 31, - }; - - // Gets the amount of time to disable virtual keys after the screen is touched - // in order to filter out accidental virtual key presses due to swiping gestures - // or taps near the edge of the display. May be 0 to disable the feature. - nsecs_t virtualKeyQuietTime; - - // The excluded device names for the platform. - // Devices with these names will be ignored. - Vector<String8> excludedDeviceNames; - - // Velocity control parameters for mouse pointer movements. - VelocityControlParameters pointerVelocityControlParameters; - - // Velocity control parameters for mouse wheel movements. - VelocityControlParameters wheelVelocityControlParameters; - - // True if pointer gestures are enabled. - bool pointerGesturesEnabled; - - // Quiet time between certain pointer gesture transitions. - // Time to allow for all fingers or buttons to settle into a stable state before - // starting a new gesture. - nsecs_t pointerGestureQuietInterval; - - // The minimum speed that a pointer must travel for us to consider switching the active - // touch pointer to it during a drag. This threshold is set to avoid switching due - // to noise from a finger resting on the touch pad (perhaps just pressing it down). - float pointerGestureDragMinSwitchSpeed; // in pixels per second - - // Tap gesture delay time. - // The time between down and up must be less than this to be considered a tap. - nsecs_t pointerGestureTapInterval; - - // Tap drag gesture delay time. - // The time between the previous tap's up and the next down must be less than - // this to be considered a drag. Otherwise, the previous tap is finished and a - // new tap begins. - // - // Note that the previous tap will be held down for this entire duration so this - // interval must be shorter than the long press timeout. - nsecs_t pointerGestureTapDragInterval; - - // The distance in pixels that the pointer is allowed to move from initial down - // to up and still be called a tap. - float pointerGestureTapSlop; // in pixels - - // Time after the first touch points go down to settle on an initial centroid. - // This is intended to be enough time to handle cases where the user puts down two - // fingers at almost but not quite exactly the same time. - nsecs_t pointerGestureMultitouchSettleInterval; - - // The transition from PRESS to SWIPE or FREEFORM gesture mode is made when - // at least two pointers have moved at least this far from their starting place. - float pointerGestureMultitouchMinDistance; // in pixels - - // The transition from PRESS to SWIPE gesture mode can only occur when the - // cosine of the angle between the two vectors is greater than or equal to than this value - // which indicates that the vectors are oriented in the same direction. - // When the vectors are oriented in the exactly same direction, the cosine is 1.0. - // (In exactly opposite directions, the cosine is -1.0.) - float pointerGestureSwipeTransitionAngleCosine; - - // The transition from PRESS to SWIPE gesture mode can only occur when the - // fingers are no more than this far apart relative to the diagonal size of - // the touch pad. For example, a ratio of 0.5 means that the fingers must be - // no more than half the diagonal size of the touch pad apart. - float pointerGestureSwipeMaxWidthRatio; - - // The gesture movement speed factor relative to the size of the display. - // Movement speed applies when the fingers are moving in the same direction. - // Without acceleration, a full swipe of the touch pad diagonal in movement mode - // will cover this portion of the display diagonal. - float pointerGestureMovementSpeedRatio; - - // The gesture zoom speed factor relative to the size of the display. - // Zoom speed applies when the fingers are mostly moving relative to each other - // to execute a scale gesture or similar. - // Without acceleration, a full swipe of the touch pad diagonal in zoom mode - // will cover this portion of the display diagonal. - float pointerGestureZoomSpeedRatio; - - // True to show the location of touches on the touch screen as spots. - bool showTouches; - - InputReaderConfiguration() : - virtualKeyQuietTime(0), - pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f), - wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f), - pointerGesturesEnabled(true), - pointerGestureQuietInterval(100 * 1000000LL), // 100 ms - pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second - pointerGestureTapInterval(150 * 1000000LL), // 150 ms - pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms - pointerGestureTapSlop(10.0f), // 10 pixels - pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms - pointerGestureMultitouchMinDistance(15), // 15 pixels - pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees - pointerGestureSwipeMaxWidthRatio(0.25f), - pointerGestureMovementSpeedRatio(0.8f), - pointerGestureZoomSpeedRatio(0.3f), - showTouches(false) { } - - bool getDisplayInfo(bool external, DisplayViewport* outViewport) const; - void setDisplayInfo(bool external, const DisplayViewport& viewport); - -private: - DisplayViewport mInternalDisplay; - DisplayViewport mExternalDisplay; -}; - - -/* - * Input reader policy interface. - * - * The input reader policy is used by the input reader to interact with the Window Manager - * and other system components. - * - * The actual implementation is partially supported by callbacks into the DVM - * via JNI. This interface is also mocked in the unit tests. - * - * These methods must NOT re-enter the input reader since they may be called while - * holding the input reader lock. - */ -class InputReaderPolicyInterface : public virtual RefBase { -protected: - InputReaderPolicyInterface() { } - virtual ~InputReaderPolicyInterface() { } - -public: - /* Gets the input reader configuration. */ - virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0; - - /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */ - virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0; - - /* Notifies the input reader policy that some input devices have changed - * and provides information about all current input devices. - */ - virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) = 0; - - /* Gets the keyboard layout for a particular input device. */ - virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor) = 0; - - /* Gets a user-supplied alias for a particular input device, or an empty string if none. */ - virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) = 0; -}; - - -/* Processes raw input events and sends cooked event data to an input listener. */ -class InputReaderInterface : public virtual RefBase { -protected: - InputReaderInterface() { } - virtual ~InputReaderInterface() { } - -public: - /* Dumps the state of the input reader. - * - * This method may be called on any thread (usually by the input manager). */ - virtual void dump(String8& dump) = 0; - - /* Called by the heatbeat to ensures that the reader has not deadlocked. */ - virtual void monitor() = 0; - - /* Runs a single iteration of the processing loop. - * Nominally reads and processes one incoming message from the EventHub. - * - * This method should be called on the input reader thread. - */ - virtual void loopOnce() = 0; - - /* Gets information about all input devices. - * - * This method may be called on any thread (usually by the input manager). - */ - virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices) = 0; - - /* Query current input state. */ - virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, - int32_t scanCode) = 0; - virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, - int32_t keyCode) = 0; - virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, - int32_t sw) = 0; - - /* Determine whether physical keys exist for the given framework-domain key codes. */ - virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, - size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0; - - /* Requests that a reconfiguration of all input devices. - * The changes flag is a bitfield that indicates what has changed and whether - * the input devices must all be reopened. */ - virtual void requestRefreshConfiguration(uint32_t changes) = 0; - - /* Controls the vibrator of a particular input device. */ - virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, - ssize_t repeat, int32_t token) = 0; - virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0; -}; - - -/* Internal interface used by individual input devices to access global input device state - * and parameters maintained by the input reader. - */ -class InputReaderContext { -public: - InputReaderContext() { } - virtual ~InputReaderContext() { } - - virtual void updateGlobalMetaState() = 0; - virtual int32_t getGlobalMetaState() = 0; - - virtual void disableVirtualKeysUntil(nsecs_t time) = 0; - virtual bool shouldDropVirtualKey(nsecs_t now, - InputDevice* device, int32_t keyCode, int32_t scanCode) = 0; - - virtual void fadePointer() = 0; - - virtual void requestTimeoutAtTime(nsecs_t when) = 0; - virtual int32_t bumpGeneration() = 0; - - virtual InputReaderPolicyInterface* getPolicy() = 0; - virtual InputListenerInterface* getListener() = 0; - virtual EventHubInterface* getEventHub() = 0; -}; - - -/* The input reader reads raw event data from the event hub and processes it into input events - * that it sends to the input listener. Some functions of the input reader, such as early - * event filtering in low power states, are controlled by a separate policy object. - * - * The InputReader owns a collection of InputMappers. Most of the work it does happens - * on the input reader thread but the InputReader can receive queries from other system - * components running on arbitrary threads. To keep things manageable, the InputReader - * uses a single Mutex to guard its state. The Mutex may be held while calling into the - * EventHub or the InputReaderPolicy but it is never held while calling into the - * InputListener. - */ -class InputReader : public InputReaderInterface { -public: - InputReader(const sp<EventHubInterface>& eventHub, - const sp<InputReaderPolicyInterface>& policy, - const sp<InputListenerInterface>& listener); - virtual ~InputReader(); - - virtual void dump(String8& dump); - virtual void monitor(); - - virtual void loopOnce(); - - virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices); - - virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, - int32_t scanCode); - virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, - int32_t keyCode); - virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, - int32_t sw); - - virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, - size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags); - - virtual void requestRefreshConfiguration(uint32_t changes); - - virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, - ssize_t repeat, int32_t token); - virtual void cancelVibrate(int32_t deviceId, int32_t token); - -protected: - // These members are protected so they can be instrumented by test cases. - virtual InputDevice* createDeviceLocked(int32_t deviceId, - const InputDeviceIdentifier& identifier, uint32_t classes); - - class ContextImpl : public InputReaderContext { - InputReader* mReader; - - public: - ContextImpl(InputReader* reader); - - virtual void updateGlobalMetaState(); - virtual int32_t getGlobalMetaState(); - virtual void disableVirtualKeysUntil(nsecs_t time); - virtual bool shouldDropVirtualKey(nsecs_t now, - InputDevice* device, int32_t keyCode, int32_t scanCode); - virtual void fadePointer(); - virtual void requestTimeoutAtTime(nsecs_t when); - virtual int32_t bumpGeneration(); - virtual InputReaderPolicyInterface* getPolicy(); - virtual InputListenerInterface* getListener(); - virtual EventHubInterface* getEventHub(); - } mContext; - - friend class ContextImpl; - -private: - Mutex mLock; - - Condition mReaderIsAliveCondition; - - sp<EventHubInterface> mEventHub; - sp<InputReaderPolicyInterface> mPolicy; - sp<QueuedInputListener> mQueuedListener; - - InputReaderConfiguration mConfig; - - // The event queue. - static const int EVENT_BUFFER_SIZE = 256; - RawEvent mEventBuffer[EVENT_BUFFER_SIZE]; - - KeyedVector<int32_t, InputDevice*> mDevices; - - // low-level input event decoding and device management - void processEventsLocked(const RawEvent* rawEvents, size_t count); - - void addDeviceLocked(nsecs_t when, int32_t deviceId); - void removeDeviceLocked(nsecs_t when, int32_t deviceId); - void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count); - void timeoutExpiredLocked(nsecs_t when); - - void handleConfigurationChangedLocked(nsecs_t when); - - int32_t mGlobalMetaState; - void updateGlobalMetaStateLocked(); - int32_t getGlobalMetaStateLocked(); - - void fadePointerLocked(); - - int32_t mGeneration; - int32_t bumpGenerationLocked(); - - void getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices); - - nsecs_t mDisableVirtualKeysTimeout; - void disableVirtualKeysUntilLocked(nsecs_t time); - bool shouldDropVirtualKeyLocked(nsecs_t now, - InputDevice* device, int32_t keyCode, int32_t scanCode); - - nsecs_t mNextTimeout; - void requestTimeoutAtTimeLocked(nsecs_t when); - - uint32_t mConfigurationChangesToRefresh; - void refreshConfigurationLocked(uint32_t changes); - - // state queries - typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code); - int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code, - GetStateFunc getStateFunc); - bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes, - const int32_t* keyCodes, uint8_t* outFlags); -}; - - -/* Reads raw events from the event hub and processes them, endlessly. */ -class InputReaderThread : public Thread { -public: - InputReaderThread(const sp<InputReaderInterface>& reader); - virtual ~InputReaderThread(); - -private: - uint32_t mFoo; - sp<InputReaderInterface> mReader; - - virtual bool threadLoop(); -}; - - -/* Represents the state of a single input device. */ -class InputDevice { -public: - InputDevice(InputReaderContext* context, int32_t id, int32_t generation, - const InputDeviceIdentifier& identifier, uint32_t classes); - ~InputDevice(); - - inline InputReaderContext* getContext() { return mContext; } - inline int32_t getId() { return mId; } - inline int32_t getGeneration() { return mGeneration; } - inline const String8& getName() { return mIdentifier.name; } - inline uint32_t getClasses() { return mClasses; } - inline uint32_t getSources() { return mSources; } - - inline bool isExternal() { return mIsExternal; } - inline void setExternal(bool external) { mIsExternal = external; } - - inline bool isIgnored() { return mMappers.isEmpty(); } - - void dump(String8& dump); - void addMapper(InputMapper* mapper); - void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); - void reset(nsecs_t when); - void process(const RawEvent* rawEvents, size_t count); - void timeoutExpired(nsecs_t when); - - void getDeviceInfo(InputDeviceInfo* outDeviceInfo); - int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); - int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); - int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); - bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, - const int32_t* keyCodes, uint8_t* outFlags); - void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token); - void cancelVibrate(int32_t token); - - int32_t getMetaState(); - - void fadePointer(); - - void bumpGeneration(); - - void notifyReset(nsecs_t when); - - inline const PropertyMap& getConfiguration() { return mConfiguration; } - inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } - - bool hasKey(int32_t code) { - return getEventHub()->hasScanCode(mId, code); - } - - bool hasAbsoluteAxis(int32_t code) { - RawAbsoluteAxisInfo info; - getEventHub()->getAbsoluteAxisInfo(mId, code, &info); - return info.valid; - } - - bool isKeyPressed(int32_t code) { - return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN; - } - - int32_t getAbsoluteAxisValue(int32_t code) { - int32_t value; - getEventHub()->getAbsoluteAxisValue(mId, code, &value); - return value; - } - -private: - InputReaderContext* mContext; - int32_t mId; - int32_t mGeneration; - InputDeviceIdentifier mIdentifier; - String8 mAlias; - uint32_t mClasses; - - Vector<InputMapper*> mMappers; - - uint32_t mSources; - bool mIsExternal; - bool mDropUntilNextSync; - - typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code); - int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc); - - PropertyMap mConfiguration; -}; - - -/* Keeps track of the state of mouse or touch pad buttons. */ -class CursorButtonAccumulator { -public: - CursorButtonAccumulator(); - void reset(InputDevice* device); - - void process(const RawEvent* rawEvent); - - uint32_t getButtonState() const; - -private: - bool mBtnLeft; - bool mBtnRight; - bool mBtnMiddle; - bool mBtnBack; - bool mBtnSide; - bool mBtnForward; - bool mBtnExtra; - bool mBtnTask; - - void clearButtons(); -}; - - -/* Keeps track of cursor movements. */ - -class CursorMotionAccumulator { -public: - CursorMotionAccumulator(); - void reset(InputDevice* device); - - void process(const RawEvent* rawEvent); - void finishSync(); - - inline int32_t getRelativeX() const { return mRelX; } - inline int32_t getRelativeY() const { return mRelY; } - -private: - int32_t mRelX; - int32_t mRelY; - - void clearRelativeAxes(); -}; - - -/* Keeps track of cursor scrolling motions. */ - -class CursorScrollAccumulator { -public: - CursorScrollAccumulator(); - void configure(InputDevice* device); - void reset(InputDevice* device); - - void process(const RawEvent* rawEvent); - void finishSync(); - - inline bool haveRelativeVWheel() const { return mHaveRelWheel; } - inline bool haveRelativeHWheel() const { return mHaveRelHWheel; } - - inline int32_t getRelativeX() const { return mRelX; } - inline int32_t getRelativeY() const { return mRelY; } - inline int32_t getRelativeVWheel() const { return mRelWheel; } - inline int32_t getRelativeHWheel() const { return mRelHWheel; } - -private: - bool mHaveRelWheel; - bool mHaveRelHWheel; - - int32_t mRelX; - int32_t mRelY; - int32_t mRelWheel; - int32_t mRelHWheel; - - void clearRelativeAxes(); -}; - - -/* Keeps track of the state of touch, stylus and tool buttons. */ -class TouchButtonAccumulator { -public: - TouchButtonAccumulator(); - void configure(InputDevice* device); - void reset(InputDevice* device); - - void process(const RawEvent* rawEvent); - - uint32_t getButtonState() const; - int32_t getToolType() const; - bool isToolActive() const; - bool isHovering() const; - bool hasStylus() const; - -private: - bool mHaveBtnTouch; - bool mHaveStylus; - - bool mBtnTouch; - bool mBtnStylus; - bool mBtnStylus2; - bool mBtnToolFinger; - bool mBtnToolPen; - bool mBtnToolRubber; - bool mBtnToolBrush; - bool mBtnToolPencil; - bool mBtnToolAirbrush; - bool mBtnToolMouse; - bool mBtnToolLens; - bool mBtnToolDoubleTap; - bool mBtnToolTripleTap; - bool mBtnToolQuadTap; - - void clearButtons(); -}; - - -/* Raw axis information from the driver. */ -struct RawPointerAxes { - RawAbsoluteAxisInfo x; - RawAbsoluteAxisInfo y; - RawAbsoluteAxisInfo pressure; - RawAbsoluteAxisInfo touchMajor; - RawAbsoluteAxisInfo touchMinor; - RawAbsoluteAxisInfo toolMajor; - RawAbsoluteAxisInfo toolMinor; - RawAbsoluteAxisInfo orientation; - RawAbsoluteAxisInfo distance; - RawAbsoluteAxisInfo tiltX; - RawAbsoluteAxisInfo tiltY; - RawAbsoluteAxisInfo trackingId; - RawAbsoluteAxisInfo slot; - - RawPointerAxes(); - void clear(); -}; - - -/* Raw data for a collection of pointers including a pointer id mapping table. */ -struct RawPointerData { - struct Pointer { - uint32_t id; - int32_t x; - int32_t y; - int32_t pressure; - int32_t touchMajor; - int32_t touchMinor; - int32_t toolMajor; - int32_t toolMinor; - int32_t orientation; - int32_t distance; - int32_t tiltX; - int32_t tiltY; - int32_t toolType; // a fully decoded AMOTION_EVENT_TOOL_TYPE constant - bool isHovering; - }; - - uint32_t pointerCount; - Pointer pointers[MAX_POINTERS]; - BitSet32 hoveringIdBits, touchingIdBits; - uint32_t idToIndex[MAX_POINTER_ID + 1]; - - RawPointerData(); - void clear(); - void copyFrom(const RawPointerData& other); - void getCentroidOfTouchingPointers(float* outX, float* outY) const; - - inline void markIdBit(uint32_t id, bool isHovering) { - if (isHovering) { - hoveringIdBits.markBit(id); - } else { - touchingIdBits.markBit(id); - } - } - - inline void clearIdBits() { - hoveringIdBits.clear(); - touchingIdBits.clear(); - } - - inline const Pointer& pointerForId(uint32_t id) const { - return pointers[idToIndex[id]]; - } - - inline bool isHovering(uint32_t pointerIndex) { - return pointers[pointerIndex].isHovering; - } -}; - - -/* Cooked data for a collection of pointers including a pointer id mapping table. */ -struct CookedPointerData { - uint32_t pointerCount; - PointerProperties pointerProperties[MAX_POINTERS]; - PointerCoords pointerCoords[MAX_POINTERS]; - BitSet32 hoveringIdBits, touchingIdBits; - uint32_t idToIndex[MAX_POINTER_ID + 1]; - - CookedPointerData(); - void clear(); - void copyFrom(const CookedPointerData& other); - - inline const PointerCoords& pointerCoordsForId(uint32_t id) const { - return pointerCoords[idToIndex[id]]; - } - - inline bool isHovering(uint32_t pointerIndex) { - return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id); - } -}; - - -/* Keeps track of the state of single-touch protocol. */ -class SingleTouchMotionAccumulator { -public: - SingleTouchMotionAccumulator(); - - void process(const RawEvent* rawEvent); - void reset(InputDevice* device); - - inline int32_t getAbsoluteX() const { return mAbsX; } - inline int32_t getAbsoluteY() const { return mAbsY; } - inline int32_t getAbsolutePressure() const { return mAbsPressure; } - inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; } - inline int32_t getAbsoluteDistance() const { return mAbsDistance; } - inline int32_t getAbsoluteTiltX() const { return mAbsTiltX; } - inline int32_t getAbsoluteTiltY() const { return mAbsTiltY; } - -private: - int32_t mAbsX; - int32_t mAbsY; - int32_t mAbsPressure; - int32_t mAbsToolWidth; - int32_t mAbsDistance; - int32_t mAbsTiltX; - int32_t mAbsTiltY; - - void clearAbsoluteAxes(); -}; - - -/* Keeps track of the state of multi-touch protocol. */ -class MultiTouchMotionAccumulator { -public: - class Slot { - public: - inline bool isInUse() const { return mInUse; } - inline int32_t getX() const { return mAbsMTPositionX; } - inline int32_t getY() const { return mAbsMTPositionY; } - inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; } - inline int32_t getTouchMinor() const { - return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; } - inline int32_t getToolMajor() const { return mAbsMTWidthMajor; } - inline int32_t getToolMinor() const { - return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; } - inline int32_t getOrientation() const { return mAbsMTOrientation; } - inline int32_t getTrackingId() const { return mAbsMTTrackingId; } - inline int32_t getPressure() const { return mAbsMTPressure; } - inline int32_t getDistance() const { return mAbsMTDistance; } - inline int32_t getToolType() const; - - private: - friend class MultiTouchMotionAccumulator; - - bool mInUse; - bool mHaveAbsMTTouchMinor; - bool mHaveAbsMTWidthMinor; - bool mHaveAbsMTToolType; - - int32_t mAbsMTPositionX; - int32_t mAbsMTPositionY; - int32_t mAbsMTTouchMajor; - int32_t mAbsMTTouchMinor; - int32_t mAbsMTWidthMajor; - int32_t mAbsMTWidthMinor; - int32_t mAbsMTOrientation; - int32_t mAbsMTTrackingId; - int32_t mAbsMTPressure; - int32_t mAbsMTDistance; - int32_t mAbsMTToolType; - - Slot(); - void clear(); - }; - - MultiTouchMotionAccumulator(); - ~MultiTouchMotionAccumulator(); - - void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol); - void reset(InputDevice* device); - void process(const RawEvent* rawEvent); - void finishSync(); - bool hasStylus() const; - - inline size_t getSlotCount() const { return mSlotCount; } - inline const Slot* getSlot(size_t index) const { return &mSlots[index]; } - -private: - int32_t mCurrentSlot; - Slot* mSlots; - size_t mSlotCount; - bool mUsingSlotsProtocol; - bool mHaveStylus; - - void clearSlots(int32_t initialSlot); -}; - - -/* An input mapper transforms raw input events into cooked event data. - * A single input device can have multiple associated input mappers in order to interpret - * different classes of events. - * - * InputMapper lifecycle: - * - create - * - configure with 0 changes - * - reset - * - process, process, process (may occasionally reconfigure with non-zero changes or reset) - * - reset - * - destroy - */ -class InputMapper { -public: - InputMapper(InputDevice* device); - virtual ~InputMapper(); - - inline InputDevice* getDevice() { return mDevice; } - inline int32_t getDeviceId() { return mDevice->getId(); } - inline const String8 getDeviceName() { return mDevice->getName(); } - inline InputReaderContext* getContext() { return mContext; } - inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); } - inline InputListenerInterface* getListener() { return mContext->getListener(); } - inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } - - virtual uint32_t getSources() = 0; - virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); - virtual void dump(String8& dump); - virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); - virtual void reset(nsecs_t when); - virtual void process(const RawEvent* rawEvent) = 0; - virtual void timeoutExpired(nsecs_t when); - - virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); - virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); - virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); - virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, - const int32_t* keyCodes, uint8_t* outFlags); - virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, - int32_t token); - virtual void cancelVibrate(int32_t token); - - virtual int32_t getMetaState(); - - virtual void fadePointer(); - -protected: - InputDevice* mDevice; - InputReaderContext* mContext; - - status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo); - void bumpGeneration(); - - static void dumpRawAbsoluteAxisInfo(String8& dump, - const RawAbsoluteAxisInfo& axis, const char* name); -}; - - -class SwitchInputMapper : public InputMapper { -public: - SwitchInputMapper(InputDevice* device); - virtual ~SwitchInputMapper(); - - virtual uint32_t getSources(); - virtual void process(const RawEvent* rawEvent); - - virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); - -private: - uint32_t mUpdatedSwitchValues; - uint32_t mUpdatedSwitchMask; - - void processSwitch(int32_t switchCode, int32_t switchValue); - void sync(nsecs_t when); -}; - - -class VibratorInputMapper : public InputMapper { -public: - VibratorInputMapper(InputDevice* device); - virtual ~VibratorInputMapper(); - - virtual uint32_t getSources(); - virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); - virtual void process(const RawEvent* rawEvent); - - virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, - int32_t token); - virtual void cancelVibrate(int32_t token); - virtual void timeoutExpired(nsecs_t when); - virtual void dump(String8& dump); - -private: - bool mVibrating; - nsecs_t mPattern[MAX_VIBRATE_PATTERN_SIZE]; - size_t mPatternSize; - ssize_t mRepeat; - int32_t mToken; - ssize_t mIndex; - nsecs_t mNextStepTime; - - void nextStep(); - void stopVibrating(); -}; - - -class KeyboardInputMapper : public InputMapper { -public: - KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType); - virtual ~KeyboardInputMapper(); - - virtual uint32_t getSources(); - virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); - virtual void dump(String8& dump); - virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); - virtual void reset(nsecs_t when); - virtual void process(const RawEvent* rawEvent); - - virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); - virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); - virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, - const int32_t* keyCodes, uint8_t* outFlags); - - virtual int32_t getMetaState(); - -private: - struct KeyDown { - int32_t keyCode; - int32_t scanCode; - }; - - uint32_t mSource; - int32_t mKeyboardType; - - int32_t mOrientation; // orientation for dpad keys - - Vector<KeyDown> mKeyDowns; // keys that are down - int32_t mMetaState; - nsecs_t mDownTime; // time of most recent key down - - int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none - - struct LedState { - bool avail; // led is available - bool on; // we think the led is currently on - }; - LedState mCapsLockLedState; - LedState mNumLockLedState; - LedState mScrollLockLedState; - - // Immutable configuration parameters. - struct Parameters { - bool hasAssociatedDisplay; - bool orientationAware; - } mParameters; - - void configureParameters(); - void dumpParameters(String8& dump); - - bool isKeyboardOrGamepadKey(int32_t scanCode); - - void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode, - uint32_t policyFlags); - - ssize_t findKeyDown(int32_t scanCode); - - void resetLedState(); - void initializeLedState(LedState& ledState, int32_t led); - void updateLedState(bool reset); - void updateLedStateForModifier(LedState& ledState, int32_t led, - int32_t modifier, bool reset); -}; - - -class CursorInputMapper : public InputMapper { -public: - CursorInputMapper(InputDevice* device); - virtual ~CursorInputMapper(); - - virtual uint32_t getSources(); - virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); - virtual void dump(String8& dump); - virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); - virtual void reset(nsecs_t when); - virtual void process(const RawEvent* rawEvent); - - virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); - - virtual void fadePointer(); - -private: - // Amount that trackball needs to move in order to generate a key event. - static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6; - - // Immutable configuration parameters. - struct Parameters { - enum Mode { - MODE_POINTER, - MODE_NAVIGATION, - }; - - Mode mode; - bool hasAssociatedDisplay; - bool orientationAware; - } mParameters; - - CursorButtonAccumulator mCursorButtonAccumulator; - CursorMotionAccumulator mCursorMotionAccumulator; - CursorScrollAccumulator mCursorScrollAccumulator; - - int32_t mSource; - float mXScale; - float mYScale; - float mXPrecision; - float mYPrecision; - - float mVWheelScale; - float mHWheelScale; - - // Velocity controls for mouse pointer and wheel movements. - // The controls for X and Y wheel movements are separate to keep them decoupled. - VelocityControl mPointerVelocityControl; - VelocityControl mWheelXVelocityControl; - VelocityControl mWheelYVelocityControl; - - int32_t mOrientation; - - sp<PointerControllerInterface> mPointerController; - - int32_t mButtonState; - nsecs_t mDownTime; - - void configureParameters(); - void dumpParameters(String8& dump); - - void sync(nsecs_t when); -}; - - -class TouchInputMapper : public InputMapper { -public: - TouchInputMapper(InputDevice* device); - virtual ~TouchInputMapper(); - - virtual uint32_t getSources(); - virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); - virtual void dump(String8& dump); - virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); - virtual void reset(nsecs_t when); - virtual void process(const RawEvent* rawEvent); - - virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); - virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); - virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, - const int32_t* keyCodes, uint8_t* outFlags); - - virtual void fadePointer(); - virtual void timeoutExpired(nsecs_t when); - -protected: - CursorButtonAccumulator mCursorButtonAccumulator; - CursorScrollAccumulator mCursorScrollAccumulator; - TouchButtonAccumulator mTouchButtonAccumulator; - - struct VirtualKey { - int32_t keyCode; - int32_t scanCode; - uint32_t flags; - - // computed hit box, specified in touch screen coords based on known display size - int32_t hitLeft; - int32_t hitTop; - int32_t hitRight; - int32_t hitBottom; - - inline bool isHit(int32_t x, int32_t y) const { - return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom; - } - }; - - // Input sources and device mode. - uint32_t mSource; - - enum DeviceMode { - DEVICE_MODE_DISABLED, // input is disabled - DEVICE_MODE_DIRECT, // direct mapping (touchscreen) - DEVICE_MODE_UNSCALED, // unscaled mapping (touchpad) - DEVICE_MODE_NAVIGATION, // unscaled mapping with assist gesture (touch navigation) - DEVICE_MODE_POINTER, // pointer mapping (pointer) - }; - DeviceMode mDeviceMode; - - // The reader's configuration. - InputReaderConfiguration mConfig; - - // Immutable configuration parameters. - struct Parameters { - enum DeviceType { - DEVICE_TYPE_TOUCH_SCREEN, - DEVICE_TYPE_TOUCH_PAD, - DEVICE_TYPE_TOUCH_NAVIGATION, - DEVICE_TYPE_POINTER, - }; - - DeviceType deviceType; - bool hasAssociatedDisplay; - bool associatedDisplayIsExternal; - bool orientationAware; - - enum GestureMode { - GESTURE_MODE_POINTER, - GESTURE_MODE_SPOTS, - }; - GestureMode gestureMode; - } mParameters; - - // Immutable calibration parameters in parsed form. - struct Calibration { - // Size - enum SizeCalibration { - SIZE_CALIBRATION_DEFAULT, - SIZE_CALIBRATION_NONE, - SIZE_CALIBRATION_GEOMETRIC, - SIZE_CALIBRATION_DIAMETER, - SIZE_CALIBRATION_BOX, - SIZE_CALIBRATION_AREA, - }; - - SizeCalibration sizeCalibration; - - bool haveSizeScale; - float sizeScale; - bool haveSizeBias; - float sizeBias; - bool haveSizeIsSummed; - bool sizeIsSummed; - - // Pressure - enum PressureCalibration { - PRESSURE_CALIBRATION_DEFAULT, - PRESSURE_CALIBRATION_NONE, - PRESSURE_CALIBRATION_PHYSICAL, - PRESSURE_CALIBRATION_AMPLITUDE, - }; - - PressureCalibration pressureCalibration; - bool havePressureScale; - float pressureScale; - - // Orientation - enum OrientationCalibration { - ORIENTATION_CALIBRATION_DEFAULT, - ORIENTATION_CALIBRATION_NONE, - ORIENTATION_CALIBRATION_INTERPOLATED, - ORIENTATION_CALIBRATION_VECTOR, - }; - - OrientationCalibration orientationCalibration; - - // Distance - enum DistanceCalibration { - DISTANCE_CALIBRATION_DEFAULT, - DISTANCE_CALIBRATION_NONE, - DISTANCE_CALIBRATION_SCALED, - }; - - DistanceCalibration distanceCalibration; - bool haveDistanceScale; - float distanceScale; - - enum CoverageCalibration { - COVERAGE_CALIBRATION_DEFAULT, - COVERAGE_CALIBRATION_NONE, - COVERAGE_CALIBRATION_BOX, - }; - - CoverageCalibration coverageCalibration; - - inline void applySizeScaleAndBias(float* outSize) const { - if (haveSizeScale) { - *outSize *= sizeScale; - } - if (haveSizeBias) { - *outSize += sizeBias; - } - } - } mCalibration; - - // Raw pointer axis information from the driver. - RawPointerAxes mRawPointerAxes; - - // Raw pointer sample data. - RawPointerData mCurrentRawPointerData; - RawPointerData mLastRawPointerData; - - // Cooked pointer sample data. - CookedPointerData mCurrentCookedPointerData; - CookedPointerData mLastCookedPointerData; - - // Button state. - int32_t mCurrentButtonState; - int32_t mLastButtonState; - - // Scroll state. - int32_t mCurrentRawVScroll; - int32_t mCurrentRawHScroll; - - // Id bits used to differentiate fingers, stylus and mouse tools. - BitSet32 mCurrentFingerIdBits; // finger or unknown - BitSet32 mLastFingerIdBits; - BitSet32 mCurrentStylusIdBits; // stylus or eraser - BitSet32 mLastStylusIdBits; - BitSet32 mCurrentMouseIdBits; // mouse or lens - BitSet32 mLastMouseIdBits; - - // True if we sent a HOVER_ENTER event. - bool mSentHoverEnter; - - // The time the primary pointer last went down. - nsecs_t mDownTime; - - // The pointer controller, or null if the device is not a pointer. - sp<PointerControllerInterface> mPointerController; - - Vector<VirtualKey> mVirtualKeys; - - virtual void configureParameters(); - virtual void dumpParameters(String8& dump); - virtual void configureRawPointerAxes(); - virtual void dumpRawPointerAxes(String8& dump); - virtual void configureSurface(nsecs_t when, bool* outResetNeeded); - virtual void dumpSurface(String8& dump); - virtual void configureVirtualKeys(); - virtual void dumpVirtualKeys(String8& dump); - virtual void parseCalibration(); - virtual void resolveCalibration(); - virtual void dumpCalibration(String8& dump); - virtual bool hasStylus() const = 0; - - virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0; - -private: - // The current viewport. - // The components of the viewport are specified in the display's rotated orientation. - DisplayViewport mViewport; - - // The surface orientation, width and height set by configureSurface(). - // The width and height are derived from the viewport but are specified - // in the natural orientation. - // The surface origin specifies how the surface coordinates should be translated - // to align with the logical display coordinate space. - // The orientation may be different from the viewport orientation as it specifies - // the rotation of the surface coordinates required to produce the viewport's - // requested orientation, so it will depend on whether the device is orientation aware. - int32_t mSurfaceWidth; - int32_t mSurfaceHeight; - int32_t mSurfaceLeft; - int32_t mSurfaceTop; - int32_t mSurfaceOrientation; - - // Translation and scaling factors, orientation-independent. - float mXTranslate; - float mXScale; - float mXPrecision; - - float mYTranslate; - float mYScale; - float mYPrecision; - - float mGeometricScale; - - float mPressureScale; - - float mSizeScale; - - float mOrientationScale; - - float mDistanceScale; - - bool mHaveTilt; - float mTiltXCenter; - float mTiltXScale; - float mTiltYCenter; - float mTiltYScale; - - // Oriented motion ranges for input device info. - struct OrientedRanges { - InputDeviceInfo::MotionRange x; - InputDeviceInfo::MotionRange y; - InputDeviceInfo::MotionRange pressure; - - bool haveSize; - InputDeviceInfo::MotionRange size; - - bool haveTouchSize; - InputDeviceInfo::MotionRange touchMajor; - InputDeviceInfo::MotionRange touchMinor; - - bool haveToolSize; - InputDeviceInfo::MotionRange toolMajor; - InputDeviceInfo::MotionRange toolMinor; - - bool haveOrientation; - InputDeviceInfo::MotionRange orientation; - - bool haveDistance; - InputDeviceInfo::MotionRange distance; - - bool haveTilt; - InputDeviceInfo::MotionRange tilt; - - OrientedRanges() { - clear(); - } - - void clear() { - haveSize = false; - haveTouchSize = false; - haveToolSize = false; - haveOrientation = false; - haveDistance = false; - haveTilt = false; - } - } mOrientedRanges; - - // Oriented dimensions and precision. - float mOrientedXPrecision; - float mOrientedYPrecision; - - struct CurrentVirtualKeyState { - bool down; - bool ignored; - nsecs_t downTime; - int32_t keyCode; - int32_t scanCode; - } mCurrentVirtualKey; - - // Scale factor for gesture or mouse based pointer movements. - float mPointerXMovementScale; - float mPointerYMovementScale; - - // Scale factor for gesture based zooming and other freeform motions. - float mPointerXZoomScale; - float mPointerYZoomScale; - - // The maximum swipe width. - float mPointerGestureMaxSwipeWidth; - - struct PointerDistanceHeapElement { - uint32_t currentPointerIndex : 8; - uint32_t lastPointerIndex : 8; - uint64_t distance : 48; // squared distance - }; - - enum PointerUsage { - POINTER_USAGE_NONE, - POINTER_USAGE_GESTURES, - POINTER_USAGE_STYLUS, - POINTER_USAGE_MOUSE, - }; - PointerUsage mPointerUsage; - - struct PointerGesture { - enum Mode { - // No fingers, button is not pressed. - // Nothing happening. - NEUTRAL, - - // No fingers, button is not pressed. - // Tap detected. - // Emits DOWN and UP events at the pointer location. - TAP, - - // Exactly one finger dragging following a tap. - // Pointer follows the active finger. - // Emits DOWN, MOVE and UP events at the pointer location. - // - // Detect double-taps when the finger goes up while in TAP_DRAG mode. - TAP_DRAG, - - // Button is pressed. - // Pointer follows the active finger if there is one. Other fingers are ignored. - // Emits DOWN, MOVE and UP events at the pointer location. - BUTTON_CLICK_OR_DRAG, - - // Exactly one finger, button is not pressed. - // Pointer follows the active finger. - // Emits HOVER_MOVE events at the pointer location. - // - // Detect taps when the finger goes up while in HOVER mode. - HOVER, - - // Exactly two fingers but neither have moved enough to clearly indicate - // whether a swipe or freeform gesture was intended. We consider the - // pointer to be pressed so this enables clicking or long-pressing on buttons. - // Pointer does not move. - // Emits DOWN, MOVE and UP events with a single stationary pointer coordinate. - PRESS, - - // Exactly two fingers moving in the same direction, button is not pressed. - // Pointer does not move. - // Emits DOWN, MOVE and UP events with a single pointer coordinate that - // follows the midpoint between both fingers. - SWIPE, - - // Two or more fingers moving in arbitrary directions, button is not pressed. - // Pointer does not move. - // Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow - // each finger individually relative to the initial centroid of the finger. - FREEFORM, - - // Waiting for quiet time to end before starting the next gesture. - QUIET, - }; - - // Time the first finger went down. - nsecs_t firstTouchTime; - - // The active pointer id from the raw touch data. - int32_t activeTouchId; // -1 if none - - // The active pointer id from the gesture last delivered to the application. - int32_t activeGestureId; // -1 if none - - // Pointer coords and ids for the current and previous pointer gesture. - Mode currentGestureMode; - BitSet32 currentGestureIdBits; - uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1]; - PointerProperties currentGestureProperties[MAX_POINTERS]; - PointerCoords currentGestureCoords[MAX_POINTERS]; - - Mode lastGestureMode; - BitSet32 lastGestureIdBits; - uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1]; - PointerProperties lastGestureProperties[MAX_POINTERS]; - PointerCoords lastGestureCoords[MAX_POINTERS]; - - // Time the pointer gesture last went down. - nsecs_t downTime; - - // Time when the pointer went down for a TAP. - nsecs_t tapDownTime; - - // Time when the pointer went up for a TAP. - nsecs_t tapUpTime; - - // Location of initial tap. - float tapX, tapY; - - // Time we started waiting for quiescence. - nsecs_t quietTime; - - // Reference points for multitouch gestures. - float referenceTouchX; // reference touch X/Y coordinates in surface units - float referenceTouchY; - float referenceGestureX; // reference gesture X/Y coordinates in pixels - float referenceGestureY; - - // Distance that each pointer has traveled which has not yet been - // subsumed into the reference gesture position. - BitSet32 referenceIdBits; - struct Delta { - float dx, dy; - }; - Delta referenceDeltas[MAX_POINTER_ID + 1]; - - // Describes how touch ids are mapped to gesture ids for freeform gestures. - uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1]; - - // A velocity tracker for determining whether to switch active pointers during drags. - VelocityTracker velocityTracker; - - void reset() { - firstTouchTime = LLONG_MIN; - activeTouchId = -1; - activeGestureId = -1; - currentGestureMode = NEUTRAL; - currentGestureIdBits.clear(); - lastGestureMode = NEUTRAL; - lastGestureIdBits.clear(); - downTime = 0; - velocityTracker.clear(); - resetTap(); - resetQuietTime(); - } - - void resetTap() { - tapDownTime = LLONG_MIN; - tapUpTime = LLONG_MIN; - } - - void resetQuietTime() { - quietTime = LLONG_MIN; - } - } mPointerGesture; - - struct PointerSimple { - PointerCoords currentCoords; - PointerProperties currentProperties; - PointerCoords lastCoords; - PointerProperties lastProperties; - - // True if the pointer is down. - bool down; - - // True if the pointer is hovering. - bool hovering; - - // Time the pointer last went down. - nsecs_t downTime; - - void reset() { - currentCoords.clear(); - currentProperties.clear(); - lastCoords.clear(); - lastProperties.clear(); - down = false; - hovering = false; - downTime = 0; - } - } mPointerSimple; - - // The pointer and scroll velocity controls. - VelocityControl mPointerVelocityControl; - VelocityControl mWheelXVelocityControl; - VelocityControl mWheelYVelocityControl; - - void sync(nsecs_t when); - - bool consumeRawTouches(nsecs_t when, uint32_t policyFlags); - void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, - int32_t keyEventAction, int32_t keyEventFlags); - - void dispatchTouches(nsecs_t when, uint32_t policyFlags); - void dispatchHoverExit(nsecs_t when, uint32_t policyFlags); - void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags); - void cookPointerData(); - - void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage); - void abortPointerUsage(nsecs_t when, uint32_t policyFlags); - - void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout); - void abortPointerGestures(nsecs_t when, uint32_t policyFlags); - bool preparePointerGestures(nsecs_t when, - bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, - bool isTimeout); - - void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags); - void abortPointerStylus(nsecs_t when, uint32_t policyFlags); - - void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags); - void abortPointerMouse(nsecs_t when, uint32_t policyFlags); - - void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, - bool down, bool hovering); - void abortPointerSimple(nsecs_t when, uint32_t policyFlags); - - // Dispatches a motion event. - // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the - // method will take care of setting the index and transmuting the action to DOWN or UP - // it is the first / last pointer to go down / up. - void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, - int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, - const PointerProperties* properties, const PointerCoords* coords, - const uint32_t* idToIndex, BitSet32 idBits, - int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime); - - // Updates pointer coords and properties for pointers with specified ids that have moved. - // Returns true if any of them changed. - bool updateMovedPointers(const PointerProperties* inProperties, - const PointerCoords* inCoords, const uint32_t* inIdToIndex, - PointerProperties* outProperties, PointerCoords* outCoords, - const uint32_t* outIdToIndex, BitSet32 idBits) const; - - bool isPointInsideSurface(int32_t x, int32_t y); - const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); - - void assignPointerIds(); -}; - - -class SingleTouchInputMapper : public TouchInputMapper { -public: - SingleTouchInputMapper(InputDevice* device); - virtual ~SingleTouchInputMapper(); - - virtual void reset(nsecs_t when); - virtual void process(const RawEvent* rawEvent); - -protected: - virtual void syncTouch(nsecs_t when, bool* outHavePointerIds); - virtual void configureRawPointerAxes(); - virtual bool hasStylus() const; - -private: - SingleTouchMotionAccumulator mSingleTouchMotionAccumulator; -}; - - -class MultiTouchInputMapper : public TouchInputMapper { -public: - MultiTouchInputMapper(InputDevice* device); - virtual ~MultiTouchInputMapper(); - - virtual void reset(nsecs_t when); - virtual void process(const RawEvent* rawEvent); - -protected: - virtual void syncTouch(nsecs_t when, bool* outHavePointerIds); - virtual void configureRawPointerAxes(); - virtual bool hasStylus() const; - -private: - MultiTouchMotionAccumulator mMultiTouchMotionAccumulator; - - // Specifies the pointer id bits that are in use, and their associated tracking id. - BitSet32 mPointerIdBits; - int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1]; -}; - - -class JoystickInputMapper : public InputMapper { -public: - JoystickInputMapper(InputDevice* device); - virtual ~JoystickInputMapper(); - - virtual uint32_t getSources(); - virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); - virtual void dump(String8& dump); - virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); - virtual void reset(nsecs_t when); - virtual void process(const RawEvent* rawEvent); - -private: - struct Axis { - RawAbsoluteAxisInfo rawAxisInfo; - AxisInfo axisInfo; - - bool explicitlyMapped; // true if the axis was explicitly assigned an axis id - - float scale; // scale factor from raw to normalized values - float offset; // offset to add after scaling for normalization - float highScale; // scale factor from raw to normalized values of high split - float highOffset; // offset to add after scaling for normalization of high split - - float min; // normalized inclusive minimum - float max; // normalized inclusive maximum - float flat; // normalized flat region size - float fuzz; // normalized error tolerance - float resolution; // normalized resolution in units/mm - - float filter; // filter out small variations of this size - float currentValue; // current value - float newValue; // most recent value - float highCurrentValue; // current value of high split - float highNewValue; // most recent value of high split - - void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo, - bool explicitlyMapped, float scale, float offset, - float highScale, float highOffset, - float min, float max, float flat, float fuzz, float resolution) { - this->rawAxisInfo = rawAxisInfo; - this->axisInfo = axisInfo; - this->explicitlyMapped = explicitlyMapped; - this->scale = scale; - this->offset = offset; - this->highScale = highScale; - this->highOffset = highOffset; - this->min = min; - this->max = max; - this->flat = flat; - this->fuzz = fuzz; - this->resolution = resolution; - this->filter = 0; - resetValue(); - } - - void resetValue() { - this->currentValue = 0; - this->newValue = 0; - this->highCurrentValue = 0; - this->highNewValue = 0; - } - }; - - // Axes indexed by raw ABS_* axis index. - KeyedVector<int32_t, Axis> mAxes; - - void sync(nsecs_t when, bool force); - - bool haveAxis(int32_t axisId); - void pruneAxes(bool ignoreExplicitlyMappedAxes); - bool filterAxes(bool force); - - static bool hasValueChangedSignificantly(float filter, - float newValue, float currentValue, float min, float max); - static bool hasMovedNearerToValueWithinFilteredRange(float filter, - float newValue, float currentValue, float thresholdValue); - - static bool isCenteredAxis(int32_t axis); - static int32_t getCompatAxis(int32_t axis); - - static void addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info); - static void setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis, - float value); -}; - -} // namespace android - -#endif // _UI_INPUT_READER_H diff --git a/widget/gonk/libui/InputTransport.cpp b/widget/gonk/libui/InputTransport.cpp deleted file mode 100644 index 3f0fcb047..000000000 --- a/widget/gonk/libui/InputTransport.cpp +++ /dev/null @@ -1,957 +0,0 @@ -// -// Copyright 2010 The Android Open Source Project -// -// Provides a shared memory transport for input events. -// -#define LOG_TAG "InputTransport" - -//#define LOG_NDEBUG 0 - -// Log debug messages about channel messages (send message, receive message) -#define DEBUG_CHANNEL_MESSAGES 0 - -// Log debug messages whenever InputChannel objects are created/destroyed -#define DEBUG_CHANNEL_LIFECYCLE 0 - -// Log debug messages about transport actions -#define DEBUG_TRANSPORT_ACTIONS 0 - -// Log debug messages about touch event resampling -#define DEBUG_RESAMPLING 0 - - -#include "cutils_log.h" -#include <cutils/properties.h> -#include <errno.h> -#include <fcntl.h> -#include "InputTransport.h" -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <math.h> - - -namespace android { - -// Socket buffer size. The default is typically about 128KB, which is much larger than -// we really need. So we make it smaller. It just needs to be big enough to hold -// a few dozen large multi-finger motion events in the case where an application gets -// behind processing touches. -static const size_t SOCKET_BUFFER_SIZE = 32 * 1024; - -// Nanoseconds per milliseconds. -static const nsecs_t NANOS_PER_MS = 1000000; - -// Latency added during resampling. A few milliseconds doesn't hurt much but -// reduces the impact of mispredicted touch positions. -static const nsecs_t RESAMPLE_LATENCY = 5 * NANOS_PER_MS; - -// Minimum time difference between consecutive samples before attempting to resample. -static const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS; - -// Maximum time to predict forward from the last known state, to avoid predicting too -// far into the future. This time is further bounded by 50% of the last time delta. -static const nsecs_t RESAMPLE_MAX_PREDICTION = 8 * NANOS_PER_MS; - -template<typename T> -inline static T min(const T& a, const T& b) { - return a < b ? a : b; -} - -inline static float lerp(float a, float b, float alpha) { - return a + alpha * (b - a); -} - -// --- InputMessage --- - -bool InputMessage::isValid(size_t actualSize) const { - if (size() == actualSize) { - switch (header.type) { - case TYPE_KEY: - return true; - case TYPE_MOTION: - return body.motion.pointerCount > 0 - && body.motion.pointerCount <= MAX_POINTERS; - case TYPE_FINISHED: - return true; - } - } - return false; -} - -size_t InputMessage::size() const { - switch (header.type) { - case TYPE_KEY: - return sizeof(Header) + body.key.size(); - case TYPE_MOTION: - return sizeof(Header) + body.motion.size(); - case TYPE_FINISHED: - return sizeof(Header) + body.finished.size(); - } - return sizeof(Header); -} - - -// --- InputChannel --- - -InputChannel::InputChannel(const String8& name, int fd) : - mName(name), mFd(fd) { -#if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel constructed: name='%s', fd=%d", - mName.string(), fd); -#endif - - int result = fcntl(mFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket " - "non-blocking. errno=%d", mName.string(), errno); -} - -InputChannel::~InputChannel() { -#if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel destroyed: name='%s', fd=%d", - mName.string(), mFd); -#endif - - ::close(mFd); -} - -status_t InputChannel::openInputChannelPair(const String8& name, - sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) { - int sockets[2]; - if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) { - status_t result = -errno; - ALOGE("channel '%s' ~ Could not create socket pair. errno=%d", - name.string(), errno); - outServerChannel.clear(); - outClientChannel.clear(); - return result; - } - - int bufferSize = SOCKET_BUFFER_SIZE; - setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); - setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); - setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); - setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); - - String8 serverChannelName = name; - serverChannelName.append(" (server)"); - outServerChannel = new InputChannel(serverChannelName, sockets[0]); - - String8 clientChannelName = name; - clientChannelName.append(" (client)"); - outClientChannel = new InputChannel(clientChannelName, sockets[1]); - return OK; -} - -status_t InputChannel::sendMessage(const InputMessage* msg) { - size_t msgLength = msg->size(); - ssize_t nWrite; - do { - nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); - } while (nWrite == -1 && errno == EINTR); - - if (nWrite < 0) { - int error = errno; -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ error sending message of type %d, errno=%d", mName.string(), - msg->header.type, error); -#endif - if (error == EAGAIN || error == EWOULDBLOCK) { - return WOULD_BLOCK; - } - if (error == EPIPE || error == ENOTCONN) { - return DEAD_OBJECT; - } - return -error; - } - - if (size_t(nWrite) != msgLength) { -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ error sending message type %d, send was incomplete", - mName.string(), msg->header.type); -#endif - return DEAD_OBJECT; - } - -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ sent message of type %d", mName.string(), msg->header.type); -#endif - return OK; -} - -status_t InputChannel::receiveMessage(InputMessage* msg) { - ssize_t nRead; - do { - nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT); - } while (nRead == -1 && errno == EINTR); - - if (nRead < 0) { - int error = errno; -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.string(), errno); -#endif - if (error == EAGAIN || error == EWOULDBLOCK) { - return WOULD_BLOCK; - } - if (error == EPIPE || error == ENOTCONN) { - return DEAD_OBJECT; - } - return -error; - } - - if (nRead == 0) { // check for EOF -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.string()); -#endif - return DEAD_OBJECT; - } - - if (!msg->isValid(nRead)) { -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ received invalid message", mName.string()); -#endif - return BAD_VALUE; - } - -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ received message of type %d", mName.string(), msg->header.type); -#endif - return OK; -} - -sp<InputChannel> InputChannel::dup() const { - int fd = ::dup(getFd()); - return fd >= 0 ? new InputChannel(getName(), fd) : NULL; -} - - -// --- InputPublisher --- - -InputPublisher::InputPublisher(const sp<InputChannel>& channel) : - mChannel(channel) { -} - -InputPublisher::~InputPublisher() { -} - -status_t InputPublisher::publishKeyEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, " - "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d," - "downTime=%lld, eventTime=%lld", - mChannel->getName().string(), seq, - deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount, - downTime, eventTime); -#endif - - if (!seq) { - ALOGE("Attempted to publish a key event with sequence number 0."); - return BAD_VALUE; - } - - InputMessage msg; - msg.header.type = InputMessage::TYPE_KEY; - msg.body.key.seq = seq; - msg.body.key.deviceId = deviceId; - msg.body.key.source = source; - msg.body.key.action = action; - msg.body.key.flags = flags; - msg.body.key.keyCode = keyCode; - msg.body.key.scanCode = scanCode; - msg.body.key.metaState = metaState; - msg.body.key.repeatCount = repeatCount; - msg.body.key.downTime = downTime; - msg.body.key.eventTime = eventTime; - return mChannel->sendMessage(&msg); -} - -status_t InputPublisher::publishMotionEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - size_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, " - "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, " - "xOffset=%f, yOffset=%f, " - "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, " - "pointerCount=%d", - mChannel->getName().string(), seq, - deviceId, source, action, flags, edgeFlags, metaState, buttonState, - xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount); -#endif - - if (!seq) { - ALOGE("Attempted to publish a motion event with sequence number 0."); - return BAD_VALUE; - } - - if (pointerCount > MAX_POINTERS || pointerCount < 1) { - ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.", - mChannel->getName().string(), pointerCount); - return BAD_VALUE; - } - - InputMessage msg; - msg.header.type = InputMessage::TYPE_MOTION; - msg.body.motion.seq = seq; - msg.body.motion.deviceId = deviceId; - msg.body.motion.source = source; - msg.body.motion.action = action; - msg.body.motion.flags = flags; - msg.body.motion.edgeFlags = edgeFlags; - msg.body.motion.metaState = metaState; - msg.body.motion.buttonState = buttonState; - msg.body.motion.xOffset = xOffset; - msg.body.motion.yOffset = yOffset; - msg.body.motion.xPrecision = xPrecision; - msg.body.motion.yPrecision = yPrecision; - msg.body.motion.downTime = downTime; - msg.body.motion.eventTime = eventTime; - msg.body.motion.pointerCount = pointerCount; - for (size_t i = 0; i < pointerCount; i++) { - msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]); - msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]); - } - return mChannel->sendMessage(&msg); -} - -status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' publisher ~ receiveFinishedSignal", - mChannel->getName().string()); -#endif - - InputMessage msg; - status_t result = mChannel->receiveMessage(&msg); - if (result) { - *outSeq = 0; - *outHandled = false; - return result; - } - if (msg.header.type != InputMessage::TYPE_FINISHED) { - ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer", - mChannel->getName().string(), msg.header.type); - return UNKNOWN_ERROR; - } - *outSeq = msg.body.finished.seq; - *outHandled = msg.body.finished.handled; - return OK; -} - -// --- InputConsumer --- - -InputConsumer::InputConsumer(const sp<InputChannel>& channel) : - mResampleTouch(isTouchResamplingEnabled()), - mChannel(channel), mMsgDeferred(false) { -} - -InputConsumer::~InputConsumer() { -} - -bool InputConsumer::isTouchResamplingEnabled() { - char value[PROPERTY_VALUE_MAX]; - int length = property_get("debug.inputconsumer.resample", value, NULL); - if (length > 0) { - if (!strcmp("0", value)) { - return false; - } - if (strcmp("1", value)) { - ALOGD("Unrecognized property value for 'debug.inputconsumer.resample'. " - "Use '1' or '0'."); - } - } - return true; -} - -status_t InputConsumer::consume(InputEventFactoryInterface* factory, - bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%lld", - mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime); -#endif - - *outSeq = 0; - *outEvent = NULL; - - // Fetch the next input message. - // Loop until an event can be returned or no additional events are received. - while (!*outEvent) { - if (mMsgDeferred) { - // mMsg contains a valid input message from the previous call to consume - // that has not yet been processed. - mMsgDeferred = false; - } else { - // Receive a fresh message. - status_t result = mChannel->receiveMessage(&mMsg); - if (result) { - // Consume the next batched event unless batches are being held for later. - if (consumeBatches || result != WOULD_BLOCK) { - result = consumeBatch(factory, frameTime, outSeq, outEvent); - if (*outEvent) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u", - mChannel->getName().string(), *outSeq); -#endif - break; - } - } - return result; - } - } - - switch (mMsg.header.type) { - case InputMessage::TYPE_KEY: { - KeyEvent* keyEvent = factory->createKeyEvent(); - if (!keyEvent) return NO_MEMORY; - - initializeKeyEvent(keyEvent, &mMsg); - *outSeq = mMsg.body.key.seq; - *outEvent = keyEvent; -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consumed key event, seq=%u", - mChannel->getName().string(), *outSeq); -#endif - break; - } - - case AINPUT_EVENT_TYPE_MOTION: { - ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source); - if (batchIndex >= 0) { - Batch& batch = mBatches.editItemAt(batchIndex); - if (canAddSample(batch, &mMsg)) { - batch.samples.push(mMsg); -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ appended to batch event", - mChannel->getName().string()); -#endif - break; - } else { - // We cannot append to the batch in progress, so we need to consume - // the previous batch right now and defer the new message until later. - mMsgDeferred = true; - status_t result = consumeSamples(factory, - batch, batch.samples.size(), outSeq, outEvent); - mBatches.removeAt(batchIndex); - if (result) { - return result; - } -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consumed batch event and " - "deferred current event, seq=%u", - mChannel->getName().string(), *outSeq); -#endif - break; - } - } - - // Start a new batch if needed. - if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE - || mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) { - mBatches.push(); - Batch& batch = mBatches.editTop(); - batch.samples.push(mMsg); -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ started batch event", - mChannel->getName().string()); -#endif - break; - } - - MotionEvent* motionEvent = factory->createMotionEvent(); - if (! motionEvent) return NO_MEMORY; - - updateTouchState(&mMsg); - initializeMotionEvent(motionEvent, &mMsg); - *outSeq = mMsg.body.motion.seq; - *outEvent = motionEvent; -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u", - mChannel->getName().string(), *outSeq); -#endif - break; - } - - default: - ALOGE("channel '%s' consumer ~ Received unexpected message of type %d", - mChannel->getName().string(), mMsg.header.type); - return UNKNOWN_ERROR; - } - } - return OK; -} - -status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory, - nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) { - status_t result; - for (size_t i = mBatches.size(); i-- > 0; ) { - Batch& batch = mBatches.editItemAt(i); - if (frameTime < 0) { - result = consumeSamples(factory, batch, batch.samples.size(), - outSeq, outEvent); - mBatches.removeAt(i); - return result; - } - - nsecs_t sampleTime = frameTime - RESAMPLE_LATENCY; - ssize_t split = findSampleNoLaterThan(batch, sampleTime); - if (split < 0) { - continue; - } - - result = consumeSamples(factory, batch, split + 1, outSeq, outEvent); - const InputMessage* next; - if (batch.samples.isEmpty()) { - mBatches.removeAt(i); - next = NULL; - } else { - next = &batch.samples.itemAt(0); - } - if (!result) { - resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next); - } - return result; - } - - return WOULD_BLOCK; -} - -status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory, - Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) { - MotionEvent* motionEvent = factory->createMotionEvent(); - if (! motionEvent) return NO_MEMORY; - - uint32_t chain = 0; - for (size_t i = 0; i < count; i++) { - InputMessage& msg = batch.samples.editItemAt(i); - updateTouchState(&msg); - if (i) { - SeqChain seqChain; - seqChain.seq = msg.body.motion.seq; - seqChain.chain = chain; - mSeqChains.push(seqChain); - addSample(motionEvent, &msg); - } else { - initializeMotionEvent(motionEvent, &msg); - } - chain = msg.body.motion.seq; - } - batch.samples.removeItemsAt(0, count); - - *outSeq = chain; - *outEvent = motionEvent; - return OK; -} - -void InputConsumer::updateTouchState(InputMessage* msg) { - if (!mResampleTouch || - !(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) { - return; - } - - int32_t deviceId = msg->body.motion.deviceId; - int32_t source = msg->body.motion.source; - nsecs_t eventTime = msg->body.motion.eventTime; - - // Update the touch state history to incorporate the new input message. - // If the message is in the past relative to the most recently produced resampled - // touch, then use the resampled time and coordinates instead. - switch (msg->body.motion.action & AMOTION_EVENT_ACTION_MASK) { - case AMOTION_EVENT_ACTION_DOWN: { - ssize_t index = findTouchState(deviceId, source); - if (index < 0) { - mTouchStates.push(); - index = mTouchStates.size() - 1; - } - TouchState& touchState = mTouchStates.editItemAt(index); - touchState.initialize(deviceId, source); - touchState.addHistory(msg); - break; - } - - case AMOTION_EVENT_ACTION_MOVE: { - ssize_t index = findTouchState(deviceId, source); - if (index >= 0) { - TouchState& touchState = mTouchStates.editItemAt(index); - touchState.addHistory(msg); - if (eventTime < touchState.lastResample.eventTime) { - rewriteMessage(touchState, msg); - } else { - touchState.lastResample.idBits.clear(); - } - } - break; - } - - case AMOTION_EVENT_ACTION_POINTER_DOWN: { - ssize_t index = findTouchState(deviceId, source); - if (index >= 0) { - TouchState& touchState = mTouchStates.editItemAt(index); - touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId()); - rewriteMessage(touchState, msg); - } - break; - } - - case AMOTION_EVENT_ACTION_POINTER_UP: { - ssize_t index = findTouchState(deviceId, source); - if (index >= 0) { - TouchState& touchState = mTouchStates.editItemAt(index); - rewriteMessage(touchState, msg); - touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId()); - } - break; - } - - case AMOTION_EVENT_ACTION_SCROLL: { - ssize_t index = findTouchState(deviceId, source); - if (index >= 0) { - const TouchState& touchState = mTouchStates.itemAt(index); - rewriteMessage(touchState, msg); - } - break; - } - - case AMOTION_EVENT_ACTION_UP: - case AMOTION_EVENT_ACTION_CANCEL: { - ssize_t index = findTouchState(deviceId, source); - if (index >= 0) { - const TouchState& touchState = mTouchStates.itemAt(index); - rewriteMessage(touchState, msg); - mTouchStates.removeAt(index); - } - break; - } - } -} - -void InputConsumer::rewriteMessage(const TouchState& state, InputMessage* msg) { - for (size_t i = 0; i < msg->body.motion.pointerCount; i++) { - uint32_t id = msg->body.motion.pointers[i].properties.id; - if (state.lastResample.idBits.hasBit(id)) { - PointerCoords& msgCoords = msg->body.motion.pointers[i].coords; - const PointerCoords& resampleCoords = state.lastResample.getPointerById(id); -#if DEBUG_RESAMPLING - ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id, - resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_X), - resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_Y), - msgCoords.getAxisValue(AMOTION_EVENT_AXIS_X), - msgCoords.getAxisValue(AMOTION_EVENT_AXIS_Y)); -#endif - msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX()); - msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY()); - } - } -} - -void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, - const InputMessage* next) { - if (!mResampleTouch - || !(event->getSource() & AINPUT_SOURCE_CLASS_POINTER) - || event->getAction() != AMOTION_EVENT_ACTION_MOVE) { - return; - } - - ssize_t index = findTouchState(event->getDeviceId(), event->getSource()); - if (index < 0) { -#if DEBUG_RESAMPLING - ALOGD("Not resampled, no touch state for device."); -#endif - return; - } - - TouchState& touchState = mTouchStates.editItemAt(index); - if (touchState.historySize < 1) { -#if DEBUG_RESAMPLING - ALOGD("Not resampled, no history for device."); -#endif - return; - } - - // Ensure that the current sample has all of the pointers that need to be reported. - const History* current = touchState.getHistory(0); - size_t pointerCount = event->getPointerCount(); - for (size_t i = 0; i < pointerCount; i++) { - uint32_t id = event->getPointerId(i); - if (!current->idBits.hasBit(id)) { -#if DEBUG_RESAMPLING - ALOGD("Not resampled, missing id %d", id); -#endif - return; - } - } - - // Find the data to use for resampling. - const History* other; - History future; - float alpha; - if (next) { - // Interpolate between current sample and future sample. - // So current->eventTime <= sampleTime <= future.eventTime. - future.initializeFrom(next); - other = &future; - nsecs_t delta = future.eventTime - current->eventTime; - if (delta < RESAMPLE_MIN_DELTA) { -#if DEBUG_RESAMPLING - ALOGD("Not resampled, delta time is %lld ns.", delta); -#endif - return; - } - alpha = float(sampleTime - current->eventTime) / delta; - } else if (touchState.historySize >= 2) { - // Extrapolate future sample using current sample and past sample. - // So other->eventTime <= current->eventTime <= sampleTime. - other = touchState.getHistory(1); - nsecs_t delta = current->eventTime - other->eventTime; - if (delta < RESAMPLE_MIN_DELTA) { -#if DEBUG_RESAMPLING - ALOGD("Not resampled, delta time is %lld ns.", delta); -#endif - return; - } - nsecs_t maxPredict = current->eventTime + min(delta / 2, RESAMPLE_MAX_PREDICTION); - if (sampleTime > maxPredict) { -#if DEBUG_RESAMPLING - ALOGD("Sample time is too far in the future, adjusting prediction " - "from %lld to %lld ns.", - sampleTime - current->eventTime, maxPredict - current->eventTime); -#endif - sampleTime = maxPredict; - } - alpha = float(current->eventTime - sampleTime) / delta; - } else { -#if DEBUG_RESAMPLING - ALOGD("Not resampled, insufficient data."); -#endif - return; - } - - // Resample touch coordinates. - touchState.lastResample.eventTime = sampleTime; - touchState.lastResample.idBits.clear(); - for (size_t i = 0; i < pointerCount; i++) { - uint32_t id = event->getPointerId(i); - touchState.lastResample.idToIndex[id] = i; - touchState.lastResample.idBits.markBit(id); - PointerCoords& resampledCoords = touchState.lastResample.pointers[i]; - const PointerCoords& currentCoords = current->getPointerById(id); - if (other->idBits.hasBit(id) - && shouldResampleTool(event->getToolType(i))) { - const PointerCoords& otherCoords = other->getPointerById(id); - resampledCoords.copyFrom(currentCoords); - resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X, - lerp(currentCoords.getX(), otherCoords.getX(), alpha)); - resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, - lerp(currentCoords.getY(), otherCoords.getY(), alpha)); -#if DEBUG_RESAMPLING - ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), " - "other (%0.3f, %0.3f), alpha %0.3f", - id, resampledCoords.getX(), resampledCoords.getY(), - currentCoords.getX(), currentCoords.getY(), - otherCoords.getX(), otherCoords.getY(), - alpha); -#endif - } else { - resampledCoords.copyFrom(currentCoords); -#if DEBUG_RESAMPLING - ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)", - id, resampledCoords.getX(), resampledCoords.getY(), - currentCoords.getX(), currentCoords.getY()); -#endif - } - } - - event->addSample(sampleTime, touchState.lastResample.pointers); -} - -bool InputConsumer::shouldResampleTool(int32_t toolType) { - return toolType == AMOTION_EVENT_TOOL_TYPE_FINGER - || toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN; -} - -status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s", - mChannel->getName().string(), seq, handled ? "true" : "false"); -#endif - - if (!seq) { - ALOGE("Attempted to send a finished signal with sequence number 0."); - return BAD_VALUE; - } - - // Send finished signals for the batch sequence chain first. - size_t seqChainCount = mSeqChains.size(); - if (seqChainCount) { - uint32_t currentSeq = seq; - uint32_t chainSeqs[seqChainCount]; - size_t chainIndex = 0; - for (size_t i = seqChainCount; i-- > 0; ) { - const SeqChain& seqChain = mSeqChains.itemAt(i); - if (seqChain.seq == currentSeq) { - currentSeq = seqChain.chain; - chainSeqs[chainIndex++] = currentSeq; - mSeqChains.removeAt(i); - } - } - status_t status = OK; - while (!status && chainIndex-- > 0) { - status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled); - } - if (status) { - // An error occurred so at least one signal was not sent, reconstruct the chain. - do { - SeqChain seqChain; - seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq; - seqChain.chain = chainSeqs[chainIndex]; - mSeqChains.push(seqChain); - } while (chainIndex-- > 0); - return status; - } - } - - // Send finished signal for the last message in the batch. - return sendUnchainedFinishedSignal(seq, handled); -} - -status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) { - InputMessage msg; - msg.header.type = InputMessage::TYPE_FINISHED; - msg.body.finished.seq = seq; - msg.body.finished.handled = handled; - return mChannel->sendMessage(&msg); -} - -bool InputConsumer::hasDeferredEvent() const { - return mMsgDeferred; -} - -bool InputConsumer::hasPendingBatch() const { - return !mBatches.isEmpty(); -} - -ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const { - for (size_t i = 0; i < mBatches.size(); i++) { - const Batch& batch = mBatches.itemAt(i); - const InputMessage& head = batch.samples.itemAt(0); - if (head.body.motion.deviceId == deviceId && head.body.motion.source == source) { - return i; - } - } - return -1; -} - -ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const { - for (size_t i = 0; i < mTouchStates.size(); i++) { - const TouchState& touchState = mTouchStates.itemAt(i); - if (touchState.deviceId == deviceId && touchState.source == source) { - return i; - } - } - return -1; -} - -void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) { - event->initialize( - msg->body.key.deviceId, - msg->body.key.source, - msg->body.key.action, - msg->body.key.flags, - msg->body.key.keyCode, - msg->body.key.scanCode, - msg->body.key.metaState, - msg->body.key.repeatCount, - msg->body.key.downTime, - msg->body.key.eventTime); -} - -void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) { - size_t pointerCount = msg->body.motion.pointerCount; - PointerProperties pointerProperties[pointerCount]; - PointerCoords pointerCoords[pointerCount]; - for (size_t i = 0; i < pointerCount; i++) { - pointerProperties[i].copyFrom(msg->body.motion.pointers[i].properties); - pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords); - } - - event->initialize( - msg->body.motion.deviceId, - msg->body.motion.source, - msg->body.motion.action, - msg->body.motion.flags, - msg->body.motion.edgeFlags, - msg->body.motion.metaState, - msg->body.motion.buttonState, - msg->body.motion.xOffset, - msg->body.motion.yOffset, - msg->body.motion.xPrecision, - msg->body.motion.yPrecision, - msg->body.motion.downTime, - msg->body.motion.eventTime, - pointerCount, - pointerProperties, - pointerCoords); -} - -void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) { - size_t pointerCount = msg->body.motion.pointerCount; - PointerCoords pointerCoords[pointerCount]; - for (size_t i = 0; i < pointerCount; i++) { - pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords); - } - - event->setMetaState(event->getMetaState() | msg->body.motion.metaState); - event->addSample(msg->body.motion.eventTime, pointerCoords); -} - -bool InputConsumer::canAddSample(const Batch& batch, const InputMessage *msg) { - const InputMessage& head = batch.samples.itemAt(0); - size_t pointerCount = msg->body.motion.pointerCount; - if (head.body.motion.pointerCount != pointerCount - || head.body.motion.action != msg->body.motion.action) { - return false; - } - for (size_t i = 0; i < pointerCount; i++) { - if (head.body.motion.pointers[i].properties - != msg->body.motion.pointers[i].properties) { - return false; - } - } - return true; -} - -ssize_t InputConsumer::findSampleNoLaterThan(const Batch& batch, nsecs_t time) { - size_t numSamples = batch.samples.size(); - size_t index = 0; - while (index < numSamples - && batch.samples.itemAt(index).body.motion.eventTime <= time) { - index += 1; - } - return ssize_t(index) - 1; -} - -} // namespace android diff --git a/widget/gonk/libui/InputTransport.h b/widget/gonk/libui/InputTransport.h deleted file mode 100644 index 66ef2850a..000000000 --- a/widget/gonk/libui/InputTransport.h +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_INPUT_TRANSPORT_H -#define _ANDROIDFW_INPUT_TRANSPORT_H - -/** - * Native input transport. - * - * The InputChannel provides a mechanism for exchanging InputMessage structures across processes. - * - * The InputPublisher and InputConsumer each handle one end-point of an input channel. - * The InputPublisher is used by the input dispatcher to send events to the application. - * The InputConsumer is used by the application to receive events from the input dispatcher. - */ - -#include "Input.h" -#include <utils/Errors.h> -#include <utils/Timers.h> -#include <utils/RefBase.h> -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/BitSet.h> - -namespace android { - -/* - * Intermediate representation used to send input events and related signals. - */ -struct InputMessage { - enum { - TYPE_KEY = 1, - TYPE_MOTION = 2, - TYPE_FINISHED = 3, - }; - - struct Header { - uint32_t type; - uint32_t padding; // 8 byte alignment for the body that follows - } header; - - union Body { - struct Key { - uint32_t seq; - nsecs_t eventTime; - int32_t deviceId; - int32_t source; - int32_t action; - int32_t flags; - int32_t keyCode; - int32_t scanCode; - int32_t metaState; - int32_t repeatCount; - nsecs_t downTime; - - inline size_t size() const { - return sizeof(Key); - } - } key; - - struct Motion { - uint32_t seq; - nsecs_t eventTime; - int32_t deviceId; - int32_t source; - int32_t action; - int32_t flags; - int32_t metaState; - int32_t buttonState; - int32_t edgeFlags; - nsecs_t downTime; - float xOffset; - float yOffset; - float xPrecision; - float yPrecision; - size_t pointerCount; - struct Pointer { - PointerProperties properties; - PointerCoords coords; - } pointers[MAX_POINTERS]; - - int32_t getActionId() const { - uint32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) - >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; - return pointers[index].properties.id; - } - - inline size_t size() const { - return sizeof(Motion) - sizeof(Pointer) * MAX_POINTERS - + sizeof(Pointer) * pointerCount; - } - } motion; - - struct Finished { - uint32_t seq; - bool handled; - - inline size_t size() const { - return sizeof(Finished); - } - } finished; - } body; - - bool isValid(size_t actualSize) const; - size_t size() const; -}; - -/* - * An input channel consists of a local unix domain socket used to send and receive - * input messages across processes. Each channel has a descriptive name for debugging purposes. - * - * Each endpoint has its own InputChannel object that specifies its file descriptor. - * - * The input channel is closed when all references to it are released. - */ -class InputChannel : public RefBase { -protected: - virtual ~InputChannel(); - -public: - InputChannel(const String8& name, int fd); - - /* Creates a pair of input channels. - * - * Returns OK on success. - */ - static status_t openInputChannelPair(const String8& name, - sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel); - - inline String8 getName() const { return mName; } - inline int getFd() const { return mFd; } - - /* Sends a message to the other endpoint. - * - * If the channel is full then the message is guaranteed not to have been sent at all. - * Try again after the consumer has sent a finished signal indicating that it has - * consumed some of the pending messages from the channel. - * - * Returns OK on success. - * Returns WOULD_BLOCK if the channel is full. - * Returns DEAD_OBJECT if the channel's peer has been closed. - * Other errors probably indicate that the channel is broken. - */ - status_t sendMessage(const InputMessage* msg); - - /* Receives a message sent by the other endpoint. - * - * If there is no message present, try again after poll() indicates that the fd - * is readable. - * - * Returns OK on success. - * Returns WOULD_BLOCK if there is no message present. - * Returns DEAD_OBJECT if the channel's peer has been closed. - * Other errors probably indicate that the channel is broken. - */ - status_t receiveMessage(InputMessage* msg); - - /* Returns a new object that has a duplicate of this channel's fd. */ - sp<InputChannel> dup() const; - -private: - String8 mName; - int mFd; -}; - -/* - * Publishes input events to an input channel. - */ -class InputPublisher { -public: - /* Creates a publisher associated with an input channel. */ - explicit InputPublisher(const sp<InputChannel>& channel); - - /* Destroys the publisher and releases its input channel. */ - ~InputPublisher(); - - /* Gets the underlying input channel. */ - inline sp<InputChannel> getChannel() { return mChannel; } - - /* Publishes a key event to the input channel. - * - * Returns OK on success. - * Returns WOULD_BLOCK if the channel is full. - * Returns DEAD_OBJECT if the channel's peer has been closed. - * Returns BAD_VALUE if seq is 0. - * Other errors probably indicate that the channel is broken. - */ - status_t publishKeyEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime); - - /* Publishes a motion event to the input channel. - * - * Returns OK on success. - * Returns WOULD_BLOCK if the channel is full. - * Returns DEAD_OBJECT if the channel's peer has been closed. - * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS. - * Other errors probably indicate that the channel is broken. - */ - status_t publishMotionEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - size_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords); - - /* Receives the finished signal from the consumer in reply to the original dispatch signal. - * If a signal was received, returns the message sequence number, - * and whether the consumer handled the message. - * - * The returned sequence number is never 0 unless the operation failed. - * - * Returns OK on success. - * Returns WOULD_BLOCK if there is no signal present. - * Returns DEAD_OBJECT if the channel's peer has been closed. - * Other errors probably indicate that the channel is broken. - */ - status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); - -private: - sp<InputChannel> mChannel; -}; - -/* - * Consumes input events from an input channel. - */ -class InputConsumer { -public: - /* Creates a consumer associated with an input channel. */ - explicit InputConsumer(const sp<InputChannel>& channel); - - /* Destroys the consumer and releases its input channel. */ - ~InputConsumer(); - - /* Gets the underlying input channel. */ - inline sp<InputChannel> getChannel() { return mChannel; } - - /* Consumes an input event from the input channel and copies its contents into - * an InputEvent object created using the specified factory. - * - * Tries to combine a series of move events into larger batches whenever possible. - * - * If consumeBatches is false, then defers consuming pending batched events if it - * is possible for additional samples to be added to them later. Call hasPendingBatch() - * to determine whether a pending batch is available to be consumed. - * - * If consumeBatches is true, then events are still batched but they are consumed - * immediately as soon as the input channel is exhausted. - * - * The frameTime parameter specifies the time when the current display frame started - * rendering in the CLOCK_MONOTONIC time base, or -1 if unknown. - * - * The returned sequence number is never 0 unless the operation failed. - * - * Returns OK on success. - * Returns WOULD_BLOCK if there is no event present. - * Returns DEAD_OBJECT if the channel's peer has been closed. - * Returns NO_MEMORY if the event could not be created. - * Other errors probably indicate that the channel is broken. - */ - status_t consume(InputEventFactoryInterface* factory, bool consumeBatches, - nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent); - - /* Sends a finished signal to the publisher to inform it that the message - * with the specified sequence number has finished being process and whether - * the message was handled by the consumer. - * - * Returns OK on success. - * Returns BAD_VALUE if seq is 0. - * Other errors probably indicate that the channel is broken. - */ - status_t sendFinishedSignal(uint32_t seq, bool handled); - - /* Returns true if there is a deferred event waiting. - * - * Should be called after calling consume() to determine whether the consumer - * has a deferred event to be processed. Deferred events are somewhat special in - * that they have already been removed from the input channel. If the input channel - * becomes empty, the client may need to do extra work to ensure that it processes - * the deferred event despite the fact that the input channel's file descriptor - * is not readable. - * - * One option is simply to call consume() in a loop until it returns WOULD_BLOCK. - * This guarantees that all deferred events will be processed. - * - * Alternately, the caller can call hasDeferredEvent() to determine whether there is - * a deferred event waiting and then ensure that its event loop wakes up at least - * one more time to consume the deferred event. - */ - bool hasDeferredEvent() const; - - /* Returns true if there is a pending batch. - * - * Should be called after calling consume() with consumeBatches == false to determine - * whether consume() should be called again later on with consumeBatches == true. - */ - bool hasPendingBatch() const; - -private: - // True if touch resampling is enabled. - const bool mResampleTouch; - - // The input channel. - sp<InputChannel> mChannel; - - // The current input message. - InputMessage mMsg; - - // True if mMsg contains a valid input message that was deferred from the previous - // call to consume and that still needs to be handled. - bool mMsgDeferred; - - // Batched motion events per device and source. - struct Batch { - Vector<InputMessage> samples; - }; - Vector<Batch> mBatches; - - // Touch state per device and source, only for sources of class pointer. - struct History { - nsecs_t eventTime; - BitSet32 idBits; - int32_t idToIndex[MAX_POINTER_ID + 1]; - PointerCoords pointers[MAX_POINTERS]; - - void initializeFrom(const InputMessage* msg) { - eventTime = msg->body.motion.eventTime; - idBits.clear(); - for (size_t i = 0; i < msg->body.motion.pointerCount; i++) { - uint32_t id = msg->body.motion.pointers[i].properties.id; - idBits.markBit(id); - idToIndex[id] = i; - pointers[i].copyFrom(msg->body.motion.pointers[i].coords); - } - } - - const PointerCoords& getPointerById(uint32_t id) const { - return pointers[idToIndex[id]]; - } - }; - struct TouchState { - int32_t deviceId; - int32_t source; - size_t historyCurrent; - size_t historySize; - History history[2]; - History lastResample; - - void initialize(int32_t deviceId, int32_t source) { - this->deviceId = deviceId; - this->source = source; - historyCurrent = 0; - historySize = 0; - lastResample.eventTime = 0; - lastResample.idBits.clear(); - } - - void addHistory(const InputMessage* msg) { - historyCurrent ^= 1; - if (historySize < 2) { - historySize += 1; - } - history[historyCurrent].initializeFrom(msg); - } - - const History* getHistory(size_t index) const { - return &history[(historyCurrent + index) & 1]; - } - }; - Vector<TouchState> mTouchStates; - - // Chain of batched sequence numbers. When multiple input messages are combined into - // a batch, we append a record here that associates the last sequence number in the - // batch with the previous one. When the finished signal is sent, we traverse the - // chain to individually finish all input messages that were part of the batch. - struct SeqChain { - uint32_t seq; // sequence number of batched input message - uint32_t chain; // sequence number of previous batched input message - }; - Vector<SeqChain> mSeqChains; - - status_t consumeBatch(InputEventFactoryInterface* factory, - nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent); - status_t consumeSamples(InputEventFactoryInterface* factory, - Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent); - - void updateTouchState(InputMessage* msg); - void rewriteMessage(const TouchState& state, InputMessage* msg); - void resampleTouchState(nsecs_t frameTime, MotionEvent* event, - const InputMessage *next); - - ssize_t findBatch(int32_t deviceId, int32_t source) const; - ssize_t findTouchState(int32_t deviceId, int32_t source) const; - - status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled); - - static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg); - static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg); - static void addSample(MotionEvent* event, const InputMessage* msg); - static bool canAddSample(const Batch& batch, const InputMessage* msg); - static ssize_t findSampleNoLaterThan(const Batch& batch, nsecs_t time); - static bool shouldResampleTool(int32_t toolType); - - static bool isTouchResamplingEnabled(); -}; - -} // namespace android - -#endif // _ANDROIDFW_INPUT_TRANSPORT_H diff --git a/widget/gonk/libui/InputWindow.cpp b/widget/gonk/libui/InputWindow.cpp deleted file mode 100644 index 3aea445a0..000000000 --- a/widget/gonk/libui/InputWindow.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputWindow" - -#include "InputWindow.h" - -#include "cutils_log.h" - -namespace android { - -// --- InputWindowInfo --- - -bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const { - return touchableRegion.contains(x, y); -} - -bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { - return x >= frameLeft && x <= frameRight - && y >= frameTop && y <= frameBottom; -} - -bool InputWindowInfo::isTrustedOverlay() const { - return layoutParamsType == TYPE_INPUT_METHOD - || layoutParamsType == TYPE_INPUT_METHOD_DIALOG - || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY; -} - -bool InputWindowInfo::supportsSplitTouch() const { - return layoutParamsFlags & FLAG_SPLIT_TOUCH; -} - - -// --- InputWindowHandle --- - -InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) : - inputApplicationHandle(inputApplicationHandle), mInfo(NULL) { -} - -InputWindowHandle::~InputWindowHandle() { - delete mInfo; -} - -void InputWindowHandle::releaseInfo() { - if (mInfo) { - delete mInfo; - mInfo = NULL; - } -} - -} // namespace android diff --git a/widget/gonk/libui/InputWindow.h b/widget/gonk/libui/InputWindow.h deleted file mode 100644 index cce5fd4fe..000000000 --- a/widget/gonk/libui/InputWindow.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UI_INPUT_WINDOW_H -#define _UI_INPUT_WINDOW_H - -#include "Input.h" -#include "InputTransport.h" -#include <utils/RefBase.h> -#include <utils/Timers.h> -#include <utils/String8.h> - -#include <SkRegion.h> - -#include "InputApplication.h" - -namespace android { - -/* - * Describes the properties of a window that can receive input. - */ -struct InputWindowInfo { - // Window flags from WindowManager.LayoutParams - enum { - FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, - FLAG_DIM_BEHIND = 0x00000002, - FLAG_BLUR_BEHIND = 0x00000004, - FLAG_NOT_FOCUSABLE = 0x00000008, - FLAG_NOT_TOUCHABLE = 0x00000010, - FLAG_NOT_TOUCH_MODAL = 0x00000020, - FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040, - FLAG_KEEP_SCREEN_ON = 0x00000080, - FLAG_LAYOUT_IN_SCREEN = 0x00000100, - FLAG_LAYOUT_NO_LIMITS = 0x00000200, - FLAG_FULLSCREEN = 0x00000400, - FLAG_FORCE_NOT_FULLSCREEN = 0x00000800, - FLAG_DITHER = 0x00001000, - FLAG_SECURE = 0x00002000, - FLAG_SCALED = 0x00004000, - FLAG_IGNORE_CHEEK_PRESSES = 0x00008000, - FLAG_LAYOUT_INSET_DECOR = 0x00010000, - FLAG_ALT_FOCUSABLE_IM = 0x00020000, - FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000, - FLAG_SHOW_WHEN_LOCKED = 0x00080000, - FLAG_SHOW_WALLPAPER = 0x00100000, - FLAG_TURN_SCREEN_ON = 0x00200000, - FLAG_DISMISS_KEYGUARD = 0x00400000, - FLAG_SPLIT_TOUCH = 0x00800000, - FLAG_HARDWARE_ACCELERATED = 0x01000000, - FLAG_HARDWARE_ACCELERATED_SYSTEM = 0x02000000, - FLAG_SLIPPERY = 0x04000000, - FLAG_NEEDS_MENU_KEY = 0x08000000, - FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000, - FLAG_COMPATIBLE_WINDOW = 0x20000000, - FLAG_SYSTEM_ERROR = 0x40000000, - }; - - // Window types from WindowManager.LayoutParams - enum { - FIRST_APPLICATION_WINDOW = 1, - TYPE_BASE_APPLICATION = 1, - TYPE_APPLICATION = 2, - TYPE_APPLICATION_STARTING = 3, - LAST_APPLICATION_WINDOW = 99, - FIRST_SUB_WINDOW = 1000, - TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW, - TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1, - TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2, - TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3, - TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4, - LAST_SUB_WINDOW = 1999, - FIRST_SYSTEM_WINDOW = 2000, - TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW, - TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1, - TYPE_PHONE = FIRST_SYSTEM_WINDOW+2, - TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3, - TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4, - TYPE_TOAST = FIRST_SYSTEM_WINDOW+5, - TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6, - TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7, - TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8, - TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9, - TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10, - TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11, - TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12, - TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13, - TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14, - TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15, - TYPE_DRAG = FIRST_SYSTEM_WINDOW+16, - TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17, - TYPE_POINTER = FIRST_SYSTEM_WINDOW+18, - TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19, - TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20, - TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21, - LAST_SYSTEM_WINDOW = 2999, - }; - - enum { - INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001, - INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002, - INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004, - }; - - sp<InputChannel> inputChannel; - String8 name; - int32_t layoutParamsFlags; - int32_t layoutParamsType; - nsecs_t dispatchingTimeout; - int32_t frameLeft; - int32_t frameTop; - int32_t frameRight; - int32_t frameBottom; - float scaleFactor; - SkRegion touchableRegion; - bool visible; - bool canReceiveKeys; - bool hasFocus; - bool hasWallpaper; - bool paused; - int32_t layer; - int32_t ownerPid; - int32_t ownerUid; - int32_t inputFeatures; - int32_t displayId; - - bool touchableRegionContainsPoint(int32_t x, int32_t y) const; - bool frameContainsPoint(int32_t x, int32_t y) const; - - /* Returns true if the window is of a trusted type that is allowed to silently - * overlay other windows for the purpose of implementing the secure views feature. - * Trusted overlays, such as IME windows, can partly obscure other windows without causing - * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. - */ - bool isTrustedOverlay() const; - - bool supportsSplitTouch() const; -}; - - -/* - * Handle for a window that can receive input. - * - * Used by the native input dispatcher to indirectly refer to the window manager objects - * that describe a window. - */ -class InputWindowHandle : public RefBase { -public: - const sp<InputApplicationHandle> inputApplicationHandle; - - inline const InputWindowInfo* getInfo() const { - return mInfo; - } - - inline sp<InputChannel> getInputChannel() const { - return mInfo ? mInfo->inputChannel : NULL; - } - - inline String8 getName() const { - return mInfo ? mInfo->name : String8("<invalid>"); - } - - inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const { - return mInfo ? mInfo->dispatchingTimeout : defaultValue; - } - - /** - * Requests that the state of this object be updated to reflect - * the most current available information about the application. - * - * This method should only be called from within the input dispatcher's - * critical section. - * - * Returns true on success, or false if the handle is no longer valid. - */ - virtual bool updateInfo() = 0; - - /** - * Releases the storage used by the associated information when it is - * no longer needed. - */ - void releaseInfo(); - -protected: - InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle); - virtual ~InputWindowHandle(); - - InputWindowInfo* mInfo; -}; - -} // namespace android - -#endif // _UI_INPUT_WINDOW_H diff --git a/widget/gonk/libui/KeyCharacterMap.cpp b/widget/gonk/libui/KeyCharacterMap.cpp deleted file mode 100644 index cec0666ce..000000000 --- a/widget/gonk/libui/KeyCharacterMap.cpp +++ /dev/null @@ -1,1153 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "KeyCharacterMap" -#include "cutils_log.h" - -#include <stdlib.h> -#include <string.h> -#include "android_keycodes.h" -#include "Keyboard.h" -#include "KeyCharacterMap.h" - -#if HAVE_ANDROID_OS -#include <binder/Parcel.h> -#endif - -#include <utils/Errors.h> -#include "Tokenizer.h" -#include <utils/Timers.h> - -// Enables debug output for the parser. -#define DEBUG_PARSER 0 - -// Enables debug output for parser performance. -#define DEBUG_PARSER_PERFORMANCE 0 - -// Enables debug output for mapping. -#define DEBUG_MAPPING 0 - - -namespace android { - -static const char* WHITESPACE = " \t\r"; -static const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r,:"; - -struct Modifier { - const char* label; - int32_t metaState; -}; -static const Modifier modifiers[] = { - { "shift", AMETA_SHIFT_ON }, - { "lshift", AMETA_SHIFT_LEFT_ON }, - { "rshift", AMETA_SHIFT_RIGHT_ON }, - { "alt", AMETA_ALT_ON }, - { "lalt", AMETA_ALT_LEFT_ON }, - { "ralt", AMETA_ALT_RIGHT_ON }, - { "ctrl", AMETA_CTRL_ON }, - { "lctrl", AMETA_CTRL_LEFT_ON }, - { "rctrl", AMETA_CTRL_RIGHT_ON }, - { "meta", AMETA_META_ON }, - { "lmeta", AMETA_META_LEFT_ON }, - { "rmeta", AMETA_META_RIGHT_ON }, - { "sym", AMETA_SYM_ON }, - { "fn", AMETA_FUNCTION_ON }, - { "capslock", AMETA_CAPS_LOCK_ON }, - { "numlock", AMETA_NUM_LOCK_ON }, - { "scrolllock", AMETA_SCROLL_LOCK_ON }, -}; - -#if DEBUG_MAPPING -static String8 toString(const char16_t* chars, size_t numChars) { - String8 result; - for (size_t i = 0; i < numChars; i++) { - result.appendFormat(i == 0 ? "%d" : ", %d", chars[i]); - } - return result; -} -#endif - - -// --- KeyCharacterMap --- - -sp<KeyCharacterMap> KeyCharacterMap::sEmpty = new KeyCharacterMap(); - -KeyCharacterMap::KeyCharacterMap() : - mType(KEYBOARD_TYPE_UNKNOWN) { -} - -KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) : - RefBase(), mType(other.mType), mKeysByScanCode(other.mKeysByScanCode), - mKeysByUsageCode(other.mKeysByUsageCode) { - for (size_t i = 0; i < other.mKeys.size(); i++) { - mKeys.add(other.mKeys.keyAt(i), new Key(*other.mKeys.valueAt(i))); - } -} - -KeyCharacterMap::~KeyCharacterMap() { - for (size_t i = 0; i < mKeys.size(); i++) { - Key* key = mKeys.editValueAt(i); - delete key; - } -} - -status_t KeyCharacterMap::load(const String8& filename, - Format format, sp<KeyCharacterMap>* outMap) { - outMap->clear(); - - Tokenizer* tokenizer; - status_t status = Tokenizer::open(filename, &tokenizer); - if (status) { - ALOGE("Error %d opening key character map file %s.", status, filename.string()); - } else { - status = load(tokenizer, format, outMap); - delete tokenizer; - } - return status; -} - -status_t KeyCharacterMap::loadContents(const String8& filename, const char* contents, - Format format, sp<KeyCharacterMap>* outMap) { - outMap->clear(); - - Tokenizer* tokenizer; - status_t status = Tokenizer::fromContents(filename, contents, &tokenizer); - if (status) { - ALOGE("Error %d opening key character map.", status); - } else { - status = load(tokenizer, format, outMap); - delete tokenizer; - } - return status; -} - -status_t KeyCharacterMap::load(Tokenizer* tokenizer, - Format format, sp<KeyCharacterMap>* outMap) { - status_t status = OK; - sp<KeyCharacterMap> map = new KeyCharacterMap(); - if (!map.get()) { - ALOGE("Error allocating key character map."); - status = NO_MEMORY; - } else { -#if DEBUG_PARSER_PERFORMANCE - nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); -#endif - Parser parser(map.get(), tokenizer, format); - status = parser.parse(); -#if DEBUG_PARSER_PERFORMANCE - nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; - ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", - tokenizer->getFilename().string(), tokenizer->getLineNumber(), - elapsedTime / 1000000.0); -#endif - if (!status) { - *outMap = map; - } - } - return status; -} - -sp<KeyCharacterMap> KeyCharacterMap::combine(const sp<KeyCharacterMap>& base, - const sp<KeyCharacterMap>& overlay) { - if (overlay == NULL) { - return base; - } - if (base == NULL) { - return overlay; - } - - sp<KeyCharacterMap> map = new KeyCharacterMap(*base.get()); - for (size_t i = 0; i < overlay->mKeys.size(); i++) { - int32_t keyCode = overlay->mKeys.keyAt(i); - Key* key = overlay->mKeys.valueAt(i); - ssize_t oldIndex = map->mKeys.indexOfKey(keyCode); - if (oldIndex >= 0) { - delete map->mKeys.valueAt(oldIndex); - map->mKeys.editValueAt(oldIndex) = new Key(*key); - } else { - map->mKeys.add(keyCode, new Key(*key)); - } - } - - for (size_t i = 0; i < overlay->mKeysByScanCode.size(); i++) { - map->mKeysByScanCode.replaceValueFor(overlay->mKeysByScanCode.keyAt(i), - overlay->mKeysByScanCode.valueAt(i)); - } - - for (size_t i = 0; i < overlay->mKeysByUsageCode.size(); i++) { - map->mKeysByUsageCode.replaceValueFor(overlay->mKeysByUsageCode.keyAt(i), - overlay->mKeysByUsageCode.valueAt(i)); - } - return map; -} - -sp<KeyCharacterMap> KeyCharacterMap::empty() { - return sEmpty; -} - -int32_t KeyCharacterMap::getKeyboardType() const { - return mType; -} - -char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const { - char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { - result = key->label; - } -#if DEBUG_MAPPING - ALOGD("getDisplayLabel: keyCode=%d ~ Result %d.", keyCode, result); -#endif - return result; -} - -char16_t KeyCharacterMap::getNumber(int32_t keyCode) const { - char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { - result = key->number; - } -#if DEBUG_MAPPING - ALOGD("getNumber: keyCode=%d ~ Result %d.", keyCode, result); -#endif - return result; -} - -char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const { - char16_t result = 0; - const Key* key; - const Behavior* behavior; - if (getKeyBehavior(keyCode, metaState, &key, &behavior)) { - result = behavior->character; - } -#if DEBUG_MAPPING - ALOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result); -#endif - return result; -} - -bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState, - FallbackAction* outFallbackAction) const { - outFallbackAction->keyCode = 0; - outFallbackAction->metaState = 0; - - bool result = false; - const Key* key; - const Behavior* behavior; - if (getKeyBehavior(keyCode, metaState, &key, &behavior)) { - if (behavior->fallbackKeyCode) { - outFallbackAction->keyCode = behavior->fallbackKeyCode; - outFallbackAction->metaState = metaState & ~behavior->metaState; - result = true; - } - } -#if DEBUG_MAPPING - ALOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, " - "fallback keyCode=%d, fallback metaState=0x%08x.", - keyCode, metaState, result ? "true" : "false", - outFallbackAction->keyCode, outFallbackAction->metaState); -#endif - return result; -} - -char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars, - int32_t metaState) const { - char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { - // Try to find the most general behavior that maps to this character. - // For example, the base key behavior will usually be last in the list. - // However, if we find a perfect meta state match for one behavior then use that one. - for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) { - if (behavior->character) { - for (size_t i = 0; i < numChars; i++) { - if (behavior->character == chars[i]) { - result = behavior->character; - if ((behavior->metaState & metaState) == behavior->metaState) { - goto ExactMatch; - } - break; - } - } - } - } - ExactMatch: ; - } -#if DEBUG_MAPPING - ALOGD("getMatch: keyCode=%d, chars=[%s], metaState=0x%08x ~ Result %d.", - keyCode, toString(chars, numChars).string(), metaState, result); -#endif - return result; -} - -bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, - Vector<KeyEvent>& outEvents) const { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - - for (size_t i = 0; i < numChars; i++) { - int32_t keyCode, metaState; - char16_t ch = chars[i]; - if (!findKey(ch, &keyCode, &metaState)) { -#if DEBUG_MAPPING - ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Failed to find mapping for character %d.", - deviceId, toString(chars, numChars).string(), ch); -#endif - return false; - } - - int32_t currentMetaState = 0; - addMetaKeys(outEvents, deviceId, metaState, true, now, ¤tMetaState); - addKey(outEvents, deviceId, keyCode, currentMetaState, true, now); - addKey(outEvents, deviceId, keyCode, currentMetaState, false, now); - addMetaKeys(outEvents, deviceId, metaState, false, now, ¤tMetaState); - } -#if DEBUG_MAPPING - ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.", - deviceId, toString(chars, numChars).string(), int32_t(outEvents.size())); - for (size_t i = 0; i < outEvents.size(); i++) { - ALOGD(" Key: keyCode=%d, metaState=0x%08x, %s.", - outEvents[i].getKeyCode(), outEvents[i].getMetaState(), - outEvents[i].getAction() == AKEY_EVENT_ACTION_DOWN ? "down" : "up"); - } -#endif - return true; -} - -status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const { - if (usageCode) { - ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); - if (index >= 0) { -#if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.", - scanCode, usageCode, *outKeyCode); -#endif - *outKeyCode = mKeysByUsageCode.valueAt(index); - return OK; - } - } - if (scanCode) { - ssize_t index = mKeysByScanCode.indexOfKey(scanCode); - if (index >= 0) { -#if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.", - scanCode, usageCode, *outKeyCode); -#endif - *outKeyCode = mKeysByScanCode.valueAt(index); - return OK; - } - } - -#if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode); -#endif - *outKeyCode = AKEYCODE_UNKNOWN; - return NAME_NOT_FOUND; -} - -bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const { - ssize_t index = mKeys.indexOfKey(keyCode); - if (index >= 0) { - *outKey = mKeys.valueAt(index); - return true; - } - return false; -} - -bool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState, - const Key** outKey, const Behavior** outBehavior) const { - const Key* key; - if (getKey(keyCode, &key)) { - const Behavior* behavior = key->firstBehavior; - while (behavior) { - if (matchesMetaState(metaState, behavior->metaState)) { - *outKey = key; - *outBehavior = behavior; - return true; - } - behavior = behavior->next; - } - } - return false; -} - -bool KeyCharacterMap::matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState) { - // Behavior must have at least the set of meta states specified. - // And if the key event has CTRL, ALT or META then the behavior must exactly - // match those, taking into account that a behavior can specify that it handles - // one, both or either of a left/right modifier pair. - if ((eventMetaState & behaviorMetaState) == behaviorMetaState) { - const int32_t EXACT_META_STATES = - AMETA_CTRL_ON | AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON - | AMETA_ALT_ON | AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON - | AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON; - int32_t unmatchedMetaState = eventMetaState & ~behaviorMetaState & EXACT_META_STATES; - if (behaviorMetaState & AMETA_CTRL_ON) { - unmatchedMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON); - } else if (behaviorMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) { - unmatchedMetaState &= ~AMETA_CTRL_ON; - } - if (behaviorMetaState & AMETA_ALT_ON) { - unmatchedMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON); - } else if (behaviorMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { - unmatchedMetaState &= ~AMETA_ALT_ON; - } - if (behaviorMetaState & AMETA_META_ON) { - unmatchedMetaState &= ~(AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON); - } else if (behaviorMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) { - unmatchedMetaState &= ~AMETA_META_ON; - } - return !unmatchedMetaState; - } - return false; -} - -bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const { - if (!ch) { - return false; - } - - for (size_t i = 0; i < mKeys.size(); i++) { - const Key* key = mKeys.valueAt(i); - - // Try to find the most general behavior that maps to this character. - // For example, the base key behavior will usually be last in the list. - const Behavior* found = NULL; - for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) { - if (behavior->character == ch) { - found = behavior; - } - } - if (found) { - *outKeyCode = mKeys.keyAt(i); - *outMetaState = found->metaState; - return true; - } - } - return false; -} - -void KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) { - outEvents.push(); - KeyEvent& event = outEvents.editTop(); - event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, - down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, - 0, keyCode, 0, metaState, 0, time, time); -} - -void KeyCharacterMap::addMetaKeys(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t* currentMetaState) { - // Add and remove meta keys symmetrically. - if (down) { - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState); - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState); - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState); - - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON, - AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON, - AMETA_SHIFT_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON, - AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON, - AMETA_ALT_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON, - AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON, - AMETA_CTRL_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_META_LEFT, AMETA_META_LEFT_ON, - AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON, - AMETA_META_ON, currentMetaState); - - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState); - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState); - } else { - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState); - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState); - - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_META_LEFT, AMETA_META_LEFT_ON, - AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON, - AMETA_META_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON, - AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON, - AMETA_CTRL_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON, - AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON, - AMETA_ALT_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON, - AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON, - AMETA_SHIFT_ON, currentMetaState); - - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState); - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState); - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState); - } -} - -bool KeyCharacterMap::addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t keyCode, int32_t keyMetaState, - int32_t* currentMetaState) { - if ((metaState & keyMetaState) == keyMetaState) { - *currentMetaState = updateMetaState(keyCode, down, *currentMetaState); - addKey(outEvents, deviceId, keyCode, *currentMetaState, down, time); - return true; - } - return false; -} - -void KeyCharacterMap::addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t leftKeyCode, int32_t leftKeyMetaState, - int32_t rightKeyCode, int32_t rightKeyMetaState, - int32_t eitherKeyMetaState, - int32_t* currentMetaState) { - bool specific = false; - specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, - leftKeyCode, leftKeyMetaState, currentMetaState); - specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, - rightKeyCode, rightKeyMetaState, currentMetaState); - - if (!specific) { - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, - leftKeyCode, eitherKeyMetaState, currentMetaState); - } -} - -void KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, nsecs_t time, - int32_t keyCode, int32_t keyMetaState, - int32_t* currentMetaState) { - if ((metaState & keyMetaState) == keyMetaState) { - *currentMetaState = updateMetaState(keyCode, true, *currentMetaState); - addKey(outEvents, deviceId, keyCode, *currentMetaState, true, time); - *currentMetaState = updateMetaState(keyCode, false, *currentMetaState); - addKey(outEvents, deviceId, keyCode, *currentMetaState, false, time); - } -} - -#if HAVE_ANDROID_OS -sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { - sp<KeyCharacterMap> map = new KeyCharacterMap(); - map->mType = parcel->readInt32(); - size_t numKeys = parcel->readInt32(); - if (parcel->errorCheck()) { - return NULL; - } - - for (size_t i = 0; i < numKeys; i++) { - int32_t keyCode = parcel->readInt32(); - char16_t label = parcel->readInt32(); - char16_t number = parcel->readInt32(); - if (parcel->errorCheck()) { - return NULL; - } - - Key* key = new Key(); - key->label = label; - key->number = number; - map->mKeys.add(keyCode, key); - - Behavior* lastBehavior = NULL; - while (parcel->readInt32()) { - int32_t metaState = parcel->readInt32(); - char16_t character = parcel->readInt32(); - int32_t fallbackKeyCode = parcel->readInt32(); - if (parcel->errorCheck()) { - return NULL; - } - - Behavior* behavior = new Behavior(); - behavior->metaState = metaState; - behavior->character = character; - behavior->fallbackKeyCode = fallbackKeyCode; - if (lastBehavior) { - lastBehavior->next = behavior; - } else { - key->firstBehavior = behavior; - } - lastBehavior = behavior; - } - - if (parcel->errorCheck()) { - return NULL; - } - } - return map; -} - -void KeyCharacterMap::writeToParcel(Parcel* parcel) const { - parcel->writeInt32(mType); - - size_t numKeys = mKeys.size(); - parcel->writeInt32(numKeys); - for (size_t i = 0; i < numKeys; i++) { - int32_t keyCode = mKeys.keyAt(i); - const Key* key = mKeys.valueAt(i); - parcel->writeInt32(keyCode); - parcel->writeInt32(key->label); - parcel->writeInt32(key->number); - for (const Behavior* behavior = key->firstBehavior; behavior != NULL; - behavior = behavior->next) { - parcel->writeInt32(1); - parcel->writeInt32(behavior->metaState); - parcel->writeInt32(behavior->character); - parcel->writeInt32(behavior->fallbackKeyCode); - } - parcel->writeInt32(0); - } -} -#endif - - -// --- KeyCharacterMap::Key --- - -KeyCharacterMap::Key::Key() : - label(0), number(0), firstBehavior(NULL) { -} - -KeyCharacterMap::Key::Key(const Key& other) : - label(other.label), number(other.number), - firstBehavior(other.firstBehavior ? new Behavior(*other.firstBehavior) : NULL) { -} - -KeyCharacterMap::Key::~Key() { - Behavior* behavior = firstBehavior; - while (behavior) { - Behavior* next = behavior->next; - delete behavior; - behavior = next; - } -} - - -// --- KeyCharacterMap::Behavior --- - -KeyCharacterMap::Behavior::Behavior() : - next(NULL), metaState(0), character(0), fallbackKeyCode(0) { -} - -KeyCharacterMap::Behavior::Behavior(const Behavior& other) : - next(other.next ? new Behavior(*other.next) : NULL), - metaState(other.metaState), character(other.character), - fallbackKeyCode(other.fallbackKeyCode) { -} - - -// --- KeyCharacterMap::Parser --- - -KeyCharacterMap::Parser::Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format) : - mMap(map), mTokenizer(tokenizer), mFormat(format), mState(STATE_TOP) { -} - -KeyCharacterMap::Parser::~Parser() { -} - -status_t KeyCharacterMap::Parser::parse() { - while (!mTokenizer->isEof()) { -#if DEBUG_PARSER - ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); -#endif - - mTokenizer->skipDelimiters(WHITESPACE); - - if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { - switch (mState) { - case STATE_TOP: { - String8 keywordToken = mTokenizer->nextToken(WHITESPACE); - if (keywordToken == "type") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseType(); - if (status) return status; - } else if (keywordToken == "map") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseMap(); - if (status) return status; - } else if (keywordToken == "key") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseKey(); - if (status) return status; - } else { - ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), - keywordToken.string()); - return BAD_VALUE; - } - break; - } - - case STATE_KEY: { - status_t status = parseKeyProperty(); - if (status) return status; - break; - } - } - - mTokenizer->skipDelimiters(WHITESPACE); - if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { - ALOGE("%s: Expected end of line or trailing comment, got '%s'.", - mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); - return BAD_VALUE; - } - } - - mTokenizer->nextLine(); - } - - if (mState != STATE_TOP) { - ALOGE("%s: Unterminated key description at end of file.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - if (mMap->mType == KEYBOARD_TYPE_UNKNOWN) { - ALOGE("%s: Keyboard layout missing required keyboard 'type' declaration.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - if (mFormat == FORMAT_BASE) { - if (mMap->mType == KEYBOARD_TYPE_OVERLAY) { - ALOGE("%s: Base keyboard layout must specify a keyboard 'type' other than 'OVERLAY'.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - } else if (mFormat == FORMAT_OVERLAY) { - if (mMap->mType != KEYBOARD_TYPE_OVERLAY) { - ALOGE("%s: Overlay keyboard layout missing required keyboard " - "'type OVERLAY' declaration.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - } - - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseType() { - if (mMap->mType != KEYBOARD_TYPE_UNKNOWN) { - ALOGE("%s: Duplicate keyboard 'type' declaration.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - KeyboardType type; - String8 typeToken = mTokenizer->nextToken(WHITESPACE); - if (typeToken == "NUMERIC") { - type = KEYBOARD_TYPE_NUMERIC; - } else if (typeToken == "PREDICTIVE") { - type = KEYBOARD_TYPE_PREDICTIVE; - } else if (typeToken == "ALPHA") { - type = KEYBOARD_TYPE_ALPHA; - } else if (typeToken == "FULL") { - type = KEYBOARD_TYPE_FULL; - } else if (typeToken == "SPECIAL_FUNCTION") { - type = KEYBOARD_TYPE_SPECIAL_FUNCTION; - } else if (typeToken == "OVERLAY") { - type = KEYBOARD_TYPE_OVERLAY; - } else { - ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(), - typeToken.string()); - return BAD_VALUE; - } - -#if DEBUG_PARSER - ALOGD("Parsed type: type=%d.", type); -#endif - mMap->mType = type; - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseMap() { - String8 keywordToken = mTokenizer->nextToken(WHITESPACE); - if (keywordToken == "key") { - mTokenizer->skipDelimiters(WHITESPACE); - return parseMapKey(); - } - ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(), - keywordToken.string()); - return BAD_VALUE; -} - -status_t KeyCharacterMap::Parser::parseMapKey() { - String8 codeToken = mTokenizer->nextToken(WHITESPACE); - bool mapUsage = false; - if (codeToken == "usage") { - mapUsage = true; - mTokenizer->skipDelimiters(WHITESPACE); - codeToken = mTokenizer->nextToken(WHITESPACE); - } - - char* end; - int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(), - mapUsage ? "usage" : "scan code", codeToken.string()); - return BAD_VALUE; - } - KeyedVector<int32_t, int32_t>& map = - mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; - if (map.indexOfKey(code) >= 0) { - ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(), - mapUsage ? "usage" : "scan code", codeToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); - if (!keyCode) { - ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), - keyCodeToken.string()); - return BAD_VALUE; - } - -#if DEBUG_PARSER - ALOGD("Parsed map key %s: code=%d, keyCode=%d.", - mapUsage ? "usage" : "scan code", code, keyCode); -#endif - map.add(code, keyCode); - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseKey() { - String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); - if (!keyCode) { - ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), - keyCodeToken.string()); - return BAD_VALUE; - } - if (mMap->mKeys.indexOfKey(keyCode) >= 0) { - ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(), - keyCodeToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 openBraceToken = mTokenizer->nextToken(WHITESPACE); - if (openBraceToken != "{") { - ALOGE("%s: Expected '{' after key code label, got '%s'.", - mTokenizer->getLocation().string(), openBraceToken.string()); - return BAD_VALUE; - } - -#if DEBUG_PARSER - ALOGD("Parsed beginning of key: keyCode=%d.", keyCode); -#endif - mKeyCode = keyCode; - mMap->mKeys.add(keyCode, new Key()); - mState = STATE_KEY; - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseKeyProperty() { - Key* key = mMap->mKeys.valueFor(mKeyCode); - String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER); - if (token == "}") { - mState = STATE_TOP; - return finishKey(key); - } - - Vector<Property> properties; - - // Parse all comma-delimited property names up to the first colon. - for (;;) { - if (token == "label") { - properties.add(Property(PROPERTY_LABEL)); - } else if (token == "number") { - properties.add(Property(PROPERTY_NUMBER)); - } else { - int32_t metaState; - status_t status = parseModifier(token, &metaState); - if (status) { - ALOGE("%s: Expected a property name or modifier, got '%s'.", - mTokenizer->getLocation().string(), token.string()); - return status; - } - properties.add(Property(PROPERTY_META, metaState)); - } - - mTokenizer->skipDelimiters(WHITESPACE); - if (!mTokenizer->isEol()) { - char ch = mTokenizer->nextChar(); - if (ch == ':') { - break; - } else if (ch == ',') { - mTokenizer->skipDelimiters(WHITESPACE); - token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER); - continue; - } - } - - ALOGE("%s: Expected ',' or ':' after property name.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - // Parse behavior after the colon. - mTokenizer->skipDelimiters(WHITESPACE); - - Behavior behavior; - bool haveCharacter = false; - bool haveFallback = false; - - do { - char ch = mTokenizer->peekChar(); - if (ch == '\'') { - char16_t character; - status_t status = parseCharacterLiteral(&character); - if (status || !character) { - ALOGE("%s: Invalid character literal for key.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - if (haveCharacter) { - ALOGE("%s: Cannot combine multiple character literals or 'none'.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - behavior.character = character; - haveCharacter = true; - } else { - token = mTokenizer->nextToken(WHITESPACE); - if (token == "none") { - if (haveCharacter) { - ALOGE("%s: Cannot combine multiple character literals or 'none'.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - haveCharacter = true; - } else if (token == "fallback") { - mTokenizer->skipDelimiters(WHITESPACE); - token = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(token.string()); - if (!keyCode) { - ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.", - mTokenizer->getLocation().string(), - token.string()); - return BAD_VALUE; - } - if (haveFallback) { - ALOGE("%s: Cannot combine multiple fallback key codes.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - behavior.fallbackKeyCode = keyCode; - haveFallback = true; - } else { - ALOGE("%s: Expected a key behavior after ':'.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - } - - mTokenizer->skipDelimiters(WHITESPACE); - } while (!mTokenizer->isEol() && mTokenizer->peekChar() != '#'); - - // Add the behavior. - for (size_t i = 0; i < properties.size(); i++) { - const Property& property = properties.itemAt(i); - switch (property.property) { - case PROPERTY_LABEL: - if (key->label) { - ALOGE("%s: Duplicate label for key.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - key->label = behavior.character; -#if DEBUG_PARSER - ALOGD("Parsed key label: keyCode=%d, label=%d.", mKeyCode, key->label); -#endif - break; - case PROPERTY_NUMBER: - if (key->number) { - ALOGE("%s: Duplicate number for key.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - key->number = behavior.character; -#if DEBUG_PARSER - ALOGD("Parsed key number: keyCode=%d, number=%d.", mKeyCode, key->number); -#endif - break; - case PROPERTY_META: { - for (Behavior* b = key->firstBehavior; b; b = b->next) { - if (b->metaState == property.metaState) { - ALOGE("%s: Duplicate key behavior for modifier.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - } - Behavior* newBehavior = new Behavior(behavior); - newBehavior->metaState = property.metaState; - newBehavior->next = key->firstBehavior; - key->firstBehavior = newBehavior; -#if DEBUG_PARSER - ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d.", mKeyCode, - newBehavior->metaState, newBehavior->character, newBehavior->fallbackKeyCode); -#endif - break; - } - } - } - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::finishKey(Key* key) { - // Fill in default number property. - if (!key->number) { - char16_t digit = 0; - char16_t symbol = 0; - for (Behavior* b = key->firstBehavior; b; b = b->next) { - char16_t ch = b->character; - if (ch) { - if (ch >= '0' && ch <= '9') { - digit = ch; - } else if (ch == '(' || ch == ')' || ch == '#' || ch == '*' - || ch == '-' || ch == '+' || ch == ',' || ch == '.' - || ch == '\'' || ch == ':' || ch == ';' || ch == '/') { - symbol = ch; - } - } - } - key->number = digit ? digit : symbol; - } - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseModifier(const String8& token, int32_t* outMetaState) { - if (token == "base") { - *outMetaState = 0; - return NO_ERROR; - } - - int32_t combinedMeta = 0; - - const char* str = token.string(); - const char* start = str; - for (const char* cur = str; ; cur++) { - char ch = *cur; - if (ch == '+' || ch == '\0') { - size_t len = cur - start; - int32_t metaState = 0; - for (size_t i = 0; i < sizeof(modifiers) / sizeof(Modifier); i++) { - if (strlen(modifiers[i].label) == len - && strncmp(modifiers[i].label, start, len) == 0) { - metaState = modifiers[i].metaState; - break; - } - } - if (!metaState) { - return BAD_VALUE; - } - if (combinedMeta & metaState) { - ALOGE("%s: Duplicate modifier combination '%s'.", - mTokenizer->getLocation().string(), token.string()); - return BAD_VALUE; - } - - combinedMeta |= metaState; - start = cur + 1; - - if (ch == '\0') { - break; - } - } - } - *outMetaState = combinedMeta; - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseCharacterLiteral(char16_t* outCharacter) { - char ch = mTokenizer->nextChar(); - if (ch != '\'') { - goto Error; - } - - ch = mTokenizer->nextChar(); - if (ch == '\\') { - // Escape sequence. - ch = mTokenizer->nextChar(); - if (ch == 'n') { - *outCharacter = '\n'; - } else if (ch == 't') { - *outCharacter = '\t'; - } else if (ch == '\\') { - *outCharacter = '\\'; - } else if (ch == '\'') { - *outCharacter = '\''; - } else if (ch == '"') { - *outCharacter = '"'; - } else if (ch == 'u') { - *outCharacter = 0; - for (int i = 0; i < 4; i++) { - ch = mTokenizer->nextChar(); - int digit; - if (ch >= '0' && ch <= '9') { - digit = ch - '0'; - } else if (ch >= 'A' && ch <= 'F') { - digit = ch - 'A' + 10; - } else if (ch >= 'a' && ch <= 'f') { - digit = ch - 'a' + 10; - } else { - goto Error; - } - *outCharacter = (*outCharacter << 4) | digit; - } - } else { - goto Error; - } - } else if (ch >= 32 && ch <= 126 && ch != '\'') { - // ASCII literal character. - *outCharacter = ch; - } else { - goto Error; - } - - ch = mTokenizer->nextChar(); - if (ch != '\'') { - goto Error; - } - - // Ensure that we consumed the entire token. - if (mTokenizer->nextToken(WHITESPACE).isEmpty()) { - return NO_ERROR; - } - -Error: - ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string()); - return BAD_VALUE; -} - -} // namespace android diff --git a/widget/gonk/libui/KeyCharacterMap.h b/widget/gonk/libui/KeyCharacterMap.h deleted file mode 100644 index c7a684105..000000000 --- a/widget/gonk/libui/KeyCharacterMap.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_KEY_CHARACTER_MAP_H -#define _ANDROIDFW_KEY_CHARACTER_MAP_H - -#include <stdint.h> - -#if HAVE_ANDROID_OS -#include <binder/IBinder.h> -#endif - -#include "Input.h" -#include <utils/Errors.h> -#include <utils/KeyedVector.h> -#include "Tokenizer.h" -#include <utils/String8.h> -#include <utils/Unicode.h> -#include <utils/RefBase.h> - -namespace android { - -/** - * Describes a mapping from Android key codes to characters. - * Also specifies other functions of the keyboard such as the keyboard type - * and key modifier semantics. - * - * This object is immutable after it has been loaded. - */ -class KeyCharacterMap : public RefBase { -public: - enum KeyboardType { - KEYBOARD_TYPE_UNKNOWN = 0, - KEYBOARD_TYPE_NUMERIC = 1, - KEYBOARD_TYPE_PREDICTIVE = 2, - KEYBOARD_TYPE_ALPHA = 3, - KEYBOARD_TYPE_FULL = 4, - KEYBOARD_TYPE_SPECIAL_FUNCTION = 5, - KEYBOARD_TYPE_OVERLAY = 6, - }; - - enum Format { - // Base keyboard layout, may contain device-specific options, such as "type" declaration. - FORMAT_BASE = 0, - // Overlay keyboard layout, more restrictive, may be published by applications, - // cannot override device-specific options. - FORMAT_OVERLAY = 1, - // Either base or overlay layout ok. - FORMAT_ANY = 2, - }; - - // Substitute key code and meta state for fallback action. - struct FallbackAction { - int32_t keyCode; - int32_t metaState; - }; - - /* Loads a key character map from a file. */ - static status_t load(const String8& filename, Format format, sp<KeyCharacterMap>* outMap); - - /* Loads a key character map from its string contents. */ - static status_t loadContents(const String8& filename, - const char* contents, Format format, sp<KeyCharacterMap>* outMap); - - /* Combines a base key character map and an overlay. */ - static sp<KeyCharacterMap> combine(const sp<KeyCharacterMap>& base, - const sp<KeyCharacterMap>& overlay); - - /* Returns an empty key character map. */ - static sp<KeyCharacterMap> empty(); - - /* Gets the keyboard type. */ - int32_t getKeyboardType() const; - - /* Gets the primary character for this key as in the label physically printed on it. - * Returns 0 if none (eg. for non-printing keys). */ - char16_t getDisplayLabel(int32_t keyCode) const; - - /* Gets the Unicode character for the number or symbol generated by the key - * when the keyboard is used as a dialing pad. - * Returns 0 if no number or symbol is generated. - */ - char16_t getNumber(int32_t keyCode) const; - - /* Gets the Unicode character generated by the key and meta key modifiers. - * Returns 0 if no character is generated. - */ - char16_t getCharacter(int32_t keyCode, int32_t metaState) const; - - /* Gets the fallback action to use by default if the application does not - * handle the specified key. - * Returns true if an action was available, false if none. - */ - bool getFallbackAction(int32_t keyCode, int32_t metaState, - FallbackAction* outFallbackAction) const; - - /* Gets the first matching Unicode character that can be generated by the key, - * preferring the one with the specified meta key modifiers. - * Returns 0 if no matching character is generated. - */ - char16_t getMatch(int32_t keyCode, const char16_t* chars, - size_t numChars, int32_t metaState) const; - - /* Gets a sequence of key events that could plausibly generate the specified - * character sequence. Returns false if some of the characters cannot be generated. - */ - bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, - Vector<KeyEvent>& outEvents) const; - - /* Maps a scan code and usage code to a key code, in case this key map overrides - * the mapping in some way. */ - status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const; - -#if HAVE_ANDROID_OS - /* Reads a key map from a parcel. */ - static sp<KeyCharacterMap> readFromParcel(Parcel* parcel); - - /* Writes a key map to a parcel. */ - void writeToParcel(Parcel* parcel) const; -#endif - -protected: - virtual ~KeyCharacterMap(); - -private: - struct Behavior { - Behavior(); - Behavior(const Behavior& other); - - /* The next behavior in the list, or NULL if none. */ - Behavior* next; - - /* The meta key modifiers for this behavior. */ - int32_t metaState; - - /* The character to insert. */ - char16_t character; - - /* The fallback keycode if the key is not handled. */ - int32_t fallbackKeyCode; - }; - - struct Key { - Key(); - Key(const Key& other); - ~Key(); - - /* The single character label printed on the key, or 0 if none. */ - char16_t label; - - /* The number or symbol character generated by the key, or 0 if none. */ - char16_t number; - - /* The list of key behaviors sorted from most specific to least specific - * meta key binding. */ - Behavior* firstBehavior; - }; - - class Parser { - enum State { - STATE_TOP = 0, - STATE_KEY = 1, - }; - - enum { - PROPERTY_LABEL = 1, - PROPERTY_NUMBER = 2, - PROPERTY_META = 3, - }; - - struct Property { - inline Property(int32_t property = 0, int32_t metaState = 0) : - property(property), metaState(metaState) { } - - int32_t property; - int32_t metaState; - }; - - KeyCharacterMap* mMap; - Tokenizer* mTokenizer; - Format mFormat; - State mState; - int32_t mKeyCode; - - public: - Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format); - ~Parser(); - status_t parse(); - - private: - status_t parseType(); - status_t parseMap(); - status_t parseMapKey(); - status_t parseKey(); - status_t parseKeyProperty(); - status_t finishKey(Key* key); - status_t parseModifier(const String8& token, int32_t* outMetaState); - status_t parseCharacterLiteral(char16_t* outCharacter); - }; - - static sp<KeyCharacterMap> sEmpty; - - KeyedVector<int32_t, Key*> mKeys; - int mType; - - KeyedVector<int32_t, int32_t> mKeysByScanCode; - KeyedVector<int32_t, int32_t> mKeysByUsageCode; - - KeyCharacterMap(); - KeyCharacterMap(const KeyCharacterMap& other); - - bool getKey(int32_t keyCode, const Key** outKey) const; - bool getKeyBehavior(int32_t keyCode, int32_t metaState, - const Key** outKey, const Behavior** outBehavior) const; - static bool matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState); - - bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const; - - static status_t load(Tokenizer* tokenizer, Format format, sp<KeyCharacterMap>* outMap); - - static void addKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time); - static void addMetaKeys(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t* currentMetaState); - static bool addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t keyCode, int32_t keyMetaState, - int32_t* currentMetaState); - static void addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t leftKeyCode, int32_t leftKeyMetaState, - int32_t rightKeyCode, int32_t rightKeyMetaState, - int32_t eitherKeyMetaState, - int32_t* currentMetaState); - static void addLockedMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, nsecs_t time, - int32_t keyCode, int32_t keyMetaState, - int32_t* currentMetaState); -}; - -} // namespace android - -#endif // _ANDROIDFW_KEY_CHARACTER_MAP_H diff --git a/widget/gonk/libui/KeyLayoutMap.cpp b/widget/gonk/libui/KeyLayoutMap.cpp deleted file mode 100644 index 8af4b84e0..000000000 --- a/widget/gonk/libui/KeyLayoutMap.cpp +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "KeyLayoutMap" -#include "cutils_log.h" - -#include <stdlib.h> -#include "android_keycodes.h" -#include "Keyboard.h" -#include "KeyLayoutMap.h" -#include <utils/Errors.h> -#include "Tokenizer.h" -#include <utils/Timers.h> - -// Enables debug output for the parser. -#define DEBUG_PARSER 0 - -// Enables debug output for parser performance. -#define DEBUG_PARSER_PERFORMANCE 0 - -// Enables debug output for mapping. -#define DEBUG_MAPPING 0 - - -namespace android { - -static const char* WHITESPACE = " \t\r"; - -// --- KeyLayoutMap --- - -KeyLayoutMap::KeyLayoutMap() { -} - -KeyLayoutMap::~KeyLayoutMap() { -} - -status_t KeyLayoutMap::load(const String8& filename, sp<KeyLayoutMap>* outMap) { - outMap->clear(); - - Tokenizer* tokenizer; - status_t status = Tokenizer::open(filename, &tokenizer); - if (status) { - ALOGE("Error %d opening key layout map file %s.", status, filename.string()); - } else { - sp<KeyLayoutMap> map = new KeyLayoutMap(); - if (!map.get()) { - ALOGE("Error allocating key layout map."); - status = NO_MEMORY; - } else { -#if DEBUG_PARSER_PERFORMANCE - nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); -#endif - Parser parser(map.get(), tokenizer); - status = parser.parse(); -#if DEBUG_PARSER_PERFORMANCE - nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; - ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.", - tokenizer->getFilename().string(), tokenizer->getLineNumber(), - elapsedTime / 1000000.0); -#endif - if (!status) { - *outMap = map; - } - } - delete tokenizer; - } - return status; -} - -status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode, - int32_t* outKeyCode, uint32_t* outFlags) const { - const Key* key = getKey(scanCode, usageCode); - if (!key) { -#if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode); -#endif - *outKeyCode = AKEYCODE_UNKNOWN; - *outFlags = 0; - return NAME_NOT_FOUND; - } - - *outKeyCode = key->keyCode; - *outFlags = key->flags; - -#if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d, outFlags=0x%08x.", - scanCode, usageCode, *outKeyCode, *outFlags); -#endif - return NO_ERROR; -} - -const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const { - if (usageCode) { - ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); - if (index >= 0) { - return &mKeysByUsageCode.valueAt(index); - } - } - if (scanCode) { - ssize_t index = mKeysByScanCode.indexOfKey(scanCode); - if (index >= 0) { - return &mKeysByScanCode.valueAt(index); - } - } - return NULL; -} - -status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const { - const size_t N = mKeysByScanCode.size(); - for (size_t i=0; i<N; i++) { - if (mKeysByScanCode.valueAt(i).keyCode == keyCode) { - outScanCodes->add(mKeysByScanCode.keyAt(i)); - } - } - return NO_ERROR; -} - -status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const { - ssize_t index = mAxes.indexOfKey(scanCode); - if (index < 0) { -#if DEBUG_MAPPING - ALOGD("mapAxis: scanCode=%d ~ Failed.", scanCode); -#endif - return NAME_NOT_FOUND; - } - - *outAxisInfo = mAxes.valueAt(index); - -#if DEBUG_MAPPING - ALOGD("mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, " - "splitValue=%d, flatOverride=%d.", - scanCode, - outAxisInfo->mode, outAxisInfo->axis, outAxisInfo->highAxis, - outAxisInfo->splitValue, outAxisInfo->flatOverride); -#endif - return NO_ERROR; -} - -status_t KeyLayoutMap::findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const { - const size_t N = mLedsByScanCode.size(); - for (size_t i = 0; i < N; i++) { - if (mLedsByScanCode.valueAt(i).ledCode == ledCode) { - *outScanCode = mLedsByScanCode.keyAt(i); -#if DEBUG_MAPPING - ALOGD("findScanCodeForLed: ledCode=%d, scanCode=%d.", ledCode, *outScanCode); -#endif - return NO_ERROR; - } - } -#if DEBUG_MAPPING - ALOGD("findScanCodeForLed: ledCode=%d ~ Not found.", ledCode); -#endif - return NAME_NOT_FOUND; -} - -status_t KeyLayoutMap::findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const { - const size_t N = mLedsByUsageCode.size(); - for (size_t i = 0; i < N; i++) { - if (mLedsByUsageCode.valueAt(i).ledCode == ledCode) { - *outUsageCode = mLedsByUsageCode.keyAt(i); -#if DEBUG_MAPPING - ALOGD("findUsageForLed: ledCode=%d, usage=%x.", ledCode, *outUsageCode); -#endif - return NO_ERROR; - } - } -#if DEBUG_MAPPING - ALOGD("findUsageForLed: ledCode=%d ~ Not found.", ledCode); -#endif - return NAME_NOT_FOUND; -} - - -// --- KeyLayoutMap::Parser --- - -KeyLayoutMap::Parser::Parser(KeyLayoutMap* map, Tokenizer* tokenizer) : - mMap(map), mTokenizer(tokenizer) { -} - -KeyLayoutMap::Parser::~Parser() { -} - -status_t KeyLayoutMap::Parser::parse() { - while (!mTokenizer->isEof()) { -#if DEBUG_PARSER - ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); -#endif - - mTokenizer->skipDelimiters(WHITESPACE); - - if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { - String8 keywordToken = mTokenizer->nextToken(WHITESPACE); - if (keywordToken == "key") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseKey(); - if (status) return status; - } else if (keywordToken == "axis") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseAxis(); - if (status) return status; - } else if (keywordToken == "led") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseLed(); - if (status) return status; - } else { - ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), - keywordToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { - ALOGE("%s: Expected end of line or trailing comment, got '%s'.", - mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); - return BAD_VALUE; - } - } - - mTokenizer->nextLine(); - } - return NO_ERROR; -} - -status_t KeyLayoutMap::Parser::parseKey() { - String8 codeToken = mTokenizer->nextToken(WHITESPACE); - bool mapUsage = false; - if (codeToken == "usage") { - mapUsage = true; - mTokenizer->skipDelimiters(WHITESPACE); - codeToken = mTokenizer->nextToken(WHITESPACE); - } - - char* end; - int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(), - mapUsage ? "usage" : "scan code", codeToken.string()); - return BAD_VALUE; - } - KeyedVector<int32_t, Key>& map = - mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; - if (map.indexOfKey(code) >= 0) { - ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(), - mapUsage ? "usage" : "scan code", codeToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); - if (!keyCode) { - ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), - keyCodeToken.string()); - return BAD_VALUE; - } - - uint32_t flags = 0; - for (;;) { - mTokenizer->skipDelimiters(WHITESPACE); - if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break; - - String8 flagToken = mTokenizer->nextToken(WHITESPACE); - uint32_t flag = getKeyFlagByLabel(flagToken.string()); - if (!flag) { - ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(), - flagToken.string()); - return BAD_VALUE; - } - if (flags & flag) { - ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(), - flagToken.string()); - return BAD_VALUE; - } - flags |= flag; - } - -#if DEBUG_PARSER - ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.", - mapUsage ? "usage" : "scan code", code, keyCode, flags); -#endif - Key key; - key.keyCode = keyCode; - key.flags = flags; - map.add(code, key); - return NO_ERROR; -} - -status_t KeyLayoutMap::Parser::parseAxis() { - String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE); - char* end; - int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(), - scanCodeToken.string()); - return BAD_VALUE; - } - if (mMap->mAxes.indexOfKey(scanCode) >= 0) { - ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(), - scanCodeToken.string()); - return BAD_VALUE; - } - - AxisInfo axisInfo; - - mTokenizer->skipDelimiters(WHITESPACE); - String8 token = mTokenizer->nextToken(WHITESPACE); - if (token == "invert") { - axisInfo.mode = AxisInfo::MODE_INVERT; - - mTokenizer->skipDelimiters(WHITESPACE); - String8 axisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.axis = getAxisByLabel(axisToken.string()); - if (axisInfo.axis < 0) { - ALOGE("%s: Expected inverted axis label, got '%s'.", - mTokenizer->getLocation().string(), axisToken.string()); - return BAD_VALUE; - } - } else if (token == "split") { - axisInfo.mode = AxisInfo::MODE_SPLIT; - - mTokenizer->skipDelimiters(WHITESPACE); - String8 splitToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected split value, got '%s'.", - mTokenizer->getLocation().string(), splitToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.axis = getAxisByLabel(lowAxisToken.string()); - if (axisInfo.axis < 0) { - ALOGE("%s: Expected low axis label, got '%s'.", - mTokenizer->getLocation().string(), lowAxisToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 highAxisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.highAxis = getAxisByLabel(highAxisToken.string()); - if (axisInfo.highAxis < 0) { - ALOGE("%s: Expected high axis label, got '%s'.", - mTokenizer->getLocation().string(), highAxisToken.string()); - return BAD_VALUE; - } - } else { - axisInfo.axis = getAxisByLabel(token.string()); - if (axisInfo.axis < 0) { - ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.", - mTokenizer->getLocation().string(), token.string()); - return BAD_VALUE; - } - } - - for (;;) { - mTokenizer->skipDelimiters(WHITESPACE); - if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') { - break; - } - String8 keywordToken = mTokenizer->nextToken(WHITESPACE); - if (keywordToken == "flat") { - mTokenizer->skipDelimiters(WHITESPACE); - String8 flatToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected flat value, got '%s'.", - mTokenizer->getLocation().string(), flatToken.string()); - return BAD_VALUE; - } - } else { - ALOGE("%s: Expected keyword 'flat', got '%s'.", - mTokenizer->getLocation().string(), keywordToken.string()); - return BAD_VALUE; - } - } - -#if DEBUG_PARSER - ALOGD("Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, " - "splitValue=%d, flatOverride=%d.", - scanCode, - axisInfo.mode, axisInfo.axis, axisInfo.highAxis, - axisInfo.splitValue, axisInfo.flatOverride); -#endif - mMap->mAxes.add(scanCode, axisInfo); - return NO_ERROR; -} - -status_t KeyLayoutMap::Parser::parseLed() { - String8 codeToken = mTokenizer->nextToken(WHITESPACE); - bool mapUsage = false; - if (codeToken == "usage") { - mapUsage = true; - mTokenizer->skipDelimiters(WHITESPACE); - codeToken = mTokenizer->nextToken(WHITESPACE); - } - char* end; - int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(), - mapUsage ? "usage" : "scan code", codeToken.string()); - return BAD_VALUE; - } - - KeyedVector<int32_t, Led>& map = mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode; - if (map.indexOfKey(code) >= 0) { - ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(), - mapUsage ? "usage" : "scan code", codeToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t ledCode = getLedByLabel(ledCodeToken.string()); - if (ledCode < 0) { - ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(), - ledCodeToken.string()); - return BAD_VALUE; - } - -#if DEBUG_PARSER - ALOGD("Parsed led %s: code=%d, ledCode=%d.", - mapUsage ? "usage" : "scan code", code, ledCode); -#endif - - Led led; - led.ledCode = ledCode; - map.add(code, led); - return NO_ERROR; -} -}; diff --git a/widget/gonk/libui/KeyLayoutMap.h b/widget/gonk/libui/KeyLayoutMap.h deleted file mode 100644 index 8a6113447..000000000 --- a/widget/gonk/libui/KeyLayoutMap.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_KEY_LAYOUT_MAP_H -#define _ANDROIDFW_KEY_LAYOUT_MAP_H - -#include <stdint.h> -#include <utils/Errors.h> -#include <utils/KeyedVector.h> -#include "Tokenizer.h" -#include <utils/RefBase.h> - -namespace android { - -struct AxisInfo { - enum Mode { - // Axis value is reported directly. - MODE_NORMAL = 0, - // Axis value should be inverted before reporting. - MODE_INVERT = 1, - // Axis value should be split into two axes - MODE_SPLIT = 2, - }; - - // Axis mode. - Mode mode; - - // Axis id. - // When split, this is the axis used for values smaller than the split position. - int32_t axis; - - // When split, this is the axis used for values after higher than the split position. - int32_t highAxis; - - // The split value, or 0 if not split. - int32_t splitValue; - - // The flat value, or -1 if none. - int32_t flatOverride; - - AxisInfo() : mode(MODE_NORMAL), axis(-1), highAxis(-1), splitValue(0), flatOverride(-1) { - } -}; - -/** - * Describes a mapping from keyboard scan codes and joystick axes to Android key codes and axes. - * - * This object is immutable after it has been loaded. - */ -class KeyLayoutMap : public RefBase { -public: - static status_t load(const String8& filename, sp<KeyLayoutMap>* outMap); - - status_t mapKey(int32_t scanCode, int32_t usageCode, - int32_t* outKeyCode, uint32_t* outFlags) const; - status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const; - status_t findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const; - status_t findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const; - - status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const; - -protected: - virtual ~KeyLayoutMap(); - -private: - struct Key { - int32_t keyCode; - uint32_t flags; - }; - - struct Led { - int32_t ledCode; - }; - - - KeyedVector<int32_t, Key> mKeysByScanCode; - KeyedVector<int32_t, Key> mKeysByUsageCode; - KeyedVector<int32_t, AxisInfo> mAxes; - KeyedVector<int32_t, Led> mLedsByScanCode; - KeyedVector<int32_t, Led> mLedsByUsageCode; - - KeyLayoutMap(); - - const Key* getKey(int32_t scanCode, int32_t usageCode) const; - - class Parser { - KeyLayoutMap* mMap; - Tokenizer* mTokenizer; - - public: - Parser(KeyLayoutMap* map, Tokenizer* tokenizer); - ~Parser(); - status_t parse(); - - private: - status_t parseKey(); - status_t parseAxis(); - status_t parseLed(); - }; -}; - -} // namespace android - -#endif // _ANDROIDFW_KEY_LAYOUT_MAP_H diff --git a/widget/gonk/libui/Keyboard.cpp b/widget/gonk/libui/Keyboard.cpp deleted file mode 100644 index 62bb53b7b..000000000 --- a/widget/gonk/libui/Keyboard.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Keyboard" -#include "cutils_log.h" - -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> - -#include "Keyboard.h" -#include "KeycodeLabels.h" -#include "KeyLayoutMap.h" -#include "KeyCharacterMap.h" -#include "InputDevice.h" -#include <utils/Errors.h> -#include <cutils/properties.h> - -namespace android { - -// --- KeyMap --- - -KeyMap::KeyMap() { -} - -KeyMap::~KeyMap() { -} - -status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier, - const PropertyMap* deviceConfiguration) { - // Use the configured key layout if available. - if (deviceConfiguration) { - String8 keyLayoutName; - if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"), - keyLayoutName)) { - status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName); - if (status == NAME_NOT_FOUND) { - ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but " - "it was not found.", - deviceIdenfifier.name.string(), keyLayoutName.string()); - } - } - - String8 keyCharacterMapName; - if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"), - keyCharacterMapName)) { - status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName); - if (status == NAME_NOT_FOUND) { - ALOGE("Configuration for keyboard device '%s' requested keyboard character " - "map '%s' but it was not found.", - deviceIdenfifier.name.string(), keyLayoutName.string()); - } - } - - if (isComplete()) { - return OK; - } - } - - // Try searching by device identifier. - if (probeKeyMap(deviceIdenfifier, String8::empty())) { - return OK; - } - - // Fall back on the Generic key map. - // TODO Apply some additional heuristics here to figure out what kind of - // generic key map to use (US English, etc.) for typical external keyboards. - if (probeKeyMap(deviceIdenfifier, String8("Generic"))) { - return OK; - } - - // Try the Virtual key map as a last resort. - if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) { - return OK; - } - - // Give up! - ALOGE("Could not determine key map for device '%s' and no default key maps were found!", - deviceIdenfifier.name.string()); - return NAME_NOT_FOUND; -} - -bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, - const String8& keyMapName) { - if (!haveKeyLayout()) { - loadKeyLayout(deviceIdentifier, keyMapName); - } - if (!haveKeyCharacterMap()) { - loadKeyCharacterMap(deviceIdentifier, keyMapName); - } - return isComplete(); -} - -status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, - const String8& name) { - String8 path(getPath(deviceIdentifier, name, - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT)); - if (path.isEmpty()) { - return NAME_NOT_FOUND; - } - - status_t status = KeyLayoutMap::load(path, &keyLayoutMap); - if (status) { - return status; - } - - keyLayoutFile.setTo(path); - return OK; -} - -status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier, - const String8& name) { - String8 path(getPath(deviceIdentifier, name, - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP)); - if (path.isEmpty()) { - return NAME_NOT_FOUND; - } - - status_t status = KeyCharacterMap::load(path, - KeyCharacterMap::FORMAT_BASE, &keyCharacterMap); - if (status) { - return status; - } - - keyCharacterMapFile.setTo(path); - return OK; -} - -String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier, - const String8& name, InputDeviceConfigurationFileType type) { - return name.isEmpty() - ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type) - : getInputDeviceConfigurationFilePathByName(name, type); -} - - -// --- Global functions --- - -bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier, - const PropertyMap* deviceConfiguration, const KeyMap* keyMap) { - if (!keyMap->haveKeyCharacterMap() - || keyMap->keyCharacterMap->getKeyboardType() - == KeyCharacterMap::KEYBOARD_TYPE_SPECIAL_FUNCTION) { - return false; - } - - if (deviceConfiguration) { - bool builtIn = false; - if (deviceConfiguration->tryGetProperty(String8("keyboard.builtIn"), builtIn) - && builtIn) { - return true; - } - } - - return strstr(deviceIdentifier.name.string(), "-keypad"); -} - -static int lookupValueByLabel(const char* literal, const KeycodeLabel *list) { - while (list->literal) { - if (strcmp(literal, list->literal) == 0) { - return list->value; - } - list++; - } - return list->value; -} - -static const char* lookupLabelByValue(int value, const KeycodeLabel *list) { - while (list->literal) { - if (list->value == value) { - return list->literal; - } - list++; - } - return NULL; -} - -int32_t getKeyCodeByLabel(const char* label) { - return int32_t(lookupValueByLabel(label, KEYCODES)); -} - -uint32_t getKeyFlagByLabel(const char* label) { - return uint32_t(lookupValueByLabel(label, FLAGS)); -} - -int32_t getAxisByLabel(const char* label) { - return int32_t(lookupValueByLabel(label, AXES)); -} - -const char* getAxisLabel(int32_t axisId) { - return lookupLabelByValue(axisId, AXES); -} - -int32_t getLedByLabel(const char* label) { - return int32_t(lookupValueByLabel(label, LEDS)); -} -static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) { - int32_t newMetaState; - if (down) { - newMetaState = oldMetaState | mask; - } else { - newMetaState = oldMetaState & - ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON); - } - - if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { - newMetaState |= AMETA_ALT_ON; - } - - if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) { - newMetaState |= AMETA_SHIFT_ON; - } - - if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) { - newMetaState |= AMETA_CTRL_ON; - } - - if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) { - newMetaState |= AMETA_META_ON; - } - return newMetaState; -} - -static int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) { - if (down) { - return oldMetaState; - } else { - return oldMetaState ^ mask; - } -} - -int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) { - switch (keyCode) { - case AKEYCODE_ALT_LEFT: - return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState); - case AKEYCODE_ALT_RIGHT: - return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState); - case AKEYCODE_SHIFT_LEFT: - return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState); - case AKEYCODE_SHIFT_RIGHT: - return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState); - case AKEYCODE_SYM: - return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState); - case AKEYCODE_FUNCTION: - return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState); - case AKEYCODE_CTRL_LEFT: - return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState); - case AKEYCODE_CTRL_RIGHT: - return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState); - case AKEYCODE_META_LEFT: - return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState); - case AKEYCODE_META_RIGHT: - return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState); - case AKEYCODE_CAPS_LOCK: - return toggleLockedMetaState(AMETA_CAPS_LOCK_ON, down, oldMetaState); - case AKEYCODE_NUM_LOCK: - return toggleLockedMetaState(AMETA_NUM_LOCK_ON, down, oldMetaState); - case AKEYCODE_SCROLL_LOCK: - return toggleLockedMetaState(AMETA_SCROLL_LOCK_ON, down, oldMetaState); - default: - return oldMetaState; - } -} - -bool isMetaKey(int32_t keyCode) { - switch (keyCode) { - case AKEYCODE_ALT_LEFT: - case AKEYCODE_ALT_RIGHT: - case AKEYCODE_SHIFT_LEFT: - case AKEYCODE_SHIFT_RIGHT: - case AKEYCODE_SYM: - case AKEYCODE_FUNCTION: - case AKEYCODE_CTRL_LEFT: - case AKEYCODE_CTRL_RIGHT: - case AKEYCODE_META_LEFT: - case AKEYCODE_META_RIGHT: - case AKEYCODE_CAPS_LOCK: - case AKEYCODE_NUM_LOCK: - case AKEYCODE_SCROLL_LOCK: - return true; - default: - return false; - } -} - - -} // namespace android diff --git a/widget/gonk/libui/Keyboard.h b/widget/gonk/libui/Keyboard.h deleted file mode 100644 index 65921b25b..000000000 --- a/widget/gonk/libui/Keyboard.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_KEYBOARD_H -#define _ANDROIDFW_KEYBOARD_H - -#include "Input.h" -#include "InputDevice.h" -#include <utils/Errors.h> -#include <utils/String8.h> -#include <utils/PropertyMap.h> - -namespace android { - -enum { - /* Device id of the built in keyboard. */ - DEVICE_ID_BUILT_IN_KEYBOARD = 0, - - /* Device id of a generic virtual keyboard with a full layout that can be used - * to synthesize key events. */ - DEVICE_ID_VIRTUAL_KEYBOARD = -1, -}; - -class KeyLayoutMap; -class KeyCharacterMap; - -/** - * Loads the key layout map and key character map for a keyboard device. - */ -class KeyMap { -public: - String8 keyLayoutFile; - sp<KeyLayoutMap> keyLayoutMap; - - String8 keyCharacterMapFile; - sp<KeyCharacterMap> keyCharacterMap; - - KeyMap(); - ~KeyMap(); - - status_t load(const InputDeviceIdentifier& deviceIdenfier, - const PropertyMap* deviceConfiguration); - - inline bool haveKeyLayout() const { - return !keyLayoutFile.isEmpty(); - } - - inline bool haveKeyCharacterMap() const { - return !keyCharacterMapFile.isEmpty(); - } - - inline bool isComplete() const { - return haveKeyLayout() && haveKeyCharacterMap(); - } - -private: - bool probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const String8& name); - status_t loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, const String8& name); - status_t loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier, - const String8& name); - String8 getPath(const InputDeviceIdentifier& deviceIdentifier, - const String8& name, InputDeviceConfigurationFileType type); -}; - -/** - * Returns true if the keyboard is eligible for use as a built-in keyboard. - */ -extern bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier, - const PropertyMap* deviceConfiguration, const KeyMap* keyMap); - -/** - * Gets a key code by its short form label, eg. "HOME". - * Returns 0 if unknown. - */ -extern int32_t getKeyCodeByLabel(const char* label); - -/** - * Gets a key flag by its short form label, eg. "WAKE". - * Returns 0 if unknown. - */ -extern uint32_t getKeyFlagByLabel(const char* label); - -/** - * Gets a axis by its short form label, eg. "X". - * Returns -1 if unknown. - */ -extern int32_t getAxisByLabel(const char* label); - -/** - * Gets a axis label by its id. - * Returns NULL if unknown. - */ -extern const char* getAxisLabel(int32_t axisId); - -extern int32_t getLedByLabel(const char* label); - -/** - * Updates a meta state field when a key is pressed or released. - */ -extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState); - -/** - * Returns true if a key is a meta key like ALT or CAPS_LOCK. - */ -extern bool isMetaKey(int32_t keyCode); - -} // namespace android - -#endif // _ANDROIDFW_KEYBOARD_H diff --git a/widget/gonk/libui/KeycodeLabels.h b/widget/gonk/libui/KeycodeLabels.h deleted file mode 100644 index 9f994597b..000000000 --- a/widget/gonk/libui/KeycodeLabels.h +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_KEYCODE_LABELS_H -#define _ANDROIDFW_KEYCODE_LABELS_H - -#include "android_keycodes.h" - -struct KeycodeLabel { - const char *literal; - int value; -}; - -static const KeycodeLabel KEYCODES[] = { - { "SOFT_LEFT", 1 }, - { "SOFT_RIGHT", 2 }, - { "HOME", 3 }, - { "BACK", 4 }, - { "CALL", 5 }, - { "ENDCALL", 6 }, - { "0", 7 }, - { "1", 8 }, - { "2", 9 }, - { "3", 10 }, - { "4", 11 }, - { "5", 12 }, - { "6", 13 }, - { "7", 14 }, - { "8", 15 }, - { "9", 16 }, - { "STAR", 17 }, - { "POUND", 18 }, - { "DPAD_UP", 19 }, - { "DPAD_DOWN", 20 }, - { "DPAD_LEFT", 21 }, - { "DPAD_RIGHT", 22 }, - { "DPAD_CENTER", 23 }, - { "VOLUME_UP", 24 }, - { "VOLUME_DOWN", 25 }, - { "POWER", 26 }, - { "CAMERA", 27 }, - { "CLEAR", 28 }, - { "A", 29 }, - { "B", 30 }, - { "C", 31 }, - { "D", 32 }, - { "E", 33 }, - { "F", 34 }, - { "G", 35 }, - { "H", 36 }, - { "I", 37 }, - { "J", 38 }, - { "K", 39 }, - { "L", 40 }, - { "M", 41 }, - { "N", 42 }, - { "O", 43 }, - { "P", 44 }, - { "Q", 45 }, - { "R", 46 }, - { "S", 47 }, - { "T", 48 }, - { "U", 49 }, - { "V", 50 }, - { "W", 51 }, - { "X", 52 }, - { "Y", 53 }, - { "Z", 54 }, - { "COMMA", 55 }, - { "PERIOD", 56 }, - { "ALT_LEFT", 57 }, - { "ALT_RIGHT", 58 }, - { "SHIFT_LEFT", 59 }, - { "SHIFT_RIGHT", 60 }, - { "TAB", 61 }, - { "SPACE", 62 }, - { "SYM", 63 }, - { "EXPLORER", 64 }, - { "ENVELOPE", 65 }, - { "ENTER", 66 }, - { "DEL", 67 }, - { "GRAVE", 68 }, - { "MINUS", 69 }, - { "EQUALS", 70 }, - { "LEFT_BRACKET", 71 }, - { "RIGHT_BRACKET", 72 }, - { "BACKSLASH", 73 }, - { "SEMICOLON", 74 }, - { "APOSTROPHE", 75 }, - { "SLASH", 76 }, - { "AT", 77 }, - { "NUM", 78 }, - { "HEADSETHOOK", 79 }, - { "FOCUS", 80 }, - { "PLUS", 81 }, - { "MENU", 82 }, - { "NOTIFICATION", 83 }, - { "SEARCH", 84 }, - { "MEDIA_PLAY_PAUSE", 85 }, - { "MEDIA_STOP", 86 }, - { "MEDIA_NEXT", 87 }, - { "MEDIA_PREVIOUS", 88 }, - { "MEDIA_REWIND", 89 }, - { "MEDIA_FAST_FORWARD", 90 }, - { "MUTE", 91 }, - { "PAGE_UP", 92 }, - { "PAGE_DOWN", 93 }, - { "PICTSYMBOLS", 94 }, - { "SWITCH_CHARSET", 95 }, - { "BUTTON_A", 96 }, - { "BUTTON_B", 97 }, - { "BUTTON_C", 98 }, - { "BUTTON_X", 99 }, - { "BUTTON_Y", 100 }, - { "BUTTON_Z", 101 }, - { "BUTTON_L1", 102 }, - { "BUTTON_R1", 103 }, - { "BUTTON_L2", 104 }, - { "BUTTON_R2", 105 }, - { "BUTTON_THUMBL", 106 }, - { "BUTTON_THUMBR", 107 }, - { "BUTTON_START", 108 }, - { "BUTTON_SELECT", 109 }, - { "BUTTON_MODE", 110 }, - { "ESCAPE", 111 }, - { "FORWARD_DEL", 112 }, - { "CTRL_LEFT", 113 }, - { "CTRL_RIGHT", 114 }, - { "CAPS_LOCK", 115 }, - { "SCROLL_LOCK", 116 }, - { "META_LEFT", 117 }, - { "META_RIGHT", 118 }, - { "FUNCTION", 119 }, - { "SYSRQ", 120 }, - { "BREAK", 121 }, - { "MOVE_HOME", 122 }, - { "MOVE_END", 123 }, - { "INSERT", 124 }, - { "FORWARD", 125 }, - { "MEDIA_PLAY", 126 }, - { "MEDIA_PAUSE", 127 }, - { "MEDIA_CLOSE", 128 }, - { "MEDIA_EJECT", 129 }, - { "MEDIA_RECORD", 130 }, - { "F1", 131 }, - { "F2", 132 }, - { "F3", 133 }, - { "F4", 134 }, - { "F5", 135 }, - { "F6", 136 }, - { "F7", 137 }, - { "F8", 138 }, - { "F9", 139 }, - { "F10", 140 }, - { "F11", 141 }, - { "F12", 142 }, - { "NUM_LOCK", 143 }, - { "NUMPAD_0", 144 }, - { "NUMPAD_1", 145 }, - { "NUMPAD_2", 146 }, - { "NUMPAD_3", 147 }, - { "NUMPAD_4", 148 }, - { "NUMPAD_5", 149 }, - { "NUMPAD_6", 150 }, - { "NUMPAD_7", 151 }, - { "NUMPAD_8", 152 }, - { "NUMPAD_9", 153 }, - { "NUMPAD_DIVIDE", 154 }, - { "NUMPAD_MULTIPLY", 155 }, - { "NUMPAD_SUBTRACT", 156 }, - { "NUMPAD_ADD", 157 }, - { "NUMPAD_DOT", 158 }, - { "NUMPAD_COMMA", 159 }, - { "NUMPAD_ENTER", 160 }, - { "NUMPAD_EQUALS", 161 }, - { "NUMPAD_LEFT_PAREN", 162 }, - { "NUMPAD_RIGHT_PAREN", 163 }, - { "VOLUME_MUTE", 164 }, - { "INFO", 165 }, - { "CHANNEL_UP", 166 }, - { "CHANNEL_DOWN", 167 }, - { "ZOOM_IN", 168 }, - { "ZOOM_OUT", 169 }, - { "TV", 170 }, - { "WINDOW", 171 }, - { "GUIDE", 172 }, - { "DVR", 173 }, - { "BOOKMARK", 174 }, - { "CAPTIONS", 175 }, - { "SETTINGS", 176 }, - { "TV_POWER", 177 }, - { "TV_INPUT", 178 }, - { "STB_POWER", 179 }, - { "STB_INPUT", 180 }, - { "AVR_POWER", 181 }, - { "AVR_INPUT", 182 }, - { "PROG_RED", 183 }, - { "PROG_GREEN", 184 }, - { "PROG_YELLOW", 185 }, - { "PROG_BLUE", 186 }, - { "APP_SWITCH", 187 }, - { "BUTTON_1", 188 }, - { "BUTTON_2", 189 }, - { "BUTTON_3", 190 }, - { "BUTTON_4", 191 }, - { "BUTTON_5", 192 }, - { "BUTTON_6", 193 }, - { "BUTTON_7", 194 }, - { "BUTTON_8", 195 }, - { "BUTTON_9", 196 }, - { "BUTTON_10", 197 }, - { "BUTTON_11", 198 }, - { "BUTTON_12", 199 }, - { "BUTTON_13", 200 }, - { "BUTTON_14", 201 }, - { "BUTTON_15", 202 }, - { "BUTTON_16", 203 }, - { "LANGUAGE_SWITCH", 204 }, - { "MANNER_MODE", 205 }, - { "3D_MODE", 206 }, - { "CONTACTS", 207 }, - { "CALENDAR", 208 }, - { "MUSIC", 209 }, - { "CALCULATOR", 210 }, - { "ZENKAKU_HANKAKU", 211 }, - { "EISU", 212 }, - { "MUHENKAN", 213 }, - { "HENKAN", 214 }, - { "KATAKANA_HIRAGANA", 215 }, - { "YEN", 216 }, - { "RO", 217 }, - { "KANA", 218 }, - { "ASSIST", 219 }, - { "BRIGHTNESS_DOWN", 220 }, - { "BRIGHTNESS_UP", 221 }, - { "MEDIA_AUDIO_TRACK", 222 }, - { "SLEEP", 223 }, - { "WAKEUP", 224 }, - { "PAIRING", 225 }, - { "MEDIA_TOP_MENU", 226 }, - { "11", 227 }, - { "12", 228 }, - { "LAST_CHANNEL", 229 }, - { "TV_DATA_SERVICE", 230 }, - { "VOICE_ASSIST", 231 }, - { "TV_RADIO_SERVICE", 232 }, - { "TV_TELETEXT", 233 }, - { "TV_NUMBER_ENTRY", 234 }, - { "TV_TERRESTRIAL_ANALOG", 235 }, - { "TV_TERRESTRIAL_DIGITAL", 236 }, - { "TV_SATELLITE", 237 }, - { "TV_SATELLITE_BS", 238 }, - { "TV_SATELLITE_CS", 239 }, - { "TV_SATELLITE_SERVICE", 240 }, - { "TV_NETWORK", 241 }, - { "TV_ANTENNA_CABLE", 242 }, - { "TV_INPUT_HDMI_1", 243 }, - { "TV_INPUT_HDMI_2", 244 }, - { "TV_INPUT_HDMI_3", 245 }, - { "TV_INPUT_HDMI_4", 246 }, - { "TV_INPUT_COMPOSITE_1", 247 }, - { "TV_INPUT_COMPOSITE_2", 248 }, - { "TV_INPUT_COMPONENT_1", 249 }, - { "TV_INPUT_COMPONENT_2", 250 }, - { "TV_INPUT_VGA_1", 251 }, - { "TV_AUDIO_DESCRIPTION", 252 }, - { "TV_AUDIO_DESCRIPTION_MIX_UP", 253 }, - { "TV_AUDIO_DESCRIPTION_MIX_DOWN", 254 }, - { "TV_ZOOM_MODE", 255 }, - { "TV_CONTENTS_MENU", 256 }, - { "TV_MEDIA_CONTEXT_MENU", 257 }, - { "TV_TIMER_PROGRAMMING", 258 }, - { "HELP", 259 }, - - // NOTE: If you add a new keycode here you must also add it to several other files. - // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. - - { NULL, 0 } -}; - -// NOTE: If you edit these flags, also edit policy flags in Input.h. -static const KeycodeLabel FLAGS[] = { - { "WAKE", 0x00000001 }, - { "WAKE_DROPPED", 0x00000002 }, - { "SHIFT", 0x00000004 }, - { "CAPS_LOCK", 0x00000008 }, - { "ALT", 0x00000010 }, - { "ALT_GR", 0x00000020 }, - { "MENU", 0x00000040 }, - { "LAUNCHER", 0x00000080 }, - { "VIRTUAL", 0x00000100 }, - { "FUNCTION", 0x00000200 }, - { NULL, 0 } -}; - -static const KeycodeLabel AXES[] = { - { "X", 0 }, - { "Y", 1 }, - { "PRESSURE", 2 }, - { "SIZE", 3 }, - { "TOUCH_MAJOR", 4 }, - { "TOUCH_MINOR", 5 }, - { "TOOL_MAJOR", 6 }, - { "TOOL_MINOR", 7 }, - { "ORIENTATION", 8 }, - { "VSCROLL", 9 }, - { "HSCROLL", 10 }, - { "Z", 11 }, - { "RX", 12 }, - { "RY", 13 }, - { "RZ", 14 }, - { "HAT_X", 15 }, - { "HAT_Y", 16 }, - { "LTRIGGER", 17 }, - { "RTRIGGER", 18 }, - { "THROTTLE", 19 }, - { "RUDDER", 20 }, - { "WHEEL", 21 }, - { "GAS", 22 }, - { "BRAKE", 23 }, - { "DISTANCE", 24 }, - { "TILT", 25 }, - { "GENERIC_1", 32 }, - { "GENERIC_2", 33 }, - { "GENERIC_3", 34 }, - { "GENERIC_4", 35 }, - { "GENERIC_5", 36 }, - { "GENERIC_6", 37 }, - { "GENERIC_7", 38 }, - { "GENERIC_8", 39 }, - { "GENERIC_9", 40 }, - { "GENERIC_10", 41 }, - { "GENERIC_11", 42 }, - { "GENERIC_12", 43 }, - { "GENERIC_13", 44 }, - { "GENERIC_14", 45 }, - { "GENERIC_15", 46 }, - { "GENERIC_16", 47 }, - - // NOTE: If you add a new axis here you must also add it to several other files. - // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list. - - { NULL, -1 } -}; - -static const KeycodeLabel LEDS[] = { - { "NUM_LOCK", 1}, - { "CAPS_LOCK", 2}, - { "SCROLL_LOCK", 3}, - { "COMPOSE", 4}, - { "KANA", 5}, - { "SLEEP", 6}, - { "SUSPEND", 7}, - { "MUTE", 8}, - { "MISC", 9}, - { "MAIL", 10}, - { "CHARGING", 11}, - { "CONTROLLER_1", 12}, - { "CONTROLLER_2", 13}, - { "CONTROLLER_3", 14}, - { "CONTROLLER_4", 15}, - - // NOTE: If you add new LEDs here, you must also add them to Input.h - { NULL, 0 } -}; - -#endif // _ANDROIDFW_KEYCODE_LABELS_H diff --git a/widget/gonk/libui/PointerController.cpp b/widget/gonk/libui/PointerController.cpp deleted file mode 100644 index ff80a0a9f..000000000 --- a/widget/gonk/libui/PointerController.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "PointerController" - -//#define LOG_NDEBUG 0 - -// Log debug messages about pointer updates -#define DEBUG_POINTER_UPDATES 0 - -#include "PointerController.h" - -#include "cutils_log.h" - -#include <SkBitmap.h> -#include <SkCanvas.h> -#include <SkColor.h> -#include <SkPaint.h> -#include <SkXfermode.h> - -namespace android { - -// --- PointerController --- - -// Time to wait before starting the fade when the pointer is inactive. -static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds -static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds - -// Time to wait between animation frames. -static const nsecs_t ANIMATION_FRAME_INTERVAL = 1000000000LL / 60; - -// Time to spend fading out the spot completely. -static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms - -// Time to spend fading out the pointer completely. -static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms - - -// --- PointerController --- - -PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy, - const sp<Looper>& looper, const sp<SpriteController>& spriteController) : - mPolicy(policy), mLooper(looper), mSpriteController(spriteController) { - mHandler = new WeakMessageHandler(this); - - AutoMutex _l(mLock); - - mLocked.animationPending = false; - - mLocked.displayWidth = -1; - mLocked.displayHeight = -1; - mLocked.displayOrientation = DISPLAY_ORIENTATION_0; - - mLocked.presentation = PRESENTATION_POINTER; - mLocked.presentationChanged = false; - - mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL; - - mLocked.pointerFadeDirection = 0; - mLocked.pointerX = 0; - mLocked.pointerY = 0; - mLocked.pointerAlpha = 0.0f; // pointer is initially faded - mLocked.pointerSprite = mSpriteController->createSprite(); - mLocked.pointerIconChanged = false; - - mLocked.buttonState = 0; - - loadResources(); -} - -PointerController::~PointerController() { - mLooper->removeMessages(mHandler); - - AutoMutex _l(mLock); - - mLocked.pointerSprite.clear(); - - for (size_t i = 0; i < mLocked.spots.size(); i++) { - delete mLocked.spots.itemAt(i); - } - mLocked.spots.clear(); - mLocked.recycledSprites.clear(); -} - -bool PointerController::getBounds(float* outMinX, float* outMinY, - float* outMaxX, float* outMaxY) const { - AutoMutex _l(mLock); - - return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY); -} - -bool PointerController::getBoundsLocked(float* outMinX, float* outMinY, - float* outMaxX, float* outMaxY) const { - if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) { - return false; - } - - *outMinX = 0; - *outMinY = 0; - switch (mLocked.displayOrientation) { - case DISPLAY_ORIENTATION_90: - case DISPLAY_ORIENTATION_270: - *outMaxX = mLocked.displayHeight - 1; - *outMaxY = mLocked.displayWidth - 1; - break; - default: - *outMaxX = mLocked.displayWidth - 1; - *outMaxY = mLocked.displayHeight - 1; - break; - } - return true; -} - -void PointerController::move(float deltaX, float deltaY) { -#if DEBUG_POINTER_UPDATES - ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY); -#endif - if (deltaX == 0.0f && deltaY == 0.0f) { - return; - } - - AutoMutex _l(mLock); - - setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY); -} - -void PointerController::setButtonState(int32_t buttonState) { -#if DEBUG_POINTER_UPDATES - ALOGD("Set button state 0x%08x", buttonState); -#endif - AutoMutex _l(mLock); - - if (mLocked.buttonState != buttonState) { - mLocked.buttonState = buttonState; - } -} - -int32_t PointerController::getButtonState() const { - AutoMutex _l(mLock); - - return mLocked.buttonState; -} - -void PointerController::setPosition(float x, float y) { -#if DEBUG_POINTER_UPDATES - ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y); -#endif - AutoMutex _l(mLock); - - setPositionLocked(x, y); -} - -void PointerController::setPositionLocked(float x, float y) { - float minX, minY, maxX, maxY; - if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) { - if (x <= minX) { - mLocked.pointerX = minX; - } else if (x >= maxX) { - mLocked.pointerX = maxX; - } else { - mLocked.pointerX = x; - } - if (y <= minY) { - mLocked.pointerY = minY; - } else if (y >= maxY) { - mLocked.pointerY = maxY; - } else { - mLocked.pointerY = y; - } - updatePointerLocked(); - } -} - -void PointerController::getPosition(float* outX, float* outY) const { - AutoMutex _l(mLock); - - *outX = mLocked.pointerX; - *outY = mLocked.pointerY; -} - -void PointerController::fade(Transition transition) { - AutoMutex _l(mLock); - - // Remove the inactivity timeout, since we are fading now. - removeInactivityTimeoutLocked(); - - // Start fading. - if (transition == TRANSITION_IMMEDIATE) { - mLocked.pointerFadeDirection = 0; - mLocked.pointerAlpha = 0.0f; - updatePointerLocked(); - } else { - mLocked.pointerFadeDirection = -1; - startAnimationLocked(); - } -} - -void PointerController::unfade(Transition transition) { - AutoMutex _l(mLock); - - // Always reset the inactivity timer. - resetInactivityTimeoutLocked(); - - // Start unfading. - if (transition == TRANSITION_IMMEDIATE) { - mLocked.pointerFadeDirection = 0; - mLocked.pointerAlpha = 1.0f; - updatePointerLocked(); - } else { - mLocked.pointerFadeDirection = 1; - startAnimationLocked(); - } -} - -void PointerController::setPresentation(Presentation presentation) { - AutoMutex _l(mLock); - - if (mLocked.presentation != presentation) { - mLocked.presentation = presentation; - mLocked.presentationChanged = true; - - if (presentation != PRESENTATION_SPOT) { - fadeOutAndReleaseAllSpotsLocked(); - } - - updatePointerLocked(); - } -} - -void PointerController::setSpots(const PointerCoords* spotCoords, - const uint32_t* spotIdToIndex, BitSet32 spotIdBits) { -#if DEBUG_POINTER_UPDATES - ALOGD("setSpots: idBits=%08x", spotIdBits.value); - for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - const PointerCoords& c = spotCoords[spotIdToIndex[id]]; - ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id, - c.getAxisValue(AMOTION_EVENT_AXIS_X), - c.getAxisValue(AMOTION_EVENT_AXIS_Y), - c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); - } -#endif - - AutoMutex _l(mLock); - - mSpriteController->openTransaction(); - - // Add or move spots for fingers that are down. - for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - const PointerCoords& c = spotCoords[spotIdToIndex[id]]; - const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0 - ? mResources.spotTouch : mResources.spotHover; - float x = c.getAxisValue(AMOTION_EVENT_AXIS_X); - float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y); - - Spot* spot = getSpotLocked(id); - if (!spot) { - spot = createAndAddSpotLocked(id); - } - - spot->updateSprite(&icon, x, y); - } - - // Remove spots for fingers that went up. - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); - if (spot->id != Spot::INVALID_ID - && !spotIdBits.hasBit(spot->id)) { - fadeOutAndReleaseSpotLocked(spot); - } - } - - mSpriteController->closeTransaction(); -} - -void PointerController::clearSpots() { -#if DEBUG_POINTER_UPDATES - ALOGD("clearSpots"); -#endif - - AutoMutex _l(mLock); - - fadeOutAndReleaseAllSpotsLocked(); -} - -void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) { - AutoMutex _l(mLock); - - if (mLocked.inactivityTimeout != inactivityTimeout) { - mLocked.inactivityTimeout = inactivityTimeout; - resetInactivityTimeoutLocked(); - } -} - -void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) { - AutoMutex _l(mLock); - - // Adjust to use the display's unrotated coordinate frame. - if (orientation == DISPLAY_ORIENTATION_90 - || orientation == DISPLAY_ORIENTATION_270) { - int32_t temp = height; - height = width; - width = temp; - } - - if (mLocked.displayWidth != width || mLocked.displayHeight != height) { - mLocked.displayWidth = width; - mLocked.displayHeight = height; - - float minX, minY, maxX, maxY; - if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) { - mLocked.pointerX = (minX + maxX) * 0.5f; - mLocked.pointerY = (minY + maxY) * 0.5f; - } else { - mLocked.pointerX = 0; - mLocked.pointerY = 0; - } - - fadeOutAndReleaseAllSpotsLocked(); - } - - if (mLocked.displayOrientation != orientation) { - // Apply offsets to convert from the pixel top-left corner position to the pixel center. - // This creates an invariant frame of reference that we can easily rotate when - // taking into account that the pointer may be located at fractional pixel offsets. - float x = mLocked.pointerX + 0.5f; - float y = mLocked.pointerY + 0.5f; - float temp; - - // Undo the previous rotation. - switch (mLocked.displayOrientation) { - case DISPLAY_ORIENTATION_90: - temp = x; - x = mLocked.displayWidth - y; - y = temp; - break; - case DISPLAY_ORIENTATION_180: - x = mLocked.displayWidth - x; - y = mLocked.displayHeight - y; - break; - case DISPLAY_ORIENTATION_270: - temp = x; - x = y; - y = mLocked.displayHeight - temp; - break; - } - - // Perform the new rotation. - switch (orientation) { - case DISPLAY_ORIENTATION_90: - temp = x; - x = y; - y = mLocked.displayWidth - temp; - break; - case DISPLAY_ORIENTATION_180: - x = mLocked.displayWidth - x; - y = mLocked.displayHeight - y; - break; - case DISPLAY_ORIENTATION_270: - temp = x; - x = mLocked.displayHeight - y; - y = temp; - break; - } - - // Apply offsets to convert from the pixel center to the pixel top-left corner position - // and save the results. - mLocked.pointerX = x - 0.5f; - mLocked.pointerY = y - 0.5f; - mLocked.displayOrientation = orientation; - } - - updatePointerLocked(); -} - -void PointerController::setPointerIcon(const SpriteIcon& icon) { - AutoMutex _l(mLock); - - mLocked.pointerIcon = icon.copy(); - mLocked.pointerIconChanged = true; - - updatePointerLocked(); -} - -void PointerController::handleMessage(const Message& message) { - switch (message.what) { - case MSG_ANIMATE: - doAnimate(); - break; - case MSG_INACTIVITY_TIMEOUT: - doInactivityTimeout(); - break; - } -} - -void PointerController::doAnimate() { - AutoMutex _l(mLock); - - bool keepAnimating = false; - mLocked.animationPending = false; - nsecs_t frameDelay = systemTime(SYSTEM_TIME_MONOTONIC) - mLocked.animationTime; - - // Animate pointer fade. - if (mLocked.pointerFadeDirection < 0) { - mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION; - if (mLocked.pointerAlpha <= 0.0f) { - mLocked.pointerAlpha = 0.0f; - mLocked.pointerFadeDirection = 0; - } else { - keepAnimating = true; - } - updatePointerLocked(); - } else if (mLocked.pointerFadeDirection > 0) { - mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION; - if (mLocked.pointerAlpha >= 1.0f) { - mLocked.pointerAlpha = 1.0f; - mLocked.pointerFadeDirection = 0; - } else { - keepAnimating = true; - } - updatePointerLocked(); - } - - // Animate spots that are fading out and being removed. - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); - if (spot->id == Spot::INVALID_ID) { - spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION; - if (spot->alpha <= 0) { - mLocked.spots.removeAt(i--); - releaseSpotLocked(spot); - } else { - spot->sprite->setAlpha(spot->alpha); - keepAnimating = true; - } - } - } - - if (keepAnimating) { - startAnimationLocked(); - } -} - -void PointerController::doInactivityTimeout() { - fade(TRANSITION_GRADUAL); -} - -void PointerController::startAnimationLocked() { - if (!mLocked.animationPending) { - mLocked.animationPending = true; - mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC); - mLooper->sendMessageDelayed(ANIMATION_FRAME_INTERVAL, mHandler, Message(MSG_ANIMATE)); - } -} - -void PointerController::resetInactivityTimeoutLocked() { - mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT); - - nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT - ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL; - mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT); -} - -void PointerController::removeInactivityTimeoutLocked() { - mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT); -} - -void PointerController::updatePointerLocked() { - mSpriteController->openTransaction(); - - mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER); - mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY); - - if (mLocked.pointerAlpha > 0) { - mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha); - mLocked.pointerSprite->setVisible(true); - } else { - mLocked.pointerSprite->setVisible(false); - } - - if (mLocked.pointerIconChanged || mLocked.presentationChanged) { - mLocked.pointerSprite->setIcon(mLocked.presentation == PRESENTATION_POINTER - ? mLocked.pointerIcon : mResources.spotAnchor); - mLocked.pointerIconChanged = false; - mLocked.presentationChanged = false; - } - - mSpriteController->closeTransaction(); -} - -PointerController::Spot* PointerController::getSpotLocked(uint32_t id) { - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); - if (spot->id == id) { - return spot; - } - } - return NULL; -} - -PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) { - // Remove spots until we have fewer than MAX_SPOTS remaining. - while (mLocked.spots.size() >= MAX_SPOTS) { - Spot* spot = removeFirstFadingSpotLocked(); - if (!spot) { - spot = mLocked.spots.itemAt(0); - mLocked.spots.removeAt(0); - } - releaseSpotLocked(spot); - } - - // Obtain a sprite from the recycled pool. - sp<Sprite> sprite; - if (! mLocked.recycledSprites.isEmpty()) { - sprite = mLocked.recycledSprites.top(); - mLocked.recycledSprites.pop(); - } else { - sprite = mSpriteController->createSprite(); - } - - // Return the new spot. - Spot* spot = new Spot(id, sprite); - mLocked.spots.push(spot); - return spot; -} - -PointerController::Spot* PointerController::removeFirstFadingSpotLocked() { - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); - if (spot->id == Spot::INVALID_ID) { - mLocked.spots.removeAt(i); - return spot; - } - } - return NULL; -} - -void PointerController::releaseSpotLocked(Spot* spot) { - spot->sprite->clearIcon(); - - if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) { - mLocked.recycledSprites.push(spot->sprite); - } - - delete spot; -} - -void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) { - if (spot->id != Spot::INVALID_ID) { - spot->id = Spot::INVALID_ID; - startAnimationLocked(); - } -} - -void PointerController::fadeOutAndReleaseAllSpotsLocked() { - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); - fadeOutAndReleaseSpotLocked(spot); - } -} - -void PointerController::loadResources() { - mPolicy->loadPointerResources(&mResources); -} - - -// --- PointerController::Spot --- - -void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) { - sprite->setLayer(Sprite::BASE_LAYER_SPOT + id); - sprite->setAlpha(alpha); - sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale)); - sprite->setPosition(x, y); - - this->x = x; - this->y = y; - - if (icon != lastIcon) { - lastIcon = icon; - if (icon) { - sprite->setIcon(*icon); - sprite->setVisible(true); - } else { - sprite->setVisible(false); - } - } -} - -} // namespace android diff --git a/widget/gonk/libui/PointerController.h b/widget/gonk/libui/PointerController.h deleted file mode 100644 index eb48d9a1f..000000000 --- a/widget/gonk/libui/PointerController.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UI_POINTER_CONTROLLER_H -#define _UI_POINTER_CONTROLLER_H - -#include "SpriteController.h" - -#include <ui/DisplayInfo.h> -#include "Input.h" -#include <utils/BitSet.h> -#include <utils/RefBase.h> -#include <utils/Looper.h> -#include <utils/String8.h> - -#include <SkBitmap.h> - -namespace android { - -/** - * Interface for tracking a mouse / touch pad pointer and touch pad spots. - * - * The spots are sprites on screen that visually represent the positions of - * fingers - * - * The pointer controller is responsible for providing synchronization and for tracking - * display orientation changes if needed. - */ -class PointerControllerInterface : public virtual RefBase { -protected: - PointerControllerInterface() { } - virtual ~PointerControllerInterface() { } - -public: - /* Gets the bounds of the region that the pointer can traverse. - * Returns true if the bounds are available. */ - virtual bool getBounds(float* outMinX, float* outMinY, - float* outMaxX, float* outMaxY) const = 0; - - /* Move the pointer. */ - virtual void move(float deltaX, float deltaY) = 0; - - /* Sets a mask that indicates which buttons are pressed. */ - virtual void setButtonState(int32_t buttonState) = 0; - - /* Gets a mask that indicates which buttons are pressed. */ - virtual int32_t getButtonState() const = 0; - - /* Sets the absolute location of the pointer. */ - virtual void setPosition(float x, float y) = 0; - - /* Gets the absolute location of the pointer. */ - virtual void getPosition(float* outX, float* outY) const = 0; - - enum Transition { - // Fade/unfade immediately. - TRANSITION_IMMEDIATE, - // Fade/unfade gradually. - TRANSITION_GRADUAL, - }; - - /* Fades the pointer out now. */ - virtual void fade(Transition transition) = 0; - - /* Makes the pointer visible if it has faded out. - * The pointer never unfades itself automatically. This method must be called - * by the client whenever the pointer is moved or a button is pressed and it - * wants to ensure that the pointer becomes visible again. */ - virtual void unfade(Transition transition) = 0; - - enum Presentation { - // Show the mouse pointer. - PRESENTATION_POINTER, - // Show spots and a spot anchor in place of the mouse pointer. - PRESENTATION_SPOT, - }; - - /* Sets the mode of the pointer controller. */ - virtual void setPresentation(Presentation presentation) = 0; - - /* Sets the spots for the current gesture. - * The spots are not subject to the inactivity timeout like the pointer - * itself it since they are expected to remain visible for so long as - * the fingers are on the touch pad. - * - * The values of the AMOTION_EVENT_AXIS_PRESSURE axis is significant. - * For spotCoords, pressure != 0 indicates that the spot's location is being - * pressed (not hovering). - */ - virtual void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, - BitSet32 spotIdBits) = 0; - - /* Removes all spots. */ - virtual void clearSpots() = 0; -}; - - -/* - * Pointer resources. - */ -struct PointerResources { - SpriteIcon spotHover; - SpriteIcon spotTouch; - SpriteIcon spotAnchor; -}; - - -/* - * Pointer controller policy interface. - * - * The pointer controller policy is used by the pointer controller to interact with - * the Window Manager and other system components. - * - * The actual implementation is partially supported by callbacks into the DVM - * via JNI. This interface is also mocked in the unit tests. - */ -class PointerControllerPolicyInterface : public virtual RefBase { -protected: - PointerControllerPolicyInterface() { } - virtual ~PointerControllerPolicyInterface() { } - -public: - virtual void loadPointerResources(PointerResources* outResources) = 0; -}; - - -/* - * Tracks pointer movements and draws the pointer sprite to a surface. - * - * Handles pointer acceleration and animation. - */ -class PointerController : public PointerControllerInterface, public MessageHandler { -protected: - virtual ~PointerController(); - -public: - enum InactivityTimeout { - INACTIVITY_TIMEOUT_NORMAL = 0, - INACTIVITY_TIMEOUT_SHORT = 1, - }; - - PointerController(const sp<PointerControllerPolicyInterface>& policy, - const sp<Looper>& looper, const sp<SpriteController>& spriteController); - - virtual bool getBounds(float* outMinX, float* outMinY, - float* outMaxX, float* outMaxY) const; - virtual void move(float deltaX, float deltaY); - virtual void setButtonState(int32_t buttonState); - virtual int32_t getButtonState() const; - virtual void setPosition(float x, float y); - virtual void getPosition(float* outX, float* outY) const; - virtual void fade(Transition transition); - virtual void unfade(Transition transition); - - virtual void setPresentation(Presentation presentation); - virtual void setSpots(const PointerCoords* spotCoords, - const uint32_t* spotIdToIndex, BitSet32 spotIdBits); - virtual void clearSpots(); - - void setDisplayViewport(int32_t width, int32_t height, int32_t orientation); - void setPointerIcon(const SpriteIcon& icon); - void setInactivityTimeout(InactivityTimeout inactivityTimeout); - -private: - static const size_t MAX_RECYCLED_SPRITES = 12; - static const size_t MAX_SPOTS = 12; - - enum { - MSG_ANIMATE, - MSG_INACTIVITY_TIMEOUT, - }; - - struct Spot { - static const uint32_t INVALID_ID = 0xffffffff; - - uint32_t id; - sp<Sprite> sprite; - float alpha; - float scale; - float x, y; - - inline Spot(uint32_t id, const sp<Sprite>& sprite) - : id(id), sprite(sprite), alpha(1.0f), scale(1.0f), - x(0.0f), y(0.0f), lastIcon(NULL) { } - - void updateSprite(const SpriteIcon* icon, float x, float y); - - private: - const SpriteIcon* lastIcon; - }; - - mutable Mutex mLock; - - sp<PointerControllerPolicyInterface> mPolicy; - sp<Looper> mLooper; - sp<SpriteController> mSpriteController; - sp<WeakMessageHandler> mHandler; - - PointerResources mResources; - - struct Locked { - bool animationPending; - nsecs_t animationTime; - - int32_t displayWidth; - int32_t displayHeight; - int32_t displayOrientation; - - InactivityTimeout inactivityTimeout; - - Presentation presentation; - bool presentationChanged; - - int32_t pointerFadeDirection; - float pointerX; - float pointerY; - float pointerAlpha; - sp<Sprite> pointerSprite; - SpriteIcon pointerIcon; - bool pointerIconChanged; - - int32_t buttonState; - - Vector<Spot*> spots; - Vector<sp<Sprite> > recycledSprites; - } mLocked; - - bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const; - void setPositionLocked(float x, float y); - - void handleMessage(const Message& message); - void doAnimate(); - void doInactivityTimeout(); - - void startAnimationLocked(); - - void resetInactivityTimeoutLocked(); - void removeInactivityTimeoutLocked(); - void updatePointerLocked(); - - Spot* getSpotLocked(uint32_t id); - Spot* createAndAddSpotLocked(uint32_t id); - Spot* removeFirstFadingSpotLocked(); - void releaseSpotLocked(Spot* spot); - void fadeOutAndReleaseSpotLocked(Spot* spot); - void fadeOutAndReleaseAllSpotsLocked(); - - void loadResources(); -}; - -} // namespace android - -#endif // _UI_POINTER_CONTROLLER_H diff --git a/widget/gonk/libui/PowerManager.h b/widget/gonk/libui/PowerManager.h deleted file mode 100644 index ba98db07c..000000000 --- a/widget/gonk/libui/PowerManager.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_POWER_MANAGER_H -#define _ANDROIDFW_POWER_MANAGER_H - - -namespace android { - -enum { - USER_ACTIVITY_EVENT_OTHER = 0, - USER_ACTIVITY_EVENT_BUTTON = 1, - USER_ACTIVITY_EVENT_TOUCH = 2, - - USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_TOUCH, // Last valid event code. -}; - -} // namespace android - -#endif // _ANDROIDFW_POWER_MANAGER_H diff --git a/widget/gonk/libui/SpriteController.cpp b/widget/gonk/libui/SpriteController.cpp deleted file mode 100644 index 8677476b1..000000000 --- a/widget/gonk/libui/SpriteController.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Sprites" - -//#define LOG_NDEBUG 0 - -#include "SpriteController.h" - -#include "cutils_log.h" -#include <utils/String8.h> -#ifdef HAVE_ANDROID_OS -#include <gui/Surface.h> -#endif - -#include <SkBitmap.h> -#include <SkCanvas.h> -#include <SkColor.h> -#include <SkPaint.h> -#include <SkXfermode.h> -#include <android/native_window.h> - -namespace android { - -// --- SpriteController --- - -SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) : - mLooper(looper), mOverlayLayer(overlayLayer) { -#ifdef HAVE_ANDROID_OS - mHandler = new WeakMessageHandler(this); -#endif - - mLocked.transactionNestingCount = 0; - mLocked.deferredSpriteUpdate = false; -} - -SpriteController::~SpriteController() { -#ifdef HAVE_ANDROID_OS - mLooper->removeMessages(mHandler); - - if (mSurfaceComposerClient != NULL) { - mSurfaceComposerClient->dispose(); - mSurfaceComposerClient.clear(); - } -#endif -} - -sp<Sprite> SpriteController::createSprite() { - return new SpriteImpl(this); -} - -void SpriteController::openTransaction() { - AutoMutex _l(mLock); - - mLocked.transactionNestingCount += 1; -} - -void SpriteController::closeTransaction() { - AutoMutex _l(mLock); - - LOG_ALWAYS_FATAL_IF(mLocked.transactionNestingCount == 0, - "Sprite closeTransaction() called but there is no open sprite transaction"); - - mLocked.transactionNestingCount -= 1; - if (mLocked.transactionNestingCount == 0 && mLocked.deferredSpriteUpdate) { - mLocked.deferredSpriteUpdate = false; -#ifdef HAVE_ANDROID_OS - mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES)); -#endif - } -} - -void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) { - bool wasEmpty = mLocked.invalidatedSprites.isEmpty(); - mLocked.invalidatedSprites.push(sprite); - if (wasEmpty) { - if (mLocked.transactionNestingCount != 0) { - mLocked.deferredSpriteUpdate = true; - } else { -#ifdef HAVE_ANDROID_OS - mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES)); -#endif - } - } -} - -#ifdef HAVE_ANDROID_OS -void SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) { - bool wasEmpty = mLocked.disposedSurfaces.isEmpty(); - mLocked.disposedSurfaces.push(surfaceControl); - if (wasEmpty) { - mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES)); - } -} - -void SpriteController::handleMessage(const Message& message) { - switch (message.what) { - case MSG_UPDATE_SPRITES: - doUpdateSprites(); - break; - case MSG_DISPOSE_SURFACES: - doDisposeSurfaces(); - break; - } -} -#endif - -void SpriteController::doUpdateSprites() { - // Collect information about sprite updates. - // Each sprite update record includes a reference to its associated sprite so we can - // be certain the sprites will not be deleted while this function runs. Sprites - // may invalidate themselves again during this time but we will handle those changes - // in the next iteration. - Vector<SpriteUpdate> updates; - size_t numSprites; - { // acquire lock - AutoMutex _l(mLock); - - numSprites = mLocked.invalidatedSprites.size(); - for (size_t i = 0; i < numSprites; i++) { - const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i); - - updates.push(SpriteUpdate(sprite, sprite->getStateLocked())); - sprite->resetDirtyLocked(); - } - mLocked.invalidatedSprites.clear(); - } // release lock - - // Create missing surfaces. - bool surfaceChanged = false; -#ifdef HAVE_ANDROID_OS - for (size_t i = 0; i < numSprites; i++) { - SpriteUpdate& update = updates.editItemAt(i); - if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) { - update.state.surfaceWidth = update.state.icon.bitmap.width(); - update.state.surfaceHeight = update.state.icon.bitmap.height(); - update.state.surfaceDrawn = false; - update.state.surfaceVisible = false; - update.state.surfaceControl = obtainSurface( - update.state.surfaceWidth, update.state.surfaceHeight); - if (update.state.surfaceControl != NULL) { - update.surfaceChanged = surfaceChanged = true; - } - } - } -#endif - - // Resize sprites if needed, inside a global transaction. -#ifdef HAVE_ANDROID_OS - bool haveGlobalTransaction = false; - for (size_t i = 0; i < numSprites; i++) { - SpriteUpdate& update = updates.editItemAt(i); - if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) { - int32_t desiredWidth = update.state.icon.bitmap.width(); - int32_t desiredHeight = update.state.icon.bitmap.height(); - if (update.state.surfaceWidth < desiredWidth - || update.state.surfaceHeight < desiredHeight) { - if (!haveGlobalTransaction) { - SurfaceComposerClient::openGlobalTransaction(); - haveGlobalTransaction = true; - } - - status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight); - if (status) { - ALOGE("Error %d resizing sprite surface from %dx%d to %dx%d", - status, update.state.surfaceWidth, update.state.surfaceHeight, - desiredWidth, desiredHeight); - } else { - update.state.surfaceWidth = desiredWidth; - update.state.surfaceHeight = desiredHeight; - update.state.surfaceDrawn = false; - update.surfaceChanged = surfaceChanged = true; - - if (update.state.surfaceVisible) { - status = update.state.surfaceControl->hide(); - if (status) { - ALOGE("Error %d hiding sprite surface after resize.", status); - } else { - update.state.surfaceVisible = false; - } - } - } - } - } - } -#endif -#ifdef HAVE_ANDROID_OS - if (haveGlobalTransaction) { - SurfaceComposerClient::closeGlobalTransaction(); - } -#endif - - // Redraw sprites if needed. - for (size_t i = 0; i < numSprites; i++) { - SpriteUpdate& update = updates.editItemAt(i); - - if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) { - update.state.surfaceDrawn = false; - update.surfaceChanged = surfaceChanged = true; - } - -#ifdef HAVE_ANDROID_OS - if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn - && update.state.wantSurfaceVisible()) { - sp<Surface> surface = update.state.surfaceControl->getSurface(); - ANativeWindow_Buffer outBuffer; - status_t status = surface->lock(&outBuffer, NULL); - if (status) { - ALOGE("Error %d locking sprite surface before drawing.", status); - } else { - SkBitmap surfaceBitmap; - ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format); - surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config, - outBuffer.width, outBuffer.height, bpr); - surfaceBitmap.setPixels(outBuffer.bits); - - SkCanvas surfaceCanvas(surfaceBitmap); - - SkPaint paint; - paint.setXfermodeMode(SkXfermode::kSrc_Mode); - surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint); - - if (outBuffer.width > uint32_t(update.state.icon.bitmap.width())) { - paint.setColor(0); // transparent fill color - surfaceCanvas.drawRectCoords(update.state.icon.bitmap.width(), 0, - outBuffer.width, update.state.icon.bitmap.height(), paint); - } - if (outBuffer.height > uint32_t(update.state.icon.bitmap.height())) { - paint.setColor(0); // transparent fill color - surfaceCanvas.drawRectCoords(0, update.state.icon.bitmap.height(), - outBuffer.width, outBuffer.height, paint); - } - - status = surface->unlockAndPost(); - if (status) { - ALOGE("Error %d unlocking and posting sprite surface after drawing.", status); - } else { - update.state.surfaceDrawn = true; - update.surfaceChanged = surfaceChanged = true; - } - } - } -#endif - } - -#ifdef HAVE_ANDROID_OS - // Set sprite surface properties and make them visible. - bool haveTransaction = false; - for (size_t i = 0; i < numSprites; i++) { - SpriteUpdate& update = updates.editItemAt(i); - bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible() - && update.state.surfaceDrawn; - bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible; - bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible; - if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden - || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA - | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER - | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) { - status_t status; - if (!haveTransaction) { - SurfaceComposerClient::openGlobalTransaction(); - haveTransaction = true; - } - - if (wantSurfaceVisibleAndDrawn - && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) { - status = update.state.surfaceControl->setAlpha(update.state.alpha); - if (status) { - ALOGE("Error %d setting sprite surface alpha.", status); - } - } - - if (wantSurfaceVisibleAndDrawn - && (becomingVisible || (update.state.dirty & (DIRTY_POSITION - | DIRTY_HOTSPOT)))) { - status = update.state.surfaceControl->setPosition( - update.state.positionX - update.state.icon.hotSpotX, - update.state.positionY - update.state.icon.hotSpotY); - if (status) { - ALOGE("Error %d setting sprite surface position.", status); - } - } - - if (wantSurfaceVisibleAndDrawn - && (becomingVisible - || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) { - status = update.state.surfaceControl->setMatrix( - update.state.transformationMatrix.dsdx, - update.state.transformationMatrix.dtdx, - update.state.transformationMatrix.dsdy, - update.state.transformationMatrix.dtdy); - if (status) { - ALOGE("Error %d setting sprite surface transformation matrix.", status); - } - } - - int32_t surfaceLayer = mOverlayLayer + update.state.layer; - if (wantSurfaceVisibleAndDrawn - && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) { - status = update.state.surfaceControl->setLayer(surfaceLayer); - if (status) { - ALOGE("Error %d setting sprite surface layer.", status); - } - } - - if (becomingVisible) { - status = update.state.surfaceControl->show(); - if (status) { - ALOGE("Error %d showing sprite surface.", status); - } else { - update.state.surfaceVisible = true; - update.surfaceChanged = surfaceChanged = true; - } - } else if (becomingHidden) { - status = update.state.surfaceControl->hide(); - if (status) { - ALOGE("Error %d hiding sprite surface.", status); - } else { - update.state.surfaceVisible = false; - update.surfaceChanged = surfaceChanged = true; - } - } - } - } -#endif - -#ifdef HAVE_ANDROID_OS - if (haveTransaction) { - SurfaceComposerClient::closeGlobalTransaction(); - } -#endif - -#ifdef HAVE_ANDROID_OS - // If any surfaces were changed, write back the new surface properties to the sprites. - if (surfaceChanged) { // acquire lock - AutoMutex _l(mLock); - - for (size_t i = 0; i < numSprites; i++) { - const SpriteUpdate& update = updates.itemAt(i); - - if (update.surfaceChanged) { - update.sprite->setSurfaceLocked(update.state.surfaceControl, - update.state.surfaceWidth, update.state.surfaceHeight, - update.state.surfaceDrawn, update.state.surfaceVisible); - } - } - } // release lock -#endif - - // Clear the sprite update vector outside the lock. It is very important that - // we do not clear sprite references inside the lock since we could be releasing - // the last remaining reference to the sprite here which would result in the - // sprite being deleted and the lock being reacquired by the sprite destructor - // while already held. - updates.clear(); -} - -void SpriteController::doDisposeSurfaces() { -#ifdef HAVE_ANDROID_OS - // Collect disposed surfaces. - Vector<sp<SurfaceControl> > disposedSurfaces; - { // acquire lock - AutoMutex _l(mLock); - - disposedSurfaces = mLocked.disposedSurfaces; - mLocked.disposedSurfaces.clear(); - } // release lock - - // Release the last reference to each surface outside of the lock. - // We don't want the surfaces to be deleted while we are holding our lock. - disposedSurfaces.clear(); -#endif -} - -void SpriteController::ensureSurfaceComposerClient() { -#ifdef HAVE_ANDROID_OS - if (mSurfaceComposerClient == NULL) { - mSurfaceComposerClient = new SurfaceComposerClient(); - } -#endif -} - -#ifdef HAVE_ANDROID_OS -sp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height) { - ensureSurfaceComposerClient(); - - sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface( - String8("Sprite"), width, height, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eHidden); - if (surfaceControl == NULL || !surfaceControl->isValid()) { - ALOGE("Error creating sprite surface."); - return NULL; - } - return surfaceControl; -} -#endif - - -// --- SpriteController::SpriteImpl --- - -SpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) : - mController(controller) { -} - -SpriteController::SpriteImpl::~SpriteImpl() { - AutoMutex _m(mController->mLock); - -#ifdef HAVE_ANDROID_OS - // Let the controller take care of deleting the last reference to sprite - // surfaces so that we do not block the caller on an IPC here. - if (mLocked.state.surfaceControl != NULL) { - mController->disposeSurfaceLocked(mLocked.state.surfaceControl); - mLocked.state.surfaceControl.clear(); - } -#endif -} - -void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) { - AutoMutex _l(mController->mLock); - -#ifdef HAVE_ANDROID_OS - uint32_t dirty; - if (icon.isValid()) { - icon.bitmap.copyTo(&mLocked.state.icon.bitmap, SkBitmap::kARGB_8888_Config); - - if (!mLocked.state.icon.isValid() - || mLocked.state.icon.hotSpotX != icon.hotSpotX - || mLocked.state.icon.hotSpotY != icon.hotSpotY) { - mLocked.state.icon.hotSpotX = icon.hotSpotX; - mLocked.state.icon.hotSpotY = icon.hotSpotY; - dirty = DIRTY_BITMAP | DIRTY_HOTSPOT; - } else { - dirty = DIRTY_BITMAP; - } - } else if (mLocked.state.icon.isValid()) { - mLocked.state.icon.bitmap.reset(); - dirty = DIRTY_BITMAP | DIRTY_HOTSPOT; - } else { - return; // setting to invalid icon and already invalid so nothing to do - } - - invalidateLocked(dirty); -#endif -} - -void SpriteController::SpriteImpl::setVisible(bool visible) { - AutoMutex _l(mController->mLock); - - if (mLocked.state.visible != visible) { - mLocked.state.visible = visible; - invalidateLocked(DIRTY_VISIBILITY); - } -} - -void SpriteController::SpriteImpl::setPosition(float x, float y) { - AutoMutex _l(mController->mLock); - - if (mLocked.state.positionX != x || mLocked.state.positionY != y) { - mLocked.state.positionX = x; - mLocked.state.positionY = y; - invalidateLocked(DIRTY_POSITION); - } -} - -void SpriteController::SpriteImpl::setLayer(int32_t layer) { - AutoMutex _l(mController->mLock); - - if (mLocked.state.layer != layer) { - mLocked.state.layer = layer; - invalidateLocked(DIRTY_LAYER); - } -} - -void SpriteController::SpriteImpl::setAlpha(float alpha) { - AutoMutex _l(mController->mLock); - - if (mLocked.state.alpha != alpha) { - mLocked.state.alpha = alpha; - invalidateLocked(DIRTY_ALPHA); - } -} - -void SpriteController::SpriteImpl::setTransformationMatrix( - const SpriteTransformationMatrix& matrix) { - AutoMutex _l(mController->mLock); - - if (mLocked.state.transformationMatrix != matrix) { - mLocked.state.transformationMatrix = matrix; - invalidateLocked(DIRTY_TRANSFORMATION_MATRIX); - } -} - -void SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) { - bool wasDirty = mLocked.state.dirty; - mLocked.state.dirty |= dirty; - - if (!wasDirty) { - mController->invalidateSpriteLocked(this); - } -} - -} // namespace android diff --git a/widget/gonk/libui/SpriteController.h b/widget/gonk/libui/SpriteController.h deleted file mode 100644 index 4926095ec..000000000 --- a/widget/gonk/libui/SpriteController.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UI_SPRITES_H -#define _UI_SPRITES_H - -#include <utils/RefBase.h> -#include <utils/Looper.h> - -#ifdef HAVE_ANDROID_OS -#include <gui/SurfaceComposerClient.h> -#endif - -#include <SkBitmap.h> - -namespace android { - -/* - * Transformation matrix for a sprite. - */ -struct SpriteTransformationMatrix { - inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { } - inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) : - dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { } - - float dsdx; - float dtdx; - float dsdy; - float dtdy; - - inline bool operator== (const SpriteTransformationMatrix& other) { - return dsdx == other.dsdx - && dtdx == other.dtdx - && dsdy == other.dsdy - && dtdy == other.dtdy; - } - - inline bool operator!= (const SpriteTransformationMatrix& other) { - return !(*this == other); - } -}; - -/* - * Icon that a sprite displays, including its hotspot. - */ -struct SpriteIcon { - inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { } -#ifdef HAVE_ANDROID_OS - inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) : - bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { } - - SkBitmap bitmap; -#endif - float hotSpotX; - float hotSpotY; - - inline SpriteIcon copy() const { -#ifdef HAVE_ANDROID_OS - SkBitmap bitmapCopy; - bitmap.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config); - return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY); -#else - return SpriteIcon(); -#endif - } - - inline void reset() { -#ifdef HAVE_ANDROID_OS - bitmap.reset(); - hotSpotX = 0; - hotSpotY = 0; -#endif - } - - inline bool isValid() const { -#ifdef HAVE_ANDROID_OS - return !bitmap.isNull() && !bitmap.empty(); -#else - return false; -#endif - } -}; - -/* - * A sprite is a simple graphical object that is displayed on-screen above other layers. - * The basic sprite class is an interface. - * The implementation is provided by the sprite controller. - */ -class Sprite : public RefBase { -protected: - Sprite() { } - virtual ~Sprite() { } - -public: - enum { - // The base layer for pointer sprites. - BASE_LAYER_POINTER = 0, // reserve space for 1 pointer - - // The base layer for spot sprites. - BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots - }; - - /* Sets the bitmap that is drawn by the sprite. - * The sprite retains a copy of the bitmap for subsequent rendering. */ - virtual void setIcon(const SpriteIcon& icon) = 0; - - inline void clearIcon() { - setIcon(SpriteIcon()); - } - - /* Sets whether the sprite is visible. */ - virtual void setVisible(bool visible) = 0; - - /* Sets the sprite position on screen, relative to the sprite's hot spot. */ - virtual void setPosition(float x, float y) = 0; - - /* Sets the layer of the sprite, relative to the system sprite overlay layer. - * Layer 0 is the overlay layer, > 0 appear above this layer. */ - virtual void setLayer(int32_t layer) = 0; - - /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */ - virtual void setAlpha(float alpha) = 0; - - /* Sets the sprite transformation matrix. */ - virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0; -}; - -/* - * Displays sprites on the screen. - * - * This interface is used by PointerController and SpotController to draw pointers or - * spot representations of fingers. It is not intended for general purpose use - * by other components. - * - * All sprite position updates and rendering is performed asynchronously. - * - * Clients are responsible for animating sprites by periodically updating their properties. - */ -class SpriteController : public MessageHandler { -protected: - virtual ~SpriteController(); - -public: - SpriteController(const sp<Looper>& looper, int32_t overlayLayer); - - /* Creates a new sprite, initially invisible. */ - sp<Sprite> createSprite(); - - /* Opens or closes a transaction to perform a batch of sprite updates as part of - * a single operation such as setPosition and setAlpha. It is not necessary to - * open a transaction when updating a single property. - * Calls to openTransaction() nest and must be matched by an equal number - * of calls to closeTransaction(). */ - void openTransaction(); - void closeTransaction(); - -private: - enum { - MSG_UPDATE_SPRITES, - MSG_DISPOSE_SURFACES, - }; - - enum { - DIRTY_BITMAP = 1 << 0, - DIRTY_ALPHA = 1 << 1, - DIRTY_POSITION = 1 << 2, - DIRTY_TRANSFORMATION_MATRIX = 1 << 3, - DIRTY_LAYER = 1 << 4, - DIRTY_VISIBILITY = 1 << 5, - DIRTY_HOTSPOT = 1 << 6, - }; - - /* Describes the state of a sprite. - * This structure is designed so that it can be copied during updates so that - * surfaces can be resized and redrawn without blocking the client by holding a lock - * on the sprites for a long time. - * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */ - struct SpriteState { - inline SpriteState() : - dirty(0), visible(false), - positionX(0), positionY(0), layer(0), alpha(1.0f), - surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) { - } - - uint32_t dirty; - - SpriteIcon icon; - bool visible; - float positionX; - float positionY; - int32_t layer; - float alpha; - SpriteTransformationMatrix transformationMatrix; - -#ifdef HAVE_ANDROID_OS - sp<SurfaceControl> surfaceControl; -#endif - int32_t surfaceWidth; - int32_t surfaceHeight; - bool surfaceDrawn; - bool surfaceVisible; - - inline bool wantSurfaceVisible() const { - return visible && alpha > 0.0f && icon.isValid(); - } - }; - - /* Client interface for a sprite. - * Requests acquire a lock on the controller, update local state and request the - * controller to invalidate the sprite. - * The real heavy lifting of creating, resizing and redrawing surfaces happens - * asynchronously with no locks held except in short critical section to copy - * the sprite state before the work and update the sprite surface control afterwards. - */ - class SpriteImpl : public Sprite { - protected: - virtual ~SpriteImpl(); - - public: - SpriteImpl(const sp<SpriteController> controller); - - virtual void setIcon(const SpriteIcon& icon); - virtual void setVisible(bool visible); - virtual void setPosition(float x, float y); - virtual void setLayer(int32_t layer); - virtual void setAlpha(float alpha); - virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix); - - inline const SpriteState& getStateLocked() const { - return mLocked.state; - } - - inline void resetDirtyLocked() { - mLocked.state.dirty = 0; - } - -#ifdef HAVE_ANDROID_OS - inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl, - int32_t width, int32_t height, bool drawn, bool visible) { - mLocked.state.surfaceControl = surfaceControl; - mLocked.state.surfaceWidth = width; - mLocked.state.surfaceHeight = height; - mLocked.state.surfaceDrawn = drawn; - mLocked.state.surfaceVisible = visible; - } -#endif - - private: - sp<SpriteController> mController; - - struct Locked { - SpriteState state; - } mLocked; // guarded by mController->mLock - - void invalidateLocked(uint32_t dirty); - }; - - /* Stores temporary information collected during the sprite update cycle. */ - struct SpriteUpdate { - inline SpriteUpdate() : surfaceChanged(false) { } - inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) : - sprite(sprite), state(state), surfaceChanged(false) { - } - - sp<SpriteImpl> sprite; - SpriteState state; - bool surfaceChanged; - }; - - mutable Mutex mLock; - - sp<Looper> mLooper; - const int32_t mOverlayLayer; -#ifdef HAVE_ANDROID_OS - sp<WeakMessageHandler> mHandler; - - sp<SurfaceComposerClient> mSurfaceComposerClient; -#endif - - struct Locked { - Vector<sp<SpriteImpl> > invalidatedSprites; -#ifdef HAVE_ANDROID_OS - Vector<sp<SurfaceControl> > disposedSurfaces; -#endif - uint32_t transactionNestingCount; - bool deferredSpriteUpdate; - } mLocked; // guarded by mLock - - void invalidateSpriteLocked(const sp<SpriteImpl>& sprite); -#ifdef HAVE_ANDROID_OS - void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl); - - void handleMessage(const Message& message); -#endif - void doUpdateSprites(); - void doDisposeSurfaces(); - - void ensureSurfaceComposerClient(); -#ifdef HAVE_ANDROID_OS - sp<SurfaceControl> obtainSurface(int32_t width, int32_t height); -#endif -}; - -} // namespace android - -#endif // _UI_SPRITES_H diff --git a/widget/gonk/libui/Tokenizer.cpp b/widget/gonk/libui/Tokenizer.cpp deleted file mode 100644 index 2f585cb4e..000000000 --- a/widget/gonk/libui/Tokenizer.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Tokenizer" -#include "cutils_log.h" - -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "Tokenizer.h" - -// Enables debug output for the tokenizer. -#define DEBUG_TOKENIZER 0 - - -namespace android { - -static inline bool isDelimiter(char ch, const char* delimiters) { - return strchr(delimiters, ch) != NULL; -} - -Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap, char* buffer, - bool ownBuffer, size_t length) : - mFilename(filename), mFileMap(fileMap), - mBuffer(buffer), mOwnBuffer(ownBuffer), mLength(length), - mCurrent(buffer), mLineNumber(1) { -} - -Tokenizer::~Tokenizer() { - if (mFileMap) { - mFileMap->release(); - } - if (mOwnBuffer) { - delete[] mBuffer; - } -} - -status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) { - *outTokenizer = NULL; - - int result = NO_ERROR; - int fd = ::open(filename.string(), O_RDONLY); - if (fd < 0) { - result = -errno; - ALOGE("Error opening file '%s', %s.", filename.string(), strerror(errno)); - } else { - struct stat stat; - if (fstat(fd, &stat)) { - result = -errno; - ALOGE("Error getting size of file '%s', %s.", filename.string(), strerror(errno)); - } else { - size_t length = size_t(stat.st_size); - - FileMap* fileMap = new FileMap(); - bool ownBuffer = false; - char* buffer; - if (fileMap->create(NULL, fd, 0, length, true)) { - fileMap->advise(FileMap::SEQUENTIAL); - buffer = static_cast<char*>(fileMap->getDataPtr()); - } else { - fileMap->release(); - fileMap = NULL; - - // Fall back to reading into a buffer since we can't mmap files in sysfs. - // The length we obtained from stat is wrong too (it will always be 4096) - // so we must trust that read will read the entire file. - buffer = new char[length]; - ownBuffer = true; - ssize_t nrd = read(fd, buffer, length); - if (nrd < 0) { - result = -errno; - ALOGE("Error reading file '%s', %s.", filename.string(), strerror(errno)); - delete[] buffer; - buffer = NULL; - } else { - length = size_t(nrd); - } - } - - if (!result) { - *outTokenizer = new Tokenizer(filename, fileMap, buffer, ownBuffer, length); - } - } - close(fd); - } - return result; -} - -status_t Tokenizer::fromContents(const String8& filename, - const char* contents, Tokenizer** outTokenizer) { - *outTokenizer = new Tokenizer(filename, NULL, - const_cast<char*>(contents), false, strlen(contents)); - return OK; -} - -String8 Tokenizer::getLocation() const { - String8 result; - result.appendFormat("%s:%d", mFilename.string(), mLineNumber); - return result; -} - -String8 Tokenizer::peekRemainderOfLine() const { - const char* end = getEnd(); - const char* eol = mCurrent; - while (eol != end) { - char ch = *eol; - if (ch == '\n') { - break; - } - eol += 1; - } - return String8(mCurrent, eol - mCurrent); -} - -String8 Tokenizer::nextToken(const char* delimiters) { -#if DEBUG_TOKENIZER - ALOGD("nextToken"); -#endif - const char* end = getEnd(); - const char* tokenStart = mCurrent; - while (mCurrent != end) { - char ch = *mCurrent; - if (ch == '\n' || isDelimiter(ch, delimiters)) { - break; - } - mCurrent += 1; - } - return String8(tokenStart, mCurrent - tokenStart); -} - -void Tokenizer::nextLine() { -#if DEBUG_TOKENIZER - ALOGD("nextLine"); -#endif - const char* end = getEnd(); - while (mCurrent != end) { - char ch = *(mCurrent++); - if (ch == '\n') { - mLineNumber += 1; - break; - } - } -} - -void Tokenizer::skipDelimiters(const char* delimiters) { -#if DEBUG_TOKENIZER - ALOGD("skipDelimiters"); -#endif - const char* end = getEnd(); - while (mCurrent != end) { - char ch = *mCurrent; - if (ch == '\n' || !isDelimiter(ch, delimiters)) { - break; - } - mCurrent += 1; - } -} - -} // namespace android diff --git a/widget/gonk/libui/Tokenizer.h b/widget/gonk/libui/Tokenizer.h deleted file mode 100644 index bb25f374c..000000000 --- a/widget/gonk/libui/Tokenizer.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UTILS_TOKENIZER_H -#define _UTILS_TOKENIZER_H - -#include <assert.h> -#include <utils/Errors.h> -#include <utils/FileMap.h> -#include <utils/String8.h> - -namespace android { - -/** - * A simple tokenizer for loading and parsing ASCII text files line by line. - */ -class Tokenizer { - Tokenizer(const String8& filename, FileMap* fileMap, char* buffer, - bool ownBuffer, size_t length); - -public: - ~Tokenizer(); - - /** - * Opens a file and maps it into memory. - * - * Returns NO_ERROR and a tokenizer for the file, if successful. - * Otherwise returns an error and sets outTokenizer to NULL. - */ - static status_t open(const String8& filename, Tokenizer** outTokenizer); - - /** - * Prepares to tokenize the contents of a string. - * - * Returns NO_ERROR and a tokenizer for the string, if successful. - * Otherwise returns an error and sets outTokenizer to NULL. - */ - static status_t fromContents(const String8& filename, - const char* contents, Tokenizer** outTokenizer); - - /** - * Returns true if at the end of the file. - */ - inline bool isEof() const { return mCurrent == getEnd(); } - - /** - * Returns true if at the end of the line or end of the file. - */ - inline bool isEol() const { return isEof() || *mCurrent == '\n'; } - - /** - * Gets the name of the file. - */ - inline String8 getFilename() const { return mFilename; } - - /** - * Gets a 1-based line number index for the current position. - */ - inline int32_t getLineNumber() const { return mLineNumber; } - - /** - * Formats a location string consisting of the filename and current line number. - * Returns a string like "MyFile.txt:33". - */ - String8 getLocation() const; - - /** - * Gets the character at the current position. - * Returns null at end of file. - */ - inline char peekChar() const { return isEof() ? '\0' : *mCurrent; } - - /** - * Gets the remainder of the current line as a string, excluding the newline character. - */ - String8 peekRemainderOfLine() const; - - /** - * Gets the character at the current position and advances past it. - * Returns null at end of file. - */ - inline char nextChar() { return isEof() ? '\0' : *(mCurrent++); } - - /** - * Gets the next token on this line stopping at the specified delimiters - * or the end of the line whichever comes first and advances past it. - * Also stops at embedded nulls. - * Returns the token or an empty string if the current character is a delimiter - * or is at the end of the line. - */ - String8 nextToken(const char* delimiters); - - /** - * Advances to the next line. - * Does nothing if already at the end of the file. - */ - void nextLine(); - - /** - * Skips over the specified delimiters in the line. - * Also skips embedded nulls. - */ - void skipDelimiters(const char* delimiters); - -private: - Tokenizer(const Tokenizer& other); // not copyable - - String8 mFilename; - FileMap* mFileMap; - char* mBuffer; - bool mOwnBuffer; - size_t mLength; - - const char* mCurrent; - int32_t mLineNumber; - - inline const char* getEnd() const { return mBuffer + mLength; } - -}; - -} // namespace android - -#endif // _UTILS_TOKENIZER_H diff --git a/widget/gonk/libui/Trace.h b/widget/gonk/libui/Trace.h deleted file mode 100644 index 24fbfb602..000000000 --- a/widget/gonk/libui/Trace.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_TRACE_H -#define ANDROID_TRACE_H - -#include <fcntl.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include <cutils/compiler.h> -#include <utils/threads.h> -#include "cutils_trace.h" - -// See <cutils/trace.h> for more ATRACE_* macros. - -// ATRACE_NAME traces the beginning and end of the current scope. To trace -// the correct start and end times this macro should be declared first in the -// scope body. -#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name) -// ATRACE_CALL is an ATRACE_NAME that uses the current function name. -#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__) - -namespace android { - -class ScopedTrace { -public: -inline ScopedTrace(uint64_t tag, const char* name) - : mTag(tag) { -#ifdef HAVE_ANDROID_OS - atrace_begin(mTag,name); -#endif -} - -inline ~ScopedTrace() { -#ifdef HAVE_ANDROID_OS - atrace_end(mTag); -#endif -} - -private: - uint64_t mTag; -}; - -}; // namespace android - -#endif // ANDROID_TRACE_H diff --git a/widget/gonk/libui/VelocityControl.cpp b/widget/gonk/libui/VelocityControl.cpp deleted file mode 100644 index 31365a220..000000000 --- a/widget/gonk/libui/VelocityControl.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "VelocityControl" -//#define LOG_NDEBUG 0 - -// Log debug messages about acceleration. -#define DEBUG_ACCELERATION 0 - -#include <math.h> -#include <limits.h> - -#include "VelocityControl.h" -#include <utils/BitSet.h> -#include <utils/Timers.h> - -namespace android { - -// --- VelocityControl --- - -const nsecs_t VelocityControl::STOP_TIME; - -VelocityControl::VelocityControl() { - reset(); -} - -void VelocityControl::setParameters(const VelocityControlParameters& parameters) { - mParameters = parameters; - reset(); -} - -void VelocityControl::reset() { - mLastMovementTime = LLONG_MIN; - mRawPosition.x = 0; - mRawPosition.y = 0; - mVelocityTracker.clear(); -} - -void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) { - if ((deltaX && *deltaX) || (deltaY && *deltaY)) { - if (eventTime >= mLastMovementTime + STOP_TIME) { -#if DEBUG_ACCELERATION - ALOGD("VelocityControl: stopped, last movement was %0.3fms ago", - (eventTime - mLastMovementTime) * 0.000001f); -#endif - reset(); - } - - mLastMovementTime = eventTime; - if (deltaX) { - mRawPosition.x += *deltaX; - } - if (deltaY) { - mRawPosition.y += *deltaY; - } - mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition); - - float vx, vy; - float scale = mParameters.scale; - if (mVelocityTracker.getVelocity(0, &vx, &vy)) { - float speed = hypotf(vx, vy) * scale; - if (speed >= mParameters.highThreshold) { - // Apply full acceleration above the high speed threshold. - scale *= mParameters.acceleration; - } else if (speed > mParameters.lowThreshold) { - // Linearly interpolate the acceleration to apply between the low and high - // speed thresholds. - scale *= 1 + (speed - mParameters.lowThreshold) - / (mParameters.highThreshold - mParameters.lowThreshold) - * (mParameters.acceleration - 1); - } - -#if DEBUG_ACCELERATION - ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): " - "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f", - mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, - mParameters.acceleration, - vx, vy, speed, scale / mParameters.scale); -#endif - } else { -#if DEBUG_ACCELERATION - ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity", - mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, - mParameters.acceleration); -#endif - } - - if (deltaX) { - *deltaX *= scale; - } - if (deltaY) { - *deltaY *= scale; - } - } -} - -} // namespace android diff --git a/widget/gonk/libui/VelocityControl.h b/widget/gonk/libui/VelocityControl.h deleted file mode 100644 index 8a2c695d6..000000000 --- a/widget/gonk/libui/VelocityControl.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_VELOCITY_CONTROL_H -#define _ANDROIDFW_VELOCITY_CONTROL_H - -#include "Input.h" -#include "VelocityTracker.h" -#include <utils/Timers.h> - -namespace android { - -/* - * Specifies parameters that govern pointer or wheel acceleration. - */ -struct VelocityControlParameters { - // A scale factor that is multiplied with the raw velocity deltas - // prior to applying any other velocity control factors. The scale - // factor should be used to adapt the input device resolution - // (eg. counts per inch) to the output device resolution (eg. pixels per inch). - // - // Must be a positive value. - // Default is 1.0 (no scaling). - float scale; - - // The scaled speed at which acceleration begins to be applied. - // This value establishes the upper bound of a low speed regime for - // small precise motions that are performed without any acceleration. - // - // Must be a non-negative value. - // Default is 0.0 (no low threshold). - float lowThreshold; - - // The scaled speed at which maximum acceleration is applied. - // The difference between highThreshold and lowThreshold controls - // the range of speeds over which the acceleration factor is interpolated. - // The wider the range, the smoother the acceleration. - // - // Must be a non-negative value greater than or equal to lowThreshold. - // Default is 0.0 (no high threshold). - float highThreshold; - - // The acceleration factor. - // When the speed is above the low speed threshold, the velocity will scaled - // by an interpolated value between 1.0 and this amount. - // - // Must be a positive greater than or equal to 1.0. - // Default is 1.0 (no acceleration). - float acceleration; - - VelocityControlParameters() : - scale(1.0f), lowThreshold(0.0f), highThreshold(0.0f), acceleration(1.0f) { - } - - VelocityControlParameters(float scale, float lowThreshold, - float highThreshold, float acceleration) : - scale(scale), lowThreshold(lowThreshold), - highThreshold(highThreshold), acceleration(acceleration) { - } -}; - -/* - * Implements mouse pointer and wheel speed control and acceleration. - */ -class VelocityControl { -public: - VelocityControl(); - - /* Sets the various parameters. */ - void setParameters(const VelocityControlParameters& parameters); - - /* Resets the current movement counters to zero. - * This has the effect of nullifying any acceleration. */ - void reset(); - - /* Translates a raw movement delta into an appropriately - * scaled / accelerated delta based on the current velocity. */ - void move(nsecs_t eventTime, float* deltaX, float* deltaY); - -private: - // If no movements are received within this amount of time, - // we assume the movement has stopped and reset the movement counters. - static const nsecs_t STOP_TIME = 500 * 1000000; // 500 ms - - VelocityControlParameters mParameters; - - nsecs_t mLastMovementTime; - VelocityTracker::Position mRawPosition; - VelocityTracker mVelocityTracker; -}; - -} // namespace android - -#endif // _ANDROIDFW_VELOCITY_CONTROL_H diff --git a/widget/gonk/libui/VelocityTracker.cpp b/widget/gonk/libui/VelocityTracker.cpp deleted file mode 100644 index 11a8bf7fc..000000000 --- a/widget/gonk/libui/VelocityTracker.cpp +++ /dev/null @@ -1,929 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "VelocityTracker" -//#define LOG_NDEBUG 0 -#include "cutils_log.h" - -// Log debug messages about velocity tracking. -#define DEBUG_VELOCITY 0 - -// Log debug messages about the progress of the algorithm itself. -#define DEBUG_STRATEGY 0 - -#include <math.h> -#include <limits.h> - -#include "VelocityTracker.h" -#include <utils/BitSet.h> -#include <utils/String8.h> -#include <utils/Timers.h> - -#include <cutils/properties.h> - -namespace android { - -// Nanoseconds per milliseconds. -static const nsecs_t NANOS_PER_MS = 1000000; - -// Threshold for determining that a pointer has stopped moving. -// Some input devices do not send ACTION_MOVE events in the case where a pointer has -// stopped. We need to detect this case so that we can accurately predict the -// velocity after the pointer starts moving again. -static const nsecs_t ASSUME_POINTER_STOPPED_TIME = 40 * NANOS_PER_MS; - - -static float vectorDot(const float* a, const float* b, uint32_t m) { - float r = 0; - while (m--) { - r += *(a++) * *(b++); - } - return r; -} - -static float vectorNorm(const float* a, uint32_t m) { - float r = 0; - while (m--) { - float t = *(a++); - r += t * t; - } - return sqrtf(r); -} - -#if DEBUG_STRATEGY || DEBUG_VELOCITY -static String8 vectorToString(const float* a, uint32_t m) { - String8 str; - str.append("["); - while (m--) { - str.appendFormat(" %f", *(a++)); - if (m) { - str.append(","); - } - } - str.append(" ]"); - return str; -} - -static String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) { - String8 str; - str.append("["); - for (size_t i = 0; i < m; i++) { - if (i) { - str.append(","); - } - str.append(" ["); - for (size_t j = 0; j < n; j++) { - if (j) { - str.append(","); - } - str.appendFormat(" %f", a[rowMajor ? i * n + j : j * m + i]); - } - str.append(" ]"); - } - str.append(" ]"); - return str; -} -#endif - - -// --- VelocityTracker --- - -// The default velocity tracker strategy. -// Although other strategies are available for testing and comparison purposes, -// this is the strategy that applications will actually use. Be very careful -// when adjusting the default strategy because it can dramatically affect -// (often in a bad way) the user experience. -const char* VelocityTracker::DEFAULT_STRATEGY = "lsq2"; - -VelocityTracker::VelocityTracker(const char* strategy) : - mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1) { - char value[PROPERTY_VALUE_MAX]; - - // Allow the default strategy to be overridden using a system property for debugging. - if (!strategy) { - int length = property_get("debug.velocitytracker.strategy", value, NULL); - if (length > 0) { - strategy = value; - } else { - strategy = DEFAULT_STRATEGY; - } - } - - // Configure the strategy. - if (!configureStrategy(strategy)) { - ALOGD("Unrecognized velocity tracker strategy name '%s'.", strategy); - if (!configureStrategy(DEFAULT_STRATEGY)) { - LOG_ALWAYS_FATAL("Could not create the default velocity tracker strategy '%s'!", - strategy); - } - } -} - -VelocityTracker::~VelocityTracker() { - delete mStrategy; -} - -bool VelocityTracker::configureStrategy(const char* strategy) { - mStrategy = createStrategy(strategy); - return mStrategy != NULL; -} - -VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) { - if (!strcmp("lsq1", strategy)) { - // 1st order least squares. Quality: POOR. - // Frequently underfits the touch data especially when the finger accelerates - // or changes direction. Often underestimates velocity. The direction - // is overly influenced by historical touch points. - return new LeastSquaresVelocityTrackerStrategy(1); - } - if (!strcmp("lsq2", strategy)) { - // 2nd order least squares. Quality: VERY GOOD. - // Pretty much ideal, but can be confused by certain kinds of touch data, - // particularly if the panel has a tendency to generate delayed, - // duplicate or jittery touch coordinates when the finger is released. - return new LeastSquaresVelocityTrackerStrategy(2); - } - if (!strcmp("lsq3", strategy)) { - // 3rd order least squares. Quality: UNUSABLE. - // Frequently overfits the touch data yielding wildly divergent estimates - // of the velocity when the finger is released. - return new LeastSquaresVelocityTrackerStrategy(3); - } - if (!strcmp("wlsq2-delta", strategy)) { - // 2nd order weighted least squares, delta weighting. Quality: EXPERIMENTAL - return new LeastSquaresVelocityTrackerStrategy(2, - LeastSquaresVelocityTrackerStrategy::WEIGHTING_DELTA); - } - if (!strcmp("wlsq2-central", strategy)) { - // 2nd order weighted least squares, central weighting. Quality: EXPERIMENTAL - return new LeastSquaresVelocityTrackerStrategy(2, - LeastSquaresVelocityTrackerStrategy::WEIGHTING_CENTRAL); - } - if (!strcmp("wlsq2-recent", strategy)) { - // 2nd order weighted least squares, recent weighting. Quality: EXPERIMENTAL - return new LeastSquaresVelocityTrackerStrategy(2, - LeastSquaresVelocityTrackerStrategy::WEIGHTING_RECENT); - } - if (!strcmp("int1", strategy)) { - // 1st order integrating filter. Quality: GOOD. - // Not as good as 'lsq2' because it cannot estimate acceleration but it is - // more tolerant of errors. Like 'lsq1', this strategy tends to underestimate - // the velocity of a fling but this strategy tends to respond to changes in - // direction more quickly and accurately. - return new IntegratingVelocityTrackerStrategy(1); - } - if (!strcmp("int2", strategy)) { - // 2nd order integrating filter. Quality: EXPERIMENTAL. - // For comparison purposes only. Unlike 'int1' this strategy can compensate - // for acceleration but it typically overestimates the effect. - return new IntegratingVelocityTrackerStrategy(2); - } - if (!strcmp("legacy", strategy)) { - // Legacy velocity tracker algorithm. Quality: POOR. - // For comparison purposes only. This algorithm is strongly influenced by - // old data points, consistently underestimates velocity and takes a very long - // time to adjust to changes in direction. - return new LegacyVelocityTrackerStrategy(); - } - return NULL; -} - -void VelocityTracker::clear() { - mCurrentPointerIdBits.clear(); - mActivePointerId = -1; - - mStrategy->clear(); -} - -void VelocityTracker::clearPointers(BitSet32 idBits) { - BitSet32 remainingIdBits(mCurrentPointerIdBits.value & ~idBits.value); - mCurrentPointerIdBits = remainingIdBits; - - if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) { - mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1; - } - - mStrategy->clearPointers(idBits); -} - -void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) { - while (idBits.count() > MAX_POINTERS) { - idBits.clearLastMarkedBit(); - } - - if ((mCurrentPointerIdBits.value & idBits.value) - && eventTime >= mLastEventTime + ASSUME_POINTER_STOPPED_TIME) { -#if DEBUG_VELOCITY - ALOGD("VelocityTracker: stopped for %0.3f ms, clearing state.", - (eventTime - mLastEventTime) * 0.000001f); -#endif - // We have not received any movements for too long. Assume that all pointers - // have stopped. - mStrategy->clear(); - } - mLastEventTime = eventTime; - - mCurrentPointerIdBits = idBits; - if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) { - mActivePointerId = idBits.isEmpty() ? -1 : idBits.firstMarkedBit(); - } - - mStrategy->addMovement(eventTime, idBits, positions); - -#if DEBUG_VELOCITY - ALOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d", - eventTime, idBits.value, mActivePointerId); - for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) { - uint32_t id = iterBits.firstMarkedBit(); - uint32_t index = idBits.getIndexOfBit(id); - iterBits.clearBit(id); - Estimator estimator; - getEstimator(id, &estimator); - ALOGD(" %d: position (%0.3f, %0.3f), " - "estimator (degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f)", - id, positions[index].x, positions[index].y, - int(estimator.degree), - vectorToString(estimator.xCoeff, estimator.degree + 1).string(), - vectorToString(estimator.yCoeff, estimator.degree + 1).string(), - estimator.confidence); - } -#endif -} - -void VelocityTracker::addMovement(const MotionEvent* event) { - int32_t actionMasked = event->getActionMasked(); - - switch (actionMasked) { - case AMOTION_EVENT_ACTION_DOWN: - case AMOTION_EVENT_ACTION_HOVER_ENTER: - // Clear all pointers on down before adding the new movement. - clear(); - break; - case AMOTION_EVENT_ACTION_POINTER_DOWN: { - // Start a new movement trace for a pointer that just went down. - // We do this on down instead of on up because the client may want to query the - // final velocity for a pointer that just went up. - BitSet32 downIdBits; - downIdBits.markBit(event->getPointerId(event->getActionIndex())); - clearPointers(downIdBits); - break; - } - case AMOTION_EVENT_ACTION_MOVE: - case AMOTION_EVENT_ACTION_HOVER_MOVE: - break; - default: - // Ignore all other actions because they do not convey any new information about - // pointer movement. We also want to preserve the last known velocity of the pointers. - // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position - // of the pointers that went up. ACTION_POINTER_UP does include the new position of - // pointers that remained down but we will also receive an ACTION_MOVE with this - // information if any of them actually moved. Since we don't know how many pointers - // will be going up at once it makes sense to just wait for the following ACTION_MOVE - // before adding the movement. - return; - } - - size_t pointerCount = event->getPointerCount(); - if (pointerCount > MAX_POINTERS) { - pointerCount = MAX_POINTERS; - } - - BitSet32 idBits; - for (size_t i = 0; i < pointerCount; i++) { - idBits.markBit(event->getPointerId(i)); - } - - uint32_t pointerIndex[MAX_POINTERS]; - for (size_t i = 0; i < pointerCount; i++) { - pointerIndex[i] = idBits.getIndexOfBit(event->getPointerId(i)); - } - - nsecs_t eventTime; - Position positions[pointerCount]; - - size_t historySize = event->getHistorySize(); - for (size_t h = 0; h < historySize; h++) { - eventTime = event->getHistoricalEventTime(h); - for (size_t i = 0; i < pointerCount; i++) { - uint32_t index = pointerIndex[i]; - positions[index].x = event->getHistoricalX(i, h); - positions[index].y = event->getHistoricalY(i, h); - } - addMovement(eventTime, idBits, positions); - } - - eventTime = event->getEventTime(); - for (size_t i = 0; i < pointerCount; i++) { - uint32_t index = pointerIndex[i]; - positions[index].x = event->getX(i); - positions[index].y = event->getY(i); - } - addMovement(eventTime, idBits, positions); -} - -bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const { - Estimator estimator; - if (getEstimator(id, &estimator) && estimator.degree >= 1) { - *outVx = estimator.xCoeff[1]; - *outVy = estimator.yCoeff[1]; - return true; - } - *outVx = 0; - *outVy = 0; - return false; -} - -bool VelocityTracker::getEstimator(uint32_t id, Estimator* outEstimator) const { - return mStrategy->getEstimator(id, outEstimator); -} - - -// --- LeastSquaresVelocityTrackerStrategy --- - -const nsecs_t LeastSquaresVelocityTrackerStrategy::HORIZON; -const uint32_t LeastSquaresVelocityTrackerStrategy::HISTORY_SIZE; - -LeastSquaresVelocityTrackerStrategy::LeastSquaresVelocityTrackerStrategy( - uint32_t degree, Weighting weighting) : - mDegree(degree), mWeighting(weighting) { - clear(); -} - -LeastSquaresVelocityTrackerStrategy::~LeastSquaresVelocityTrackerStrategy() { -} - -void LeastSquaresVelocityTrackerStrategy::clear() { - mIndex = 0; - mMovements[0].idBits.clear(); -} - -void LeastSquaresVelocityTrackerStrategy::clearPointers(BitSet32 idBits) { - BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value); - mMovements[mIndex].idBits = remainingIdBits; -} - -void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits, - const VelocityTracker::Position* positions) { - if (++mIndex == HISTORY_SIZE) { - mIndex = 0; - } - - Movement& movement = mMovements[mIndex]; - movement.eventTime = eventTime; - movement.idBits = idBits; - uint32_t count = idBits.count(); - for (uint32_t i = 0; i < count; i++) { - movement.positions[i] = positions[i]; - } -} - -/** - * Solves a linear least squares problem to obtain a N degree polynomial that fits - * the specified input data as nearly as possible. - * - * Returns true if a solution is found, false otherwise. - * - * The input consists of two vectors of data points X and Y with indices 0..m-1 - * along with a weight vector W of the same size. - * - * The output is a vector B with indices 0..n that describes a polynomial - * that fits the data, such the sum of W[i] * W[i] * abs(Y[i] - (B[0] + B[1] X[i] - * + B[2] X[i]^2 ... B[n] X[i]^n)) for all i between 0 and m-1 is minimized. - * - * Accordingly, the weight vector W should be initialized by the caller with the - * reciprocal square root of the variance of the error in each input data point. - * In other words, an ideal choice for W would be W[i] = 1 / var(Y[i]) = 1 / stddev(Y[i]). - * The weights express the relative importance of each data point. If the weights are - * all 1, then the data points are considered to be of equal importance when fitting - * the polynomial. It is a good idea to choose weights that diminish the importance - * of data points that may have higher than usual error margins. - * - * Errors among data points are assumed to be independent. W is represented here - * as a vector although in the literature it is typically taken to be a diagonal matrix. - * - * That is to say, the function that generated the input data can be approximated - * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n. - * - * The coefficient of determination (R^2) is also returned to describe the goodness - * of fit of the model for the given data. It is a value between 0 and 1, where 1 - * indicates perfect correspondence. - * - * This function first expands the X vector to a m by n matrix A such that - * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n, then - * multiplies it by w[i]./ - * - * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q - * and an m by n upper triangular matrix R. Because R is upper triangular (lower - * part is all zeroes), we can simplify the decomposition into an m by n matrix - * Q1 and a n by n matrix R1 such that A = Q1 R1. - * - * Finally we solve the system of linear equations given by R1 B = (Qtranspose W Y) - * to find B. - * - * For efficiency, we lay out A and Q column-wise in memory because we frequently - * operate on the column vectors. Conversely, we lay out R row-wise. - * - * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares - * http://en.wikipedia.org/wiki/Gram-Schmidt - */ -static bool solveLeastSquares(const float* x, const float* y, - const float* w, uint32_t m, uint32_t n, float* outB, float* outDet) { -#if DEBUG_STRATEGY - ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n), - vectorToString(x, m).string(), vectorToString(y, m).string(), - vectorToString(w, m).string()); -#endif - - // Expand the X vector to a matrix A, pre-multiplied by the weights. - float a[n][m]; // column-major order - for (uint32_t h = 0; h < m; h++) { - a[0][h] = w[h]; - for (uint32_t i = 1; i < n; i++) { - a[i][h] = a[i - 1][h] * x[h]; - } - } -#if DEBUG_STRATEGY - ALOGD(" - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string()); -#endif - - // Apply the Gram-Schmidt process to A to obtain its QR decomposition. - float q[n][m]; // orthonormal basis, column-major order - float r[n][n]; // upper triangular matrix, row-major order - for (uint32_t j = 0; j < n; j++) { - for (uint32_t h = 0; h < m; h++) { - q[j][h] = a[j][h]; - } - for (uint32_t i = 0; i < j; i++) { - float dot = vectorDot(&q[j][0], &q[i][0], m); - for (uint32_t h = 0; h < m; h++) { - q[j][h] -= dot * q[i][h]; - } - } - - float norm = vectorNorm(&q[j][0], m); - if (norm < 0.000001f) { - // vectors are linearly dependent or zero so no solution -#if DEBUG_STRATEGY - ALOGD(" - no solution, norm=%f", norm); -#endif - return false; - } - - float invNorm = 1.0f / norm; - for (uint32_t h = 0; h < m; h++) { - q[j][h] *= invNorm; - } - for (uint32_t i = 0; i < n; i++) { - r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m); - } - } -#if DEBUG_STRATEGY - ALOGD(" - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string()); - ALOGD(" - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string()); - - // calculate QR, if we factored A correctly then QR should equal A - float qr[n][m]; - for (uint32_t h = 0; h < m; h++) { - for (uint32_t i = 0; i < n; i++) { - qr[i][h] = 0; - for (uint32_t j = 0; j < n; j++) { - qr[i][h] += q[j][h] * r[j][i]; - } - } - } - ALOGD(" - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string()); -#endif - - // Solve R B = Qt W Y to find B. This is easy because R is upper triangular. - // We just work from bottom-right to top-left calculating B's coefficients. - float wy[m]; - for (uint32_t h = 0; h < m; h++) { - wy[h] = y[h] * w[h]; - } - for (uint32_t i = n; i-- != 0; ) { - outB[i] = vectorDot(&q[i][0], wy, m); - for (uint32_t j = n - 1; j > i; j--) { - outB[i] -= r[i][j] * outB[j]; - } - outB[i] /= r[i][i]; - } -#if DEBUG_STRATEGY - ALOGD(" - b=%s", vectorToString(outB, n).string()); -#endif - - // Calculate the coefficient of determination as 1 - (SSerr / SStot) where - // SSerr is the residual sum of squares (variance of the error), - // and SStot is the total sum of squares (variance of the data) where each - // has been weighted. - float ymean = 0; - for (uint32_t h = 0; h < m; h++) { - ymean += y[h]; - } - ymean /= m; - - float sserr = 0; - float sstot = 0; - for (uint32_t h = 0; h < m; h++) { - float err = y[h] - outB[0]; - float term = 1; - for (uint32_t i = 1; i < n; i++) { - term *= x[h]; - err -= term * outB[i]; - } - sserr += w[h] * w[h] * err * err; - float var = y[h] - ymean; - sstot += w[h] * w[h] * var * var; - } - *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1; -#if DEBUG_STRATEGY - ALOGD(" - sserr=%f", sserr); - ALOGD(" - sstot=%f", sstot); - ALOGD(" - det=%f", *outDet); -#endif - return true; -} - -bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id, - VelocityTracker::Estimator* outEstimator) const { - outEstimator->clear(); - - // Iterate over movement samples in reverse time order and collect samples. - float x[HISTORY_SIZE]; - float y[HISTORY_SIZE]; - float w[HISTORY_SIZE]; - float time[HISTORY_SIZE]; - uint32_t m = 0; - uint32_t index = mIndex; - const Movement& newestMovement = mMovements[mIndex]; - do { - const Movement& movement = mMovements[index]; - if (!movement.idBits.hasBit(id)) { - break; - } - - nsecs_t age = newestMovement.eventTime - movement.eventTime; - if (age > HORIZON) { - break; - } - - const VelocityTracker::Position& position = movement.getPosition(id); - x[m] = position.x; - y[m] = position.y; - w[m] = chooseWeight(index); - time[m] = -age * 0.000000001f; - index = (index == 0 ? HISTORY_SIZE : index) - 1; - } while (++m < HISTORY_SIZE); - - if (m == 0) { - return false; // no data - } - - // Calculate a least squares polynomial fit. - uint32_t degree = mDegree; - if (degree > m - 1) { - degree = m - 1; - } - if (degree >= 1) { - float xdet, ydet; - uint32_t n = degree + 1; - if (solveLeastSquares(time, x, w, m, n, outEstimator->xCoeff, &xdet) - && solveLeastSquares(time, y, w, m, n, outEstimator->yCoeff, &ydet)) { - outEstimator->time = newestMovement.eventTime; - outEstimator->degree = degree; - outEstimator->confidence = xdet * ydet; -#if DEBUG_STRATEGY - ALOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f", - int(outEstimator->degree), - vectorToString(outEstimator->xCoeff, n).string(), - vectorToString(outEstimator->yCoeff, n).string(), - outEstimator->confidence); -#endif - return true; - } - } - - // No velocity data available for this pointer, but we do have its current position. - outEstimator->xCoeff[0] = x[0]; - outEstimator->yCoeff[0] = y[0]; - outEstimator->time = newestMovement.eventTime; - outEstimator->degree = 0; - outEstimator->confidence = 1; - return true; -} - -float LeastSquaresVelocityTrackerStrategy::chooseWeight(uint32_t index) const { - switch (mWeighting) { - case WEIGHTING_DELTA: { - // Weight points based on how much time elapsed between them and the next - // point so that points that "cover" a shorter time span are weighed less. - // delta 0ms: 0.5 - // delta 10ms: 1.0 - if (index == mIndex) { - return 1.0f; - } - uint32_t nextIndex = (index + 1) % HISTORY_SIZE; - float deltaMillis = (mMovements[nextIndex].eventTime- mMovements[index].eventTime) - * 0.000001f; - if (deltaMillis < 0) { - return 0.5f; - } - if (deltaMillis < 10) { - return 0.5f + deltaMillis * 0.05; - } - return 1.0f; - } - - case WEIGHTING_CENTRAL: { - // Weight points based on their age, weighing very recent and very old points less. - // age 0ms: 0.5 - // age 10ms: 1.0 - // age 50ms: 1.0 - // age 60ms: 0.5 - float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime) - * 0.000001f; - if (ageMillis < 0) { - return 0.5f; - } - if (ageMillis < 10) { - return 0.5f + ageMillis * 0.05; - } - if (ageMillis < 50) { - return 1.0f; - } - if (ageMillis < 60) { - return 0.5f + (60 - ageMillis) * 0.05; - } - return 0.5f; - } - - case WEIGHTING_RECENT: { - // Weight points based on their age, weighing older points less. - // age 0ms: 1.0 - // age 50ms: 1.0 - // age 100ms: 0.5 - float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime) - * 0.000001f; - if (ageMillis < 50) { - return 1.0f; - } - if (ageMillis < 100) { - return 0.5f + (100 - ageMillis) * 0.01f; - } - return 0.5f; - } - - case WEIGHTING_NONE: - default: - return 1.0f; - } -} - - -// --- IntegratingVelocityTrackerStrategy --- - -IntegratingVelocityTrackerStrategy::IntegratingVelocityTrackerStrategy(uint32_t degree) : - mDegree(degree) { -} - -IntegratingVelocityTrackerStrategy::~IntegratingVelocityTrackerStrategy() { -} - -void IntegratingVelocityTrackerStrategy::clear() { - mPointerIdBits.clear(); -} - -void IntegratingVelocityTrackerStrategy::clearPointers(BitSet32 idBits) { - mPointerIdBits.value &= ~idBits.value; -} - -void IntegratingVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits, - const VelocityTracker::Position* positions) { - uint32_t index = 0; - for (BitSet32 iterIdBits(idBits); !iterIdBits.isEmpty();) { - uint32_t id = iterIdBits.clearFirstMarkedBit(); - State& state = mPointerState[id]; - const VelocityTracker::Position& position = positions[index++]; - if (mPointerIdBits.hasBit(id)) { - updateState(state, eventTime, position.x, position.y); - } else { - initState(state, eventTime, position.x, position.y); - } - } - - mPointerIdBits = idBits; -} - -bool IntegratingVelocityTrackerStrategy::getEstimator(uint32_t id, - VelocityTracker::Estimator* outEstimator) const { - outEstimator->clear(); - - if (mPointerIdBits.hasBit(id)) { - const State& state = mPointerState[id]; - populateEstimator(state, outEstimator); - return true; - } - - return false; -} - -void IntegratingVelocityTrackerStrategy::initState(State& state, - nsecs_t eventTime, float xpos, float ypos) const { - state.updateTime = eventTime; - state.degree = 0; - - state.xpos = xpos; - state.xvel = 0; - state.xaccel = 0; - state.ypos = ypos; - state.yvel = 0; - state.yaccel = 0; -} - -void IntegratingVelocityTrackerStrategy::updateState(State& state, - nsecs_t eventTime, float xpos, float ypos) const { - const nsecs_t MIN_TIME_DELTA = 2 * NANOS_PER_MS; - const float FILTER_TIME_CONSTANT = 0.010f; // 10 milliseconds - - if (eventTime <= state.updateTime + MIN_TIME_DELTA) { - return; - } - - float dt = (eventTime - state.updateTime) * 0.000000001f; - state.updateTime = eventTime; - - float xvel = (xpos - state.xpos) / dt; - float yvel = (ypos - state.ypos) / dt; - if (state.degree == 0) { - state.xvel = xvel; - state.yvel = yvel; - state.degree = 1; - } else { - float alpha = dt / (FILTER_TIME_CONSTANT + dt); - if (mDegree == 1) { - state.xvel += (xvel - state.xvel) * alpha; - state.yvel += (yvel - state.yvel) * alpha; - } else { - float xaccel = (xvel - state.xvel) / dt; - float yaccel = (yvel - state.yvel) / dt; - if (state.degree == 1) { - state.xaccel = xaccel; - state.yaccel = yaccel; - state.degree = 2; - } else { - state.xaccel += (xaccel - state.xaccel) * alpha; - state.yaccel += (yaccel - state.yaccel) * alpha; - } - state.xvel += (state.xaccel * dt) * alpha; - state.yvel += (state.yaccel * dt) * alpha; - } - } - state.xpos = xpos; - state.ypos = ypos; -} - -void IntegratingVelocityTrackerStrategy::populateEstimator(const State& state, - VelocityTracker::Estimator* outEstimator) const { - outEstimator->time = state.updateTime; - outEstimator->confidence = 1.0f; - outEstimator->degree = state.degree; - outEstimator->xCoeff[0] = state.xpos; - outEstimator->xCoeff[1] = state.xvel; - outEstimator->xCoeff[2] = state.xaccel / 2; - outEstimator->yCoeff[0] = state.ypos; - outEstimator->yCoeff[1] = state.yvel; - outEstimator->yCoeff[2] = state.yaccel / 2; -} - - -// --- LegacyVelocityTrackerStrategy --- - -const nsecs_t LegacyVelocityTrackerStrategy::HORIZON; -const uint32_t LegacyVelocityTrackerStrategy::HISTORY_SIZE; -const nsecs_t LegacyVelocityTrackerStrategy::MIN_DURATION; - -LegacyVelocityTrackerStrategy::LegacyVelocityTrackerStrategy() { - clear(); -} - -LegacyVelocityTrackerStrategy::~LegacyVelocityTrackerStrategy() { -} - -void LegacyVelocityTrackerStrategy::clear() { - mIndex = 0; - mMovements[0].idBits.clear(); -} - -void LegacyVelocityTrackerStrategy::clearPointers(BitSet32 idBits) { - BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value); - mMovements[mIndex].idBits = remainingIdBits; -} - -void LegacyVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits, - const VelocityTracker::Position* positions) { - if (++mIndex == HISTORY_SIZE) { - mIndex = 0; - } - - Movement& movement = mMovements[mIndex]; - movement.eventTime = eventTime; - movement.idBits = idBits; - uint32_t count = idBits.count(); - for (uint32_t i = 0; i < count; i++) { - movement.positions[i] = positions[i]; - } -} - -bool LegacyVelocityTrackerStrategy::getEstimator(uint32_t id, - VelocityTracker::Estimator* outEstimator) const { - outEstimator->clear(); - - const Movement& newestMovement = mMovements[mIndex]; - if (!newestMovement.idBits.hasBit(id)) { - return false; // no data - } - - // Find the oldest sample that contains the pointer and that is not older than HORIZON. - nsecs_t minTime = newestMovement.eventTime - HORIZON; - uint32_t oldestIndex = mIndex; - uint32_t numTouches = 1; - do { - uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1; - const Movement& nextOldestMovement = mMovements[nextOldestIndex]; - if (!nextOldestMovement.idBits.hasBit(id) - || nextOldestMovement.eventTime < minTime) { - break; - } - oldestIndex = nextOldestIndex; - } while (++numTouches < HISTORY_SIZE); - - // Calculate an exponentially weighted moving average of the velocity estimate - // at different points in time measured relative to the oldest sample. - // This is essentially an IIR filter. Newer samples are weighted more heavily - // than older samples. Samples at equal time points are weighted more or less - // equally. - // - // One tricky problem is that the sample data may be poorly conditioned. - // Sometimes samples arrive very close together in time which can cause us to - // overestimate the velocity at that time point. Most samples might be measured - // 16ms apart but some consecutive samples could be only 0.5sm apart because - // the hardware or driver reports them irregularly or in bursts. - float accumVx = 0; - float accumVy = 0; - uint32_t index = oldestIndex; - uint32_t samplesUsed = 0; - const Movement& oldestMovement = mMovements[oldestIndex]; - const VelocityTracker::Position& oldestPosition = oldestMovement.getPosition(id); - nsecs_t lastDuration = 0; - - while (numTouches-- > 1) { - if (++index == HISTORY_SIZE) { - index = 0; - } - const Movement& movement = mMovements[index]; - nsecs_t duration = movement.eventTime - oldestMovement.eventTime; - - // If the duration between samples is small, we may significantly overestimate - // the velocity. Consequently, we impose a minimum duration constraint on the - // samples that we include in the calculation. - if (duration >= MIN_DURATION) { - const VelocityTracker::Position& position = movement.getPosition(id); - float scale = 1000000000.0f / duration; // one over time delta in seconds - float vx = (position.x - oldestPosition.x) * scale; - float vy = (position.y - oldestPosition.y) * scale; - accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration); - accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration); - lastDuration = duration; - samplesUsed += 1; - } - } - - // Report velocity. - const VelocityTracker::Position& newestPosition = newestMovement.getPosition(id); - outEstimator->time = newestMovement.eventTime; - outEstimator->confidence = 1; - outEstimator->xCoeff[0] = newestPosition.x; - outEstimator->yCoeff[0] = newestPosition.y; - if (samplesUsed) { - outEstimator->xCoeff[1] = accumVx; - outEstimator->yCoeff[1] = accumVy; - outEstimator->degree = 1; - } else { - outEstimator->degree = 0; - } - return true; -} - -} // namespace android diff --git a/widget/gonk/libui/VelocityTracker.h b/widget/gonk/libui/VelocityTracker.h deleted file mode 100644 index fd077d438..000000000 --- a/widget/gonk/libui/VelocityTracker.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_VELOCITY_TRACKER_H -#define _ANDROIDFW_VELOCITY_TRACKER_H - -#include "Input.h" -#include <utils/Timers.h> -#include <utils/BitSet.h> - -namespace android { - -class VelocityTrackerStrategy; - -/* - * Calculates the velocity of pointer movements over time. - */ -class VelocityTracker { -public: - struct Position { - float x, y; - }; - - struct Estimator { - static const size_t MAX_DEGREE = 4; - - // Estimator time base. - nsecs_t time; - - // Polynomial coefficients describing motion in X and Y. - float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1]; - - // Polynomial degree (number of coefficients), or zero if no information is - // available. - uint32_t degree; - - // Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit). - float confidence; - - inline void clear() { - time = 0; - degree = 0; - confidence = 0; - for (size_t i = 0; i <= MAX_DEGREE; i++) { - xCoeff[i] = 0; - yCoeff[i] = 0; - } - } - }; - - // Creates a velocity tracker using the specified strategy. - // If strategy is NULL, uses the default strategy for the platform. - VelocityTracker(const char* strategy = NULL); - - ~VelocityTracker(); - - // Resets the velocity tracker state. - void clear(); - - // Resets the velocity tracker state for specific pointers. - // Call this method when some pointers have changed and may be reusing - // an id that was assigned to a different pointer earlier. - void clearPointers(BitSet32 idBits); - - // Adds movement information for a set of pointers. - // The idBits bitfield specifies the pointer ids of the pointers whose positions - // are included in the movement. - // The positions array contains position information for each pointer in order by - // increasing id. Its size should be equal to the number of one bits in idBits. - void addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions); - - // Adds movement information for all pointers in a MotionEvent, including historical samples. - void addMovement(const MotionEvent* event); - - // Gets the velocity of the specified pointer id in position units per second. - // Returns false and sets the velocity components to zero if there is - // insufficient movement information for the pointer. - bool getVelocity(uint32_t id, float* outVx, float* outVy) const; - - // Gets an estimator for the recent movements of the specified pointer id. - // Returns false and clears the estimator if there is no information available - // about the pointer. - bool getEstimator(uint32_t id, Estimator* outEstimator) const; - - // Gets the active pointer id, or -1 if none. - inline int32_t getActivePointerId() const { return mActivePointerId; } - - // Gets a bitset containing all pointer ids from the most recent movement. - inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; } - -private: - static const char* DEFAULT_STRATEGY; - - nsecs_t mLastEventTime; - BitSet32 mCurrentPointerIdBits; - int32_t mActivePointerId; - VelocityTrackerStrategy* mStrategy; - - bool configureStrategy(const char* strategy); - - static VelocityTrackerStrategy* createStrategy(const char* strategy); -}; - - -/* - * Implements a particular velocity tracker algorithm. - */ -class VelocityTrackerStrategy { -protected: - VelocityTrackerStrategy() { } - -public: - virtual ~VelocityTrackerStrategy() { } - - virtual void clear() = 0; - virtual void clearPointers(BitSet32 idBits) = 0; - virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, - const VelocityTracker::Position* positions) = 0; - virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const = 0; -}; - - -/* - * Velocity tracker algorithm based on least-squares linear regression. - */ -class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy { -public: - enum Weighting { - // No weights applied. All data points are equally reliable. - WEIGHTING_NONE, - - // Weight by time delta. Data points clustered together are weighted less. - WEIGHTING_DELTA, - - // Weight such that points within a certain horizon are weighed more than those - // outside of that horizon. - WEIGHTING_CENTRAL, - - // Weight such that points older than a certain amount are weighed less. - WEIGHTING_RECENT, - }; - - // Degree must be no greater than Estimator::MAX_DEGREE. - LeastSquaresVelocityTrackerStrategy(uint32_t degree, Weighting weighting = WEIGHTING_NONE); - virtual ~LeastSquaresVelocityTrackerStrategy(); - - virtual void clear(); - virtual void clearPointers(BitSet32 idBits); - virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, - const VelocityTracker::Position* positions); - virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; - -private: - // Sample horizon. - // We don't use too much history by default since we want to react to quick - // changes in direction. - static const nsecs_t HORIZON = 100 * 1000000; // 100 ms - - // Number of samples to keep. - static const uint32_t HISTORY_SIZE = 20; - - struct Movement { - nsecs_t eventTime; - BitSet32 idBits; - VelocityTracker::Position positions[MAX_POINTERS]; - - inline const VelocityTracker::Position& getPosition(uint32_t id) const { - return positions[idBits.getIndexOfBit(id)]; - } - }; - - float chooseWeight(uint32_t index) const; - - const uint32_t mDegree; - const Weighting mWeighting; - uint32_t mIndex; - Movement mMovements[HISTORY_SIZE]; -}; - - -/* - * Velocity tracker algorithm that uses an IIR filter. - */ -class IntegratingVelocityTrackerStrategy : public VelocityTrackerStrategy { -public: - // Degree must be 1 or 2. - IntegratingVelocityTrackerStrategy(uint32_t degree); - ~IntegratingVelocityTrackerStrategy(); - - virtual void clear(); - virtual void clearPointers(BitSet32 idBits); - virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, - const VelocityTracker::Position* positions); - virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; - -private: - // Current state estimate for a particular pointer. - struct State { - nsecs_t updateTime; - uint32_t degree; - - float xpos, xvel, xaccel; - float ypos, yvel, yaccel; - }; - - const uint32_t mDegree; - BitSet32 mPointerIdBits; - State mPointerState[MAX_POINTER_ID + 1]; - - void initState(State& state, nsecs_t eventTime, float xpos, float ypos) const; - void updateState(State& state, nsecs_t eventTime, float xpos, float ypos) const; - void populateEstimator(const State& state, VelocityTracker::Estimator* outEstimator) const; -}; - - -/* - * Velocity tracker strategy used prior to ICS. - */ -class LegacyVelocityTrackerStrategy : public VelocityTrackerStrategy { -public: - LegacyVelocityTrackerStrategy(); - virtual ~LegacyVelocityTrackerStrategy(); - - virtual void clear(); - virtual void clearPointers(BitSet32 idBits); - virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, - const VelocityTracker::Position* positions); - virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; - -private: - // Oldest sample to consider when calculating the velocity. - static const nsecs_t HORIZON = 200 * 1000000; // 100 ms - - // Number of samples to keep. - static const uint32_t HISTORY_SIZE = 20; - - // The minimum duration between samples when estimating velocity. - static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms - - struct Movement { - nsecs_t eventTime; - BitSet32 idBits; - VelocityTracker::Position positions[MAX_POINTERS]; - - inline const VelocityTracker::Position& getPosition(uint32_t id) const { - return positions[idBits.getIndexOfBit(id)]; - } - }; - - uint32_t mIndex; - Movement mMovements[HISTORY_SIZE]; -}; - -} // namespace android - -#endif // _ANDROIDFW_VELOCITY_TRACKER_H diff --git a/widget/gonk/libui/VirtualKeyMap.cpp b/widget/gonk/libui/VirtualKeyMap.cpp deleted file mode 100644 index 444ab3718..000000000 --- a/widget/gonk/libui/VirtualKeyMap.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "VirtualKeyMap" -#include "cutils_log.h" - -#include <stdlib.h> -#include <string.h> -#include "VirtualKeyMap.h" -#include <utils/Errors.h> -#include "Tokenizer.h" -#include <utils/Timers.h> - -// Enables debug output for the parser. -#define DEBUG_PARSER 0 - -// Enables debug output for parser performance. -#define DEBUG_PARSER_PERFORMANCE 0 - - -namespace android { - -static const char* WHITESPACE = " \t\r"; -static const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:"; - - -// --- VirtualKeyMap --- - -VirtualKeyMap::VirtualKeyMap() { -} - -VirtualKeyMap::~VirtualKeyMap() { -} - -status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) { - *outMap = NULL; - - Tokenizer* tokenizer; - status_t status = Tokenizer::open(filename, &tokenizer); - if (status) { - ALOGE("Error %d opening virtual key map file %s.", status, filename.string()); - } else { - VirtualKeyMap* map = new VirtualKeyMap(); - if (!map) { - ALOGE("Error allocating virtual key map."); - status = NO_MEMORY; - } else { -#if DEBUG_PARSER_PERFORMANCE - nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); -#endif - Parser parser(map, tokenizer); - status = parser.parse(); -#if DEBUG_PARSER_PERFORMANCE - nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; - ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", - tokenizer->getFilename().string(), tokenizer->getLineNumber(), - elapsedTime / 1000000.0); -#endif - if (status) { - delete map; - } else { - *outMap = map; - } - } - delete tokenizer; - } - return status; -} - - -// --- VirtualKeyMap::Parser --- - -VirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) : - mMap(map), mTokenizer(tokenizer) { -} - -VirtualKeyMap::Parser::~Parser() { -} - -status_t VirtualKeyMap::Parser::parse() { - while (!mTokenizer->isEof()) { -#if DEBUG_PARSER - ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); -#endif - - mTokenizer->skipDelimiters(WHITESPACE); - - if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { - // Multiple keys can appear on one line or they can be broken up across multiple lines. - do { - String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); - if (token != "0x01") { - ALOGE("%s: Unknown virtual key type, expected 0x01.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - VirtualKeyDefinition defn; - bool success = parseNextIntField(&defn.scanCode) - && parseNextIntField(&defn.centerX) - && parseNextIntField(&defn.centerY) - && parseNextIntField(&defn.width) - && parseNextIntField(&defn.height); - if (!success) { - ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - -#if DEBUG_PARSER - ALOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, " - "width=%d, height=%d", - defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height); -#endif - mMap->mVirtualKeys.push(defn); - } while (consumeFieldDelimiterAndSkipWhitespace()); - - if (!mTokenizer->isEol()) { - ALOGE("%s: Expected end of line, got '%s'.", - mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); - return BAD_VALUE; - } - } - - mTokenizer->nextLine(); - } - - return NO_ERROR; -} - -bool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() { - mTokenizer->skipDelimiters(WHITESPACE); - if (mTokenizer->peekChar() == ':') { - mTokenizer->nextChar(); - mTokenizer->skipDelimiters(WHITESPACE); - return true; - } - return false; -} - -bool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) { - if (!consumeFieldDelimiterAndSkipWhitespace()) { - return false; - } - - String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); - char* end; - *outValue = strtol(token.string(), &end, 0); - if (token.isEmpty() || *end != '\0') { - ALOGE("Expected an integer, got '%s'.", token.string()); - return false; - } - return true; -} - -} // namespace android diff --git a/widget/gonk/libui/VirtualKeyMap.h b/widget/gonk/libui/VirtualKeyMap.h deleted file mode 100644 index 79d61a536..000000000 --- a/widget/gonk/libui/VirtualKeyMap.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROIDFW_VIRTUAL_KEY_MAP_H -#define _ANDROIDFW_VIRTUAL_KEY_MAP_H - -#include <stdint.h> - -#include "Input.h" -#include <utils/Errors.h> -#include <utils/KeyedVector.h> -#include "Tokenizer.h" -#include <utils/String8.h> -#include <utils/Unicode.h> - -namespace android { - -/* Describes a virtual key. */ -struct VirtualKeyDefinition { - int32_t scanCode; - - // configured position data, specified in display coords - int32_t centerX; - int32_t centerY; - int32_t width; - int32_t height; -}; - - -/** - * Describes a collection of virtual keys on a touch screen in terms of - * virtual scan codes and hit rectangles. - * - * This object is immutable after it has been loaded. - */ -class VirtualKeyMap { -public: - ~VirtualKeyMap(); - - static status_t load(const String8& filename, VirtualKeyMap** outMap); - - inline const Vector<VirtualKeyDefinition>& getVirtualKeys() const { - return mVirtualKeys; - } - -private: - class Parser { - VirtualKeyMap* mMap; - Tokenizer* mTokenizer; - - public: - Parser(VirtualKeyMap* map, Tokenizer* tokenizer); - ~Parser(); - status_t parse(); - - private: - bool consumeFieldDelimiterAndSkipWhitespace(); - bool parseNextIntField(int32_t* outValue); - }; - - Vector<VirtualKeyDefinition> mVirtualKeys; - - VirtualKeyMap(); -}; - -} // namespace android - -#endif // _ANDROIDFW_KEY_CHARACTER_MAP_H diff --git a/widget/gonk/libui/android_input.h b/widget/gonk/libui/android_input.h deleted file mode 100644 index 00e81b28d..000000000 --- a/widget/gonk/libui/android_input.h +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROID_INPUT_H -#define _ANDROID_INPUT_H - -/****************************************************************** - * - * IMPORTANT NOTICE: - * - * This file is part of Android's set of stable system headers - * exposed by the Android NDK (Native Development Kit). - * - * Third-party source AND binary code relies on the definitions - * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES. - * - * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES) - * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS - * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY - * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES - */ - -/* - * Structures and functions to receive and process input events in - * native code. - * - * NOTE: These functions MUST be implemented by /system/lib/libui.so - */ - -#include <stdint.h> -#include <sys/types.h> -#include "android_keycodes.h" -#include <android/looper.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Key states (may be returned by queries about the current state of a - * particular key code, scan code or switch). - */ -enum { - /* The key state is unknown or the requested key itself is not supported. */ - AKEY_STATE_UNKNOWN = -1, - - /* The key is up. */ - AKEY_STATE_UP = 0, - - /* The key is down. */ - AKEY_STATE_DOWN = 1, - - /* The key is down but is a virtual key press that is being emulated by the system. */ - AKEY_STATE_VIRTUAL = 2 -}; - -/* - * Meta key / modifer state. - */ -enum { - /* No meta keys are pressed. */ - AMETA_NONE = 0, - - /* This mask is used to check whether one of the ALT meta keys is pressed. */ - AMETA_ALT_ON = 0x02, - - /* This mask is used to check whether the left ALT meta key is pressed. */ - AMETA_ALT_LEFT_ON = 0x10, - - /* This mask is used to check whether the right ALT meta key is pressed. */ - AMETA_ALT_RIGHT_ON = 0x20, - - /* This mask is used to check whether one of the SHIFT meta keys is pressed. */ - AMETA_SHIFT_ON = 0x01, - - /* This mask is used to check whether the left SHIFT meta key is pressed. */ - AMETA_SHIFT_LEFT_ON = 0x40, - - /* This mask is used to check whether the right SHIFT meta key is pressed. */ - AMETA_SHIFT_RIGHT_ON = 0x80, - - /* This mask is used to check whether the SYM meta key is pressed. */ - AMETA_SYM_ON = 0x04, - - /* This mask is used to check whether the FUNCTION meta key is pressed. */ - AMETA_FUNCTION_ON = 0x08, - - /* This mask is used to check whether one of the CTRL meta keys is pressed. */ - AMETA_CTRL_ON = 0x1000, - - /* This mask is used to check whether the left CTRL meta key is pressed. */ - AMETA_CTRL_LEFT_ON = 0x2000, - - /* This mask is used to check whether the right CTRL meta key is pressed. */ - AMETA_CTRL_RIGHT_ON = 0x4000, - - /* This mask is used to check whether one of the META meta keys is pressed. */ - AMETA_META_ON = 0x10000, - - /* This mask is used to check whether the left META meta key is pressed. */ - AMETA_META_LEFT_ON = 0x20000, - - /* This mask is used to check whether the right META meta key is pressed. */ - AMETA_META_RIGHT_ON = 0x40000, - - /* This mask is used to check whether the CAPS LOCK meta key is on. */ - AMETA_CAPS_LOCK_ON = 0x100000, - - /* This mask is used to check whether the NUM LOCK meta key is on. */ - AMETA_NUM_LOCK_ON = 0x200000, - - /* This mask is used to check whether the SCROLL LOCK meta key is on. */ - AMETA_SCROLL_LOCK_ON = 0x400000, -}; - -/* - * Input events. - * - * Input events are opaque structures. Use the provided accessors functions to - * read their properties. - */ -struct AInputEvent; -typedef struct AInputEvent AInputEvent; - -/* - * Input event types. - */ -enum { - /* Indicates that the input event is a key event. */ - AINPUT_EVENT_TYPE_KEY = 1, - - /* Indicates that the input event is a motion event. */ - AINPUT_EVENT_TYPE_MOTION = 2 -}; - -/* - * Key event actions. - */ -enum { - /* The key has been pressed down. */ - AKEY_EVENT_ACTION_DOWN = 0, - - /* The key has been released. */ - AKEY_EVENT_ACTION_UP = 1, - - /* Multiple duplicate key events have occurred in a row, or a complex string is - * being delivered. The repeat_count property of the key event contains the number - * of times the given key code should be executed. - */ - AKEY_EVENT_ACTION_MULTIPLE = 2 -}; - -/* - * Key event flags. - */ -enum { - /* This mask is set if the device woke because of this key event. */ - AKEY_EVENT_FLAG_WOKE_HERE = 0x1, - - /* This mask is set if the key event was generated by a software keyboard. */ - AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2, - - /* This mask is set if we don't want the key event to cause us to leave touch mode. */ - AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4, - - /* This mask is set if an event was known to come from a trusted part - * of the system. That is, the event is known to come from the user, - * and could not have been spoofed by a third party component. */ - AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8, - - /* This mask is used for compatibility, to identify enter keys that are - * coming from an IME whose enter key has been auto-labelled "next" or - * "done". This allows TextView to dispatch these as normal enter keys - * for old applications, but still do the appropriate action when - * receiving them. */ - AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10, - - /* When associated with up key events, this indicates that the key press - * has been canceled. Typically this is used with virtual touch screen - * keys, where the user can slide from the virtual key area on to the - * display: in that case, the application will receive a canceled up - * event and should not perform the action normally associated with the - * key. Note that for this to work, the application can not perform an - * action for a key until it receives an up or the long press timeout has - * expired. */ - AKEY_EVENT_FLAG_CANCELED = 0x20, - - /* This key event was generated by a virtual (on-screen) hard key area. - * Typically this is an area of the touchscreen, outside of the regular - * display, dedicated to "hardware" buttons. */ - AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40, - - /* This flag is set for the first key repeat that occurs after the - * long press timeout. */ - AKEY_EVENT_FLAG_LONG_PRESS = 0x80, - - /* Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long - * press action was executed while it was down. */ - AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100, - - /* Set for AKEY_EVENT_ACTION_UP when this event's key code is still being - * tracked from its initial down. That is, somebody requested that tracking - * started on the key down and a long press has not caused - * the tracking to be canceled. */ - AKEY_EVENT_FLAG_TRACKING = 0x200, - - /* Set when a key event has been synthesized to implement default behavior - * for an event that the application did not handle. - * Fallback key events are generated by unhandled trackball motions - * (to emulate a directional keypad) and by certain unhandled key presses - * that are declared in the key map (such as special function numeric keypad - * keys when numlock is off). */ - AKEY_EVENT_FLAG_FALLBACK = 0x400, -}; - -/* - * Motion event actions. - */ - -/* Bit shift for the action bits holding the pointer index as - * defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK. - */ -#define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8 - -enum { - /* Bit mask of the parts of the action code that are the action itself. - */ - AMOTION_EVENT_ACTION_MASK = 0xff, - - /* Bits in the action code that represent a pointer index, used with - * AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting - * down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer - * index where the data for the pointer going up or down can be found. - */ - AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00, - - /* A pressed gesture has started, the motion contains the initial starting location. - */ - AMOTION_EVENT_ACTION_DOWN = 0, - - /* A pressed gesture has finished, the motion contains the final release location - * as well as any intermediate points since the last down or move event. - */ - AMOTION_EVENT_ACTION_UP = 1, - - /* A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and - * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as - * any intermediate points since the last down or move event. - */ - AMOTION_EVENT_ACTION_MOVE = 2, - - /* The current gesture has been aborted. - * You will not receive any more points in it. You should treat this as - * an up event, but not perform any action that you normally would. - */ - AMOTION_EVENT_ACTION_CANCEL = 3, - - /* A movement has happened outside of the normal bounds of the UI element. - * This does not provide a full gesture, but only the initial location of the movement/touch. - */ - AMOTION_EVENT_ACTION_OUTSIDE = 4, - - /* A non-primary pointer has gone down. - * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed. - */ - AMOTION_EVENT_ACTION_POINTER_DOWN = 5, - - /* A non-primary pointer has gone up. - * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed. - */ - AMOTION_EVENT_ACTION_POINTER_UP = 6, - - /* A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE). - * The motion contains the most recent point, as well as any intermediate points since - * the last hover move event. - */ - AMOTION_EVENT_ACTION_HOVER_MOVE = 7, - - /* The motion event contains relative vertical and/or horizontal scroll offsets. - * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL - * and AMOTION_EVENT_AXIS_HSCROLL. - * The pointer may or may not be down when this event is dispatched. - * This action is always delivered to the winder under the pointer, which - * may not be the window currently touched. - */ - AMOTION_EVENT_ACTION_SCROLL = 8, - - /* The pointer is not down but has entered the boundaries of a window or view. - */ - AMOTION_EVENT_ACTION_HOVER_ENTER = 9, - - /* The pointer is not down but has exited the boundaries of a window or view. - */ - AMOTION_EVENT_ACTION_HOVER_EXIT = 10, -}; - -/* - * Motion event flags. - */ -enum { - /* This flag indicates that the window that received this motion event is partly - * or wholly obscured by another visible window above it. This flag is set to true - * even if the event did not directly pass through the obscured area. - * A security sensitive application can check this flag to identify situations in which - * a malicious application may have covered up part of its content for the purpose - * of misleading the user or hijacking touches. An appropriate response might be - * to drop the suspect touches or to take additional precautions to confirm the user's - * actual intent. - */ - AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1, -}; - -/* - * Motion event edge touch flags. - */ -enum { - /* No edges intersected */ - AMOTION_EVENT_EDGE_FLAG_NONE = 0, - - /* Flag indicating the motion event intersected the top edge of the screen. */ - AMOTION_EVENT_EDGE_FLAG_TOP = 0x01, - - /* Flag indicating the motion event intersected the bottom edge of the screen. */ - AMOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02, - - /* Flag indicating the motion event intersected the left edge of the screen. */ - AMOTION_EVENT_EDGE_FLAG_LEFT = 0x04, - - /* Flag indicating the motion event intersected the right edge of the screen. */ - AMOTION_EVENT_EDGE_FLAG_RIGHT = 0x08 -}; - -/* - * Constants that identify each individual axis of a motion event. - * Refer to the documentation on the MotionEvent class for descriptions of each axis. - */ -enum { - AMOTION_EVENT_AXIS_X = 0, - AMOTION_EVENT_AXIS_Y = 1, - AMOTION_EVENT_AXIS_PRESSURE = 2, - AMOTION_EVENT_AXIS_SIZE = 3, - AMOTION_EVENT_AXIS_TOUCH_MAJOR = 4, - AMOTION_EVENT_AXIS_TOUCH_MINOR = 5, - AMOTION_EVENT_AXIS_TOOL_MAJOR = 6, - AMOTION_EVENT_AXIS_TOOL_MINOR = 7, - AMOTION_EVENT_AXIS_ORIENTATION = 8, - AMOTION_EVENT_AXIS_VSCROLL = 9, - AMOTION_EVENT_AXIS_HSCROLL = 10, - AMOTION_EVENT_AXIS_Z = 11, - AMOTION_EVENT_AXIS_RX = 12, - AMOTION_EVENT_AXIS_RY = 13, - AMOTION_EVENT_AXIS_RZ = 14, - AMOTION_EVENT_AXIS_HAT_X = 15, - AMOTION_EVENT_AXIS_HAT_Y = 16, - AMOTION_EVENT_AXIS_LTRIGGER = 17, - AMOTION_EVENT_AXIS_RTRIGGER = 18, - AMOTION_EVENT_AXIS_THROTTLE = 19, - AMOTION_EVENT_AXIS_RUDDER = 20, - AMOTION_EVENT_AXIS_WHEEL = 21, - AMOTION_EVENT_AXIS_GAS = 22, - AMOTION_EVENT_AXIS_BRAKE = 23, - AMOTION_EVENT_AXIS_DISTANCE = 24, - AMOTION_EVENT_AXIS_TILT = 25, - AMOTION_EVENT_AXIS_GENERIC_1 = 32, - AMOTION_EVENT_AXIS_GENERIC_2 = 33, - AMOTION_EVENT_AXIS_GENERIC_3 = 34, - AMOTION_EVENT_AXIS_GENERIC_4 = 35, - AMOTION_EVENT_AXIS_GENERIC_5 = 36, - AMOTION_EVENT_AXIS_GENERIC_6 = 37, - AMOTION_EVENT_AXIS_GENERIC_7 = 38, - AMOTION_EVENT_AXIS_GENERIC_8 = 39, - AMOTION_EVENT_AXIS_GENERIC_9 = 40, - AMOTION_EVENT_AXIS_GENERIC_10 = 41, - AMOTION_EVENT_AXIS_GENERIC_11 = 42, - AMOTION_EVENT_AXIS_GENERIC_12 = 43, - AMOTION_EVENT_AXIS_GENERIC_13 = 44, - AMOTION_EVENT_AXIS_GENERIC_14 = 45, - AMOTION_EVENT_AXIS_GENERIC_15 = 46, - AMOTION_EVENT_AXIS_GENERIC_16 = 47, - - // NOTE: If you add a new axis here you must also add it to several other files. - // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list. -}; - -/* - * Constants that identify buttons that are associated with motion events. - * Refer to the documentation on the MotionEvent class for descriptions of each button. - */ -enum { - AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0, - AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1, - AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2, - AMOTION_EVENT_BUTTON_BACK = 1 << 3, - AMOTION_EVENT_BUTTON_FORWARD = 1 << 4, -}; - -/* - * Constants that identify tool types. - * Refer to the documentation on the MotionEvent class for descriptions of each tool type. - */ -enum { - AMOTION_EVENT_TOOL_TYPE_UNKNOWN = 0, - AMOTION_EVENT_TOOL_TYPE_FINGER = 1, - AMOTION_EVENT_TOOL_TYPE_STYLUS = 2, - AMOTION_EVENT_TOOL_TYPE_MOUSE = 3, - AMOTION_EVENT_TOOL_TYPE_ERASER = 4, -}; - -/* - * Input sources. - * - * Refer to the documentation on android.view.InputDevice for more details about input sources - * and their correct interpretation. - */ -enum { - AINPUT_SOURCE_CLASS_MASK = 0x000000ff, - - AINPUT_SOURCE_CLASS_NONE = 0x00000000, - AINPUT_SOURCE_CLASS_BUTTON = 0x00000001, - AINPUT_SOURCE_CLASS_POINTER = 0x00000002, - AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004, - AINPUT_SOURCE_CLASS_POSITION = 0x00000008, - AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010, -}; - -enum { - AINPUT_SOURCE_UNKNOWN = 0x00000000, - - AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON, - AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON, - AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON, - AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER, - AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER, - AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER, - AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION, - AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION, - AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE, - AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK, - - AINPUT_SOURCE_ANY = 0xffffff00, -}; - -/* - * Keyboard types. - * - * Refer to the documentation on android.view.InputDevice for more details. - */ -enum { - AINPUT_KEYBOARD_TYPE_NONE = 0, - AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC = 1, - AINPUT_KEYBOARD_TYPE_ALPHABETIC = 2, -}; - -/* - * Constants used to retrieve information about the range of motion for a particular - * coordinate of a motion event. - * - * Refer to the documentation on android.view.InputDevice for more details about input sources - * and their correct interpretation. - * - * DEPRECATION NOTICE: These constants are deprecated. Use AMOTION_EVENT_AXIS_* constants instead. - */ -enum { - AINPUT_MOTION_RANGE_X = AMOTION_EVENT_AXIS_X, - AINPUT_MOTION_RANGE_Y = AMOTION_EVENT_AXIS_Y, - AINPUT_MOTION_RANGE_PRESSURE = AMOTION_EVENT_AXIS_PRESSURE, - AINPUT_MOTION_RANGE_SIZE = AMOTION_EVENT_AXIS_SIZE, - AINPUT_MOTION_RANGE_TOUCH_MAJOR = AMOTION_EVENT_AXIS_TOUCH_MAJOR, - AINPUT_MOTION_RANGE_TOUCH_MINOR = AMOTION_EVENT_AXIS_TOUCH_MINOR, - AINPUT_MOTION_RANGE_TOOL_MAJOR = AMOTION_EVENT_AXIS_TOOL_MAJOR, - AINPUT_MOTION_RANGE_TOOL_MINOR = AMOTION_EVENT_AXIS_TOOL_MINOR, - AINPUT_MOTION_RANGE_ORIENTATION = AMOTION_EVENT_AXIS_ORIENTATION, -} __attribute__ ((deprecated)); - - -/* - * Input event accessors. - * - * Note that most functions can only be used on input events that are of a given type. - * Calling these functions on input events of other types will yield undefined behavior. - */ - -/*** Accessors for all input events. ***/ - -/* Get the input event type. */ -int32_t AInputEvent_getType(const AInputEvent* event); - -/* Get the id for the device that an input event came from. - * - * Input events can be generated by multiple different input devices. - * Use the input device id to obtain information about the input - * device that was responsible for generating a particular event. - * - * An input device id of 0 indicates that the event didn't come from a physical device; - * other numbers are arbitrary and you shouldn't depend on the values. - * Use the provided input device query API to obtain information about input devices. - */ -int32_t AInputEvent_getDeviceId(const AInputEvent* event); - -/* Get the input event source. */ -int32_t AInputEvent_getSource(const AInputEvent* event); - -/*** Accessors for key events only. ***/ - -/* Get the key event action. */ -int32_t AKeyEvent_getAction(const AInputEvent* key_event); - -/* Get the key event flags. */ -int32_t AKeyEvent_getFlags(const AInputEvent* key_event); - -/* Get the key code of the key event. - * This is the physical key that was pressed, not the Unicode character. */ -int32_t AKeyEvent_getKeyCode(const AInputEvent* key_event); - -/* Get the hardware key id of this key event. - * These values are not reliable and vary from device to device. */ -int32_t AKeyEvent_getScanCode(const AInputEvent* key_event); - -/* Get the meta key state. */ -int32_t AKeyEvent_getMetaState(const AInputEvent* key_event); - -/* Get the repeat count of the event. - * For both key up an key down events, this is the number of times the key has - * repeated with the first down starting at 0 and counting up from there. For - * multiple key events, this is the number of down/up pairs that have occurred. */ -int32_t AKeyEvent_getRepeatCount(const AInputEvent* key_event); - -/* Get the time of the most recent key down event, in the - * java.lang.System.nanoTime() time base. If this is a down event, - * this will be the same as eventTime. - * Note that when chording keys, this value is the down time of the most recently - * pressed key, which may not be the same physical key of this event. */ -int64_t AKeyEvent_getDownTime(const AInputEvent* key_event); - -/* Get the time this event occurred, in the - * java.lang.System.nanoTime() time base. */ -int64_t AKeyEvent_getEventTime(const AInputEvent* key_event); - -/*** Accessors for motion events only. ***/ - -/* Get the combined motion event action code and pointer index. */ -int32_t AMotionEvent_getAction(const AInputEvent* motion_event); - -/* Get the motion event flags. */ -int32_t AMotionEvent_getFlags(const AInputEvent* motion_event); - -/* Get the state of any meta / modifier keys that were in effect when the - * event was generated. */ -int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event); - -/* Get the button state of all buttons that are pressed. */ -int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event); - -/* Get a bitfield indicating which edges, if any, were touched by this motion event. - * For touch events, clients can use this to determine if the user's finger was - * touching the edge of the display. */ -int32_t AMotionEvent_getEdgeFlags(const AInputEvent* motion_event); - -/* Get the time when the user originally pressed down to start a stream of - * position events, in the java.lang.System.nanoTime() time base. */ -int64_t AMotionEvent_getDownTime(const AInputEvent* motion_event); - -/* Get the time when this specific event was generated, - * in the java.lang.System.nanoTime() time base. */ -int64_t AMotionEvent_getEventTime(const AInputEvent* motion_event); - -/* Get the X coordinate offset. - * For touch events on the screen, this is the delta that was added to the raw - * screen coordinates to adjust for the absolute position of the containing windows - * and views. */ -float AMotionEvent_getXOffset(const AInputEvent* motion_event); - -/* Get the precision of the Y coordinates being reported. - * For touch events on the screen, this is the delta that was added to the raw - * screen coordinates to adjust for the absolute position of the containing windows - * and views. */ -float AMotionEvent_getYOffset(const AInputEvent* motion_event); - -/* Get the precision of the X coordinates being reported. - * You can multiply this number with an X coordinate sample to find the - * actual hardware value of the X coordinate. */ -float AMotionEvent_getXPrecision(const AInputEvent* motion_event); - -/* Get the precision of the Y coordinates being reported. - * You can multiply this number with a Y coordinate sample to find the - * actual hardware value of the Y coordinate. */ -float AMotionEvent_getYPrecision(const AInputEvent* motion_event); - -/* Get the number of pointers of data contained in this event. - * Always >= 1. */ -size_t AMotionEvent_getPointerCount(const AInputEvent* motion_event); - -/* Get the pointer identifier associated with a particular pointer - * data index in this event. The identifier tells you the actual pointer - * number associated with the data, accounting for individual pointers - * going up and down since the start of the current gesture. */ -int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the tool type of a pointer for the given pointer index. - * The tool type indicates the type of tool used to make contact such as a - * finger or stylus, if known. */ -int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the original raw X coordinate of this event. - * For touch events on the screen, this is the original location of the event - * on the screen, before it had been adjusted for the containing window - * and views. */ -float AMotionEvent_getRawX(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the original raw X coordinate of this event. - * For touch events on the screen, this is the original location of the event - * on the screen, before it had been adjusted for the containing window - * and views. */ -float AMotionEvent_getRawY(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current X coordinate of this event for the given pointer index. - * Whole numbers are pixels; the value may have a fraction for input devices - * that are sub-pixel precise. */ -float AMotionEvent_getX(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current Y coordinate of this event for the given pointer index. - * Whole numbers are pixels; the value may have a fraction for input devices - * that are sub-pixel precise. */ -float AMotionEvent_getY(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current pressure of this event for the given pointer index. - * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), - * although values higher than 1 may be generated depending on the calibration of - * the input device. */ -float AMotionEvent_getPressure(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current scaled value of the approximate size for the given pointer index. - * This represents some approximation of the area of the screen being - * pressed; the actual value in pixels corresponding to the - * touch is normalized with the device specific range of values - * and scaled to a value between 0 and 1. The value of size can be used to - * determine fat touch events. */ -float AMotionEvent_getSize(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current length of the major axis of an ellipse that describes the touch area - * at the point of contact for the given pointer index. */ -float AMotionEvent_getTouchMajor(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current length of the minor axis of an ellipse that describes the touch area - * at the point of contact for the given pointer index. */ -float AMotionEvent_getTouchMinor(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current length of the major axis of an ellipse that describes the size - * of the approaching tool for the given pointer index. - * The tool area represents the estimated size of the finger or pen that is - * touching the device independent of its actual touch area at the point of contact. */ -float AMotionEvent_getToolMajor(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current length of the minor axis of an ellipse that describes the size - * of the approaching tool for the given pointer index. - * The tool area represents the estimated size of the finger or pen that is - * touching the device independent of its actual touch area at the point of contact. */ -float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the current orientation of the touch area and tool area in radians clockwise from - * vertical for the given pointer index. - * An angle of 0 degrees indicates that the major axis of contact is oriented - * upwards, is perfectly circular or is of unknown orientation. A positive angle - * indicates that the major axis of contact is oriented to the right. A negative angle - * indicates that the major axis of contact is oriented to the left. - * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians - * (finger pointing fully right). */ -float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index); - -/* Get the value of the request axis for the given pointer index. */ -float AMotionEvent_getAxisValue(const AInputEvent* motion_event, - int32_t axis, size_t pointer_index); - -/* Get the number of historical points in this event. These are movements that - * have occurred between this event and the previous event. This only applies - * to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0. - * Historical samples are indexed from oldest to newest. */ -size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event); - -/* Get the time that a historical movement occurred between this event and - * the previous event, in the java.lang.System.nanoTime() time base. */ -int64_t AMotionEvent_getHistoricalEventTime(AInputEvent* motion_event, - size_t history_index); - -/* Get the historical raw X coordinate of this event for the given pointer index that - * occurred between this event and the previous motion event. - * For touch events on the screen, this is the original location of the event - * on the screen, before it had been adjusted for the containing window - * and views. - * Whole numbers are pixels; the value may have a fraction for input devices - * that are sub-pixel precise. */ -float AMotionEvent_getHistoricalRawX(const AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical raw Y coordinate of this event for the given pointer index that - * occurred between this event and the previous motion event. - * For touch events on the screen, this is the original location of the event - * on the screen, before it had been adjusted for the containing window - * and views. - * Whole numbers are pixels; the value may have a fraction for input devices - * that are sub-pixel precise. */ -float AMotionEvent_getHistoricalRawY(const AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical X coordinate of this event for the given pointer index that - * occurred between this event and the previous motion event. - * Whole numbers are pixels; the value may have a fraction for input devices - * that are sub-pixel precise. */ -float AMotionEvent_getHistoricalX(AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical Y coordinate of this event for the given pointer index that - * occurred between this event and the previous motion event. - * Whole numbers are pixels; the value may have a fraction for input devices - * that are sub-pixel precise. */ -float AMotionEvent_getHistoricalY(AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical pressure of this event for the given pointer index that - * occurred between this event and the previous motion event. - * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), - * although values higher than 1 may be generated depending on the calibration of - * the input device. */ -float AMotionEvent_getHistoricalPressure(AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the current scaled value of the approximate size for the given pointer index that - * occurred between this event and the previous motion event. - * This represents some approximation of the area of the screen being - * pressed; the actual value in pixels corresponding to the - * touch is normalized with the device specific range of values - * and scaled to a value between 0 and 1. The value of size can be used to - * determine fat touch events. */ -float AMotionEvent_getHistoricalSize(AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical length of the major axis of an ellipse that describes the touch area - * at the point of contact for the given pointer index that - * occurred between this event and the previous motion event. */ -float AMotionEvent_getHistoricalTouchMajor(const AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical length of the minor axis of an ellipse that describes the touch area - * at the point of contact for the given pointer index that - * occurred between this event and the previous motion event. */ -float AMotionEvent_getHistoricalTouchMinor(const AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical length of the major axis of an ellipse that describes the size - * of the approaching tool for the given pointer index that - * occurred between this event and the previous motion event. - * The tool area represents the estimated size of the finger or pen that is - * touching the device independent of its actual touch area at the point of contact. */ -float AMotionEvent_getHistoricalToolMajor(const AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical length of the minor axis of an ellipse that describes the size - * of the approaching tool for the given pointer index that - * occurred between this event and the previous motion event. - * The tool area represents the estimated size of the finger or pen that is - * touching the device independent of its actual touch area at the point of contact. */ -float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical orientation of the touch area and tool area in radians clockwise from - * vertical for the given pointer index that - * occurred between this event and the previous motion event. - * An angle of 0 degrees indicates that the major axis of contact is oriented - * upwards, is perfectly circular or is of unknown orientation. A positive angle - * indicates that the major axis of contact is oriented to the right. A negative angle - * indicates that the major axis of contact is oriented to the left. - * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians - * (finger pointing fully right). */ -float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index, - size_t history_index); - -/* Get the historical value of the request axis for the given pointer index - * that occurred between this event and the previous motion event. */ -float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event, - int32_t axis, size_t pointer_index, size_t history_index); - - -/* - * Input queue - * - * An input queue is the facility through which you retrieve input - * events. - */ -struct AInputQueue; -typedef struct AInputQueue AInputQueue; - -/* - * Add this input queue to a looper for processing. See - * ALooper_addFd() for information on the ident, callback, and data params. - */ -void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper, - int ident, ALooper_callbackFunc callback, void* data); - -/* - * Remove the input queue from the looper it is currently attached to. - */ -void AInputQueue_detachLooper(AInputQueue* queue); - -/* - * Returns true if there are one or more events available in the - * input queue. Returns 1 if the queue has events; 0 if - * it does not have events; and a negative value if there is an error. - */ -int32_t AInputQueue_hasEvents(AInputQueue* queue); - -/* - * Returns the next available event from the queue. Returns a negative - * value if no events are available or an error has occurred. - */ -int32_t AInputQueue_getEvent(AInputQueue* queue, AInputEvent** outEvent); - -/* - * Sends the key for standard pre-dispatching -- that is, possibly deliver - * it to the current IME to be consumed before the app. Returns 0 if it - * was not pre-dispatched, meaning you can process it right now. If non-zero - * is returned, you must abandon the current event processing and allow the - * event to appear again in the event queue (if it does not get consumed during - * pre-dispatching). - */ -int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event); - -/* - * Report that dispatching has finished with the given event. - * This must be called after receiving an event with AInputQueue_get_event(). - */ -void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled); - -#ifdef __cplusplus -} -#endif - -#endif // _ANDROID_INPUT_H diff --git a/widget/gonk/libui/android_keycodes.h b/widget/gonk/libui/android_keycodes.h deleted file mode 100644 index 9e63d1d01..000000000 --- a/widget/gonk/libui/android_keycodes.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROID_KEYCODES_H -#define _ANDROID_KEYCODES_H - -/****************************************************************** - * - * IMPORTANT NOTICE: - * - * This file is part of Android's set of stable system headers - * exposed by the Android NDK (Native Development Kit). - * - * Third-party source AND binary code relies on the definitions - * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES. - * - * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES) - * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS - * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY - * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES - */ - -#include <sys/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Key codes. - */ -enum { - AKEYCODE_UNKNOWN = 0, - AKEYCODE_SOFT_LEFT = 1, - AKEYCODE_SOFT_RIGHT = 2, - AKEYCODE_HOME = 3, - AKEYCODE_BACK = 4, - AKEYCODE_CALL = 5, - AKEYCODE_ENDCALL = 6, - AKEYCODE_0 = 7, - AKEYCODE_1 = 8, - AKEYCODE_2 = 9, - AKEYCODE_3 = 10, - AKEYCODE_4 = 11, - AKEYCODE_5 = 12, - AKEYCODE_6 = 13, - AKEYCODE_7 = 14, - AKEYCODE_8 = 15, - AKEYCODE_9 = 16, - AKEYCODE_STAR = 17, - AKEYCODE_POUND = 18, - AKEYCODE_DPAD_UP = 19, - AKEYCODE_DPAD_DOWN = 20, - AKEYCODE_DPAD_LEFT = 21, - AKEYCODE_DPAD_RIGHT = 22, - AKEYCODE_DPAD_CENTER = 23, - AKEYCODE_VOLUME_UP = 24, - AKEYCODE_VOLUME_DOWN = 25, - AKEYCODE_POWER = 26, - AKEYCODE_CAMERA = 27, - AKEYCODE_CLEAR = 28, - AKEYCODE_A = 29, - AKEYCODE_B = 30, - AKEYCODE_C = 31, - AKEYCODE_D = 32, - AKEYCODE_E = 33, - AKEYCODE_F = 34, - AKEYCODE_G = 35, - AKEYCODE_H = 36, - AKEYCODE_I = 37, - AKEYCODE_J = 38, - AKEYCODE_K = 39, - AKEYCODE_L = 40, - AKEYCODE_M = 41, - AKEYCODE_N = 42, - AKEYCODE_O = 43, - AKEYCODE_P = 44, - AKEYCODE_Q = 45, - AKEYCODE_R = 46, - AKEYCODE_S = 47, - AKEYCODE_T = 48, - AKEYCODE_U = 49, - AKEYCODE_V = 50, - AKEYCODE_W = 51, - AKEYCODE_X = 52, - AKEYCODE_Y = 53, - AKEYCODE_Z = 54, - AKEYCODE_COMMA = 55, - AKEYCODE_PERIOD = 56, - AKEYCODE_ALT_LEFT = 57, - AKEYCODE_ALT_RIGHT = 58, - AKEYCODE_SHIFT_LEFT = 59, - AKEYCODE_SHIFT_RIGHT = 60, - AKEYCODE_TAB = 61, - AKEYCODE_SPACE = 62, - AKEYCODE_SYM = 63, - AKEYCODE_EXPLORER = 64, - AKEYCODE_ENVELOPE = 65, - AKEYCODE_ENTER = 66, - AKEYCODE_DEL = 67, - AKEYCODE_GRAVE = 68, - AKEYCODE_MINUS = 69, - AKEYCODE_EQUALS = 70, - AKEYCODE_LEFT_BRACKET = 71, - AKEYCODE_RIGHT_BRACKET = 72, - AKEYCODE_BACKSLASH = 73, - AKEYCODE_SEMICOLON = 74, - AKEYCODE_APOSTROPHE = 75, - AKEYCODE_SLASH = 76, - AKEYCODE_AT = 77, - AKEYCODE_NUM = 78, - AKEYCODE_HEADSETHOOK = 79, - AKEYCODE_FOCUS = 80, // *Camera* focus - AKEYCODE_PLUS = 81, - AKEYCODE_MENU = 82, - AKEYCODE_NOTIFICATION = 83, - AKEYCODE_SEARCH = 84, - AKEYCODE_MEDIA_PLAY_PAUSE= 85, - AKEYCODE_MEDIA_STOP = 86, - AKEYCODE_MEDIA_NEXT = 87, - AKEYCODE_MEDIA_PREVIOUS = 88, - AKEYCODE_MEDIA_REWIND = 89, - AKEYCODE_MEDIA_FAST_FORWARD = 90, - AKEYCODE_MUTE = 91, - AKEYCODE_PAGE_UP = 92, - AKEYCODE_PAGE_DOWN = 93, - AKEYCODE_PICTSYMBOLS = 94, - AKEYCODE_SWITCH_CHARSET = 95, - AKEYCODE_BUTTON_A = 96, - AKEYCODE_BUTTON_B = 97, - AKEYCODE_BUTTON_C = 98, - AKEYCODE_BUTTON_X = 99, - AKEYCODE_BUTTON_Y = 100, - AKEYCODE_BUTTON_Z = 101, - AKEYCODE_BUTTON_L1 = 102, - AKEYCODE_BUTTON_R1 = 103, - AKEYCODE_BUTTON_L2 = 104, - AKEYCODE_BUTTON_R2 = 105, - AKEYCODE_BUTTON_THUMBL = 106, - AKEYCODE_BUTTON_THUMBR = 107, - AKEYCODE_BUTTON_START = 108, - AKEYCODE_BUTTON_SELECT = 109, - AKEYCODE_BUTTON_MODE = 110, - AKEYCODE_ESCAPE = 111, - AKEYCODE_FORWARD_DEL = 112, - AKEYCODE_CTRL_LEFT = 113, - AKEYCODE_CTRL_RIGHT = 114, - AKEYCODE_CAPS_LOCK = 115, - AKEYCODE_SCROLL_LOCK = 116, - AKEYCODE_META_LEFT = 117, - AKEYCODE_META_RIGHT = 118, - AKEYCODE_FUNCTION = 119, - AKEYCODE_SYSRQ = 120, - AKEYCODE_BREAK = 121, - AKEYCODE_MOVE_HOME = 122, - AKEYCODE_MOVE_END = 123, - AKEYCODE_INSERT = 124, - AKEYCODE_FORWARD = 125, - AKEYCODE_MEDIA_PLAY = 126, - AKEYCODE_MEDIA_PAUSE = 127, - AKEYCODE_MEDIA_CLOSE = 128, - AKEYCODE_MEDIA_EJECT = 129, - AKEYCODE_MEDIA_RECORD = 130, - AKEYCODE_F1 = 131, - AKEYCODE_F2 = 132, - AKEYCODE_F3 = 133, - AKEYCODE_F4 = 134, - AKEYCODE_F5 = 135, - AKEYCODE_F6 = 136, - AKEYCODE_F7 = 137, - AKEYCODE_F8 = 138, - AKEYCODE_F9 = 139, - AKEYCODE_F10 = 140, - AKEYCODE_F11 = 141, - AKEYCODE_F12 = 142, - AKEYCODE_NUM_LOCK = 143, - AKEYCODE_NUMPAD_0 = 144, - AKEYCODE_NUMPAD_1 = 145, - AKEYCODE_NUMPAD_2 = 146, - AKEYCODE_NUMPAD_3 = 147, - AKEYCODE_NUMPAD_4 = 148, - AKEYCODE_NUMPAD_5 = 149, - AKEYCODE_NUMPAD_6 = 150, - AKEYCODE_NUMPAD_7 = 151, - AKEYCODE_NUMPAD_8 = 152, - AKEYCODE_NUMPAD_9 = 153, - AKEYCODE_NUMPAD_DIVIDE = 154, - AKEYCODE_NUMPAD_MULTIPLY = 155, - AKEYCODE_NUMPAD_SUBTRACT = 156, - AKEYCODE_NUMPAD_ADD = 157, - AKEYCODE_NUMPAD_DOT = 158, - AKEYCODE_NUMPAD_COMMA = 159, - AKEYCODE_NUMPAD_ENTER = 160, - AKEYCODE_NUMPAD_EQUALS = 161, - AKEYCODE_NUMPAD_LEFT_PAREN = 162, - AKEYCODE_NUMPAD_RIGHT_PAREN = 163, - AKEYCODE_VOLUME_MUTE = 164, - AKEYCODE_INFO = 165, - AKEYCODE_CHANNEL_UP = 166, - AKEYCODE_CHANNEL_DOWN = 167, - AKEYCODE_ZOOM_IN = 168, - AKEYCODE_ZOOM_OUT = 169, - AKEYCODE_TV = 170, - AKEYCODE_WINDOW = 171, - AKEYCODE_GUIDE = 172, - AKEYCODE_DVR = 173, - AKEYCODE_BOOKMARK = 174, - AKEYCODE_CAPTIONS = 175, - AKEYCODE_SETTINGS = 176, - AKEYCODE_TV_POWER = 177, - AKEYCODE_TV_INPUT = 178, - AKEYCODE_STB_POWER = 179, - AKEYCODE_STB_INPUT = 180, - AKEYCODE_AVR_POWER = 181, - AKEYCODE_AVR_INPUT = 182, - AKEYCODE_PROG_RED = 183, - AKEYCODE_PROG_GREEN = 184, - AKEYCODE_PROG_YELLOW = 185, - AKEYCODE_PROG_BLUE = 186, - AKEYCODE_APP_SWITCH = 187, - AKEYCODE_BUTTON_1 = 188, - AKEYCODE_BUTTON_2 = 189, - AKEYCODE_BUTTON_3 = 190, - AKEYCODE_BUTTON_4 = 191, - AKEYCODE_BUTTON_5 = 192, - AKEYCODE_BUTTON_6 = 193, - AKEYCODE_BUTTON_7 = 194, - AKEYCODE_BUTTON_8 = 195, - AKEYCODE_BUTTON_9 = 196, - AKEYCODE_BUTTON_10 = 197, - AKEYCODE_BUTTON_11 = 198, - AKEYCODE_BUTTON_12 = 199, - AKEYCODE_BUTTON_13 = 200, - AKEYCODE_BUTTON_14 = 201, - AKEYCODE_BUTTON_15 = 202, - AKEYCODE_BUTTON_16 = 203, - AKEYCODE_LANGUAGE_SWITCH = 204, - AKEYCODE_MANNER_MODE = 205, - AKEYCODE_3D_MODE = 206, - AKEYCODE_CONTACTS = 207, - AKEYCODE_CALENDAR = 208, - AKEYCODE_MUSIC = 209, - AKEYCODE_CALCULATOR = 210, - AKEYCODE_ZENKAKU_HANKAKU = 211, - AKEYCODE_EISU = 212, - AKEYCODE_MUHENKAN = 213, - AKEYCODE_HENKAN = 214, - AKEYCODE_KATAKANA_HIRAGANA = 215, - AKEYCODE_YEN = 216, - AKEYCODE_RO = 217, - AKEYCODE_KANA = 218, - AKEYCODE_ASSIST = 219, - AKEYCODE_BRIGHTNESS_DOWN = 220, - AKEYCODE_BRIGHTNESS_UP = 221, - AKEYCODE_MEDIA_AUDIO_TRACK = 222, - AKEYCODE_SLEEP = 223, - AKEYCODE_WAKEUP = 224, - AKEYCODE_PAIRING = 225, - AKEYCODE_MEDIA_TOP_MENU = 226, - AKEYCODE_11 = 227, - AKEYCODE_12 = 228, - AKEYCODE_LAST_CHANNEL = 229, - AKEYCODE_TV_DATA_SERVICE = 230, - AKEYCODE_VOICE_ASSIST = 231, - AKEYCODE_TV_RADIO_SERVICE = 232, - AKEYCODE_TV_TELETEXT = 233, - AKEYCODE_TV_NUMBER_ENTRY = 234, - AKEYCODE_TV_TERRESTRIAL_ANALOG = 235, - AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236, - AKEYCODE_TV_SATELLITE = 237, - AKEYCODE_TV_SATELLITE_BS = 238, - AKEYCODE_TV_SATELLITE_CS = 239, - AKEYCODE_TV_SATELLITE_SERVICE = 240, - AKEYCODE_TV_NETWORK = 241, - AKEYCODE_TV_ANTENNA_CABLE = 242, - AKEYCODE_TV_INPUT_HDMI_1 = 243, - AKEYCODE_TV_INPUT_HDMI_2 = 244, - AKEYCODE_TV_INPUT_HDMI_3 = 245, - AKEYCODE_TV_INPUT_HDMI_4 = 246, - AKEYCODE_TV_INPUT_COMPOSITE_1 = 247, - AKEYCODE_TV_INPUT_COMPOSITE_2 = 248, - AKEYCODE_TV_INPUT_COMPONENT_1 = 249, - AKEYCODE_TV_INPUT_COMPONENT_2 = 250, - AKEYCODE_TV_INPUT_VGA_1 = 251, - AKEYCODE_TV_AUDIO_DESCRIPTION = 252, - AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253, - AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254, - AKEYCODE_TV_ZOOM_MODE = 255, - AKEYCODE_TV_CONTENTS_MENU = 256, - AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257, - AKEYCODE_TV_TIMER_PROGRAMMING = 258, - AKEYCODE_HELP = 259, - - // NOTE: If you add a new keycode here you must also add it to several other files. - // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. -}; - -#ifdef __cplusplus -} -#endif - -#endif // _ANDROID_KEYCODES_H diff --git a/widget/gonk/libui/cutils_log.h b/widget/gonk/libui/cutils_log.h deleted file mode 100644 index f4252c867..000000000 --- a/widget/gonk/libui/cutils_log.h +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// C/C++ logging functions. See the logging documentation for API details. -// -// We'd like these to be available from C code (in case we import some from -// somewhere), so this has a C interface. -// -// The output will be correct when the log file is shared between multiple -// threads and/or multiple processes so long as the operating system -// supports O_APPEND. These calls have mutex-protected data structures -// and so are NOT reentrant. Do not use LOG in a signal handler. -// -#if !defined(_LIBS_CUTILS_LOG_H) && !defined(_LIBS_LOG_LOG_H) -#define _LIBS_LOG_LOG_H -#define _LIBS_CUTILS_LOG_H - -#include <stdio.h> -#include <time.h> -#include <sys/types.h> -#include <unistd.h> -#ifdef HAVE_PTHREADS -#include <pthread.h> -#endif -#include <stdarg.h> - -#if ANDROID_VERSION >= 19 -#include <log/uio.h> -#include <log/logd.h> -#else -#include <cutils/uio.h> -#include <cutils/logd.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// --------------------------------------------------------------------- - -/* - * Normally we strip ALOGV (VERBOSE messages) from release builds. - * You can modify this (for example with "#define LOG_NDEBUG 0" - * at the top of your source file) to change that behavior. - */ -#ifndef LOG_NDEBUG -#ifdef NDEBUG -#define LOG_NDEBUG 1 -#else -#define LOG_NDEBUG 0 -#endif -#endif - -/* - * This is the local tag used for the following simplified - * logging macros. You can change this preprocessor definition - * before using the other macros to change the tag. - */ -#ifndef LOG_TAG -#define LOG_TAG NULL -#endif - -// --------------------------------------------------------------------- - -/* - * Simplified macro to send a verbose log message using the current LOG_TAG. - */ -#ifndef ALOGV -#if LOG_NDEBUG -#define ALOGV(...) ((void)0) -#else -#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#endif -#endif - -#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) - -#ifndef ALOGV_IF -#if LOG_NDEBUG -#define ALOGV_IF(cond, ...) ((void)0) -#else -#define ALOGV_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif -#endif - -/* - * Simplified macro to send a debug log message using the current LOG_TAG. - */ -#ifndef ALOGD -#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef ALOGD_IF -#define ALOGD_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an info log message using the current LOG_TAG. - */ -#ifndef ALOGI -#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef ALOGI_IF -#define ALOGI_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send a warning log message using the current LOG_TAG. - */ -#ifndef ALOGW -#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef ALOGW_IF -#define ALOGW_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an error log message using the current LOG_TAG. - */ -#ifndef ALOGE -#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef ALOGE_IF -#define ALOGE_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -// --------------------------------------------------------------------- - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * verbose priority. - */ -#ifndef IF_ALOGV -#if LOG_NDEBUG -#define IF_ALOGV() if (false) -#else -#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG) -#endif -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * debug priority. - */ -#ifndef IF_ALOGD -#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * info priority. - */ -#ifndef IF_ALOGI -#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * warn priority. - */ -#ifndef IF_ALOGW -#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * error priority. - */ -#ifndef IF_ALOGE -#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG) -#endif - - -// --------------------------------------------------------------------- - -/* - * Simplified macro to send a verbose system log message using the current LOG_TAG. - */ -#ifndef SLOGV -#if LOG_NDEBUG -#define SLOGV(...) ((void)0) -#else -#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#endif -#endif - -#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) - -#ifndef SLOGV_IF -#if LOG_NDEBUG -#define SLOGV_IF(cond, ...) ((void)0) -#else -#define SLOGV_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif -#endif - -/* - * Simplified macro to send a debug system log message using the current LOG_TAG. - */ -#ifndef SLOGD -#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef SLOGD_IF -#define SLOGD_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an info system log message using the current LOG_TAG. - */ -#ifndef SLOGI -#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef SLOGI_IF -#define SLOGI_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send a warning system log message using the current LOG_TAG. - */ -#ifndef SLOGW -#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef SLOGW_IF -#define SLOGW_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an error system log message using the current LOG_TAG. - */ -#ifndef SLOGE -#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef SLOGE_IF -#define SLOGE_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -// --------------------------------------------------------------------- - -/* - * Simplified macro to send a verbose radio log message using the current LOG_TAG. - */ -#ifndef RLOGV -#if LOG_NDEBUG -#define RLOGV(...) ((void)0) -#else -#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#endif -#endif - -#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) - -#ifndef RLOGV_IF -#if LOG_NDEBUG -#define RLOGV_IF(cond, ...) ((void)0) -#else -#define RLOGV_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif -#endif - -/* - * Simplified macro to send a debug radio log message using the current LOG_TAG. - */ -#ifndef RLOGD -#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef RLOGD_IF -#define RLOGD_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an info radio log message using the current LOG_TAG. - */ -#ifndef RLOGI -#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef RLOGI_IF -#define RLOGI_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send a warning radio log message using the current LOG_TAG. - */ -#ifndef RLOGW -#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef RLOGW_IF -#define RLOGW_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an error radio log message using the current LOG_TAG. - */ -#ifndef RLOGE -#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef RLOGE_IF -#define RLOGE_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - - -// --------------------------------------------------------------------- - -/* - * Log a fatal error. If the given condition fails, this stops program - * execution like a normal assertion, but also generating the given message. - * It is NOT stripped from release builds. Note that the condition test - * is -inverted- from the normal assert() semantics. - */ -#ifndef LOG_ALWAYS_FATAL_IF -#define LOG_ALWAYS_FATAL_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \ - : (void)0 ) -#endif - -#ifndef LOG_ALWAYS_FATAL -#define LOG_ALWAYS_FATAL(...) \ - ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) ) -#endif - -/* - * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that - * are stripped out of release builds. - */ -#if LOG_NDEBUG - -#ifndef LOG_FATAL_IF -#define LOG_FATAL_IF(cond, ...) ((void)0) -#endif -#ifndef LOG_FATAL -#define LOG_FATAL(...) ((void)0) -#endif - -#else - -#ifndef LOG_FATAL_IF -#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__) -#endif -#ifndef LOG_FATAL -#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__) -#endif - -#endif - -/* - * Assertion that generates a log message when the assertion fails. - * Stripped out of release builds. Uses the current LOG_TAG. - */ -#ifndef ALOG_ASSERT -#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__) -//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond) -#endif - -// --------------------------------------------------------------------- - -/* - * Basic log message macro. - * - * Example: - * ALOG(LOG_WARN, NULL, "Failed with error %d", errno); - * - * The second argument may be NULL or "" to indicate the "global" tag. - */ -#ifndef ALOG -#define ALOG(priority, tag, ...) \ - LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) -#endif - -/* - * Log macro that allows you to specify a number for the priority. - */ -#ifndef LOG_PRI -#define LOG_PRI(priority, tag, ...) \ - android_printLog(priority, tag, __VA_ARGS__) -#endif - -/* - * Log macro that allows you to pass in a varargs ("args" is a va_list). - */ -#ifndef LOG_PRI_VA -#define LOG_PRI_VA(priority, tag, fmt, args) \ - android_vprintLog(priority, NULL, tag, fmt, args) -#endif - -/* - * Conditional given a desired logging priority and tag. - */ -#ifndef IF_ALOG -#define IF_ALOG(priority, tag) \ - if (android_testLog(ANDROID_##priority, tag)) -#endif - -// --------------------------------------------------------------------- - -/* - * Event logging. - */ - -/* - * Event log entry types. These must match up with the declarations in - * java/android/android/util/EventLog.java. - */ -typedef enum { - EVENT_TYPE_INT = 0, - EVENT_TYPE_LONG = 1, - EVENT_TYPE_STRING = 2, - EVENT_TYPE_LIST = 3, -} AndroidEventLogType; - - -#ifndef LOG_EVENT_INT -#define LOG_EVENT_INT(_tag, _value) { \ - int intBuf = _value; \ - (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, \ - sizeof(intBuf)); \ - } -#endif -#ifndef LOG_EVENT_LONG -#define LOG_EVENT_LONG(_tag, _value) { \ - long long longBuf = _value; \ - (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, \ - sizeof(longBuf)); \ - } -#endif -#ifndef LOG_EVENT_STRING -#define LOG_EVENT_STRING(_tag, _value) \ - ((void) 0) /* not implemented -- must combine len with string */ -#endif -/* TODO: something for LIST */ - -/* - * =========================================================================== - * - * The stuff in the rest of this file should not be used directly. - */ - -#define android_printLog(prio, tag, fmt...) \ - __android_log_print(prio, tag, fmt) - -#define android_vprintLog(prio, cond, tag, fmt...) \ - __android_log_vprint(prio, tag, fmt) - -/* XXX Macros to work around syntax errors in places where format string - * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF - * (happens only in debug builds). - */ - -/* Returns 2nd arg. Used to substitute default value if caller's vararg list - * is empty. - */ -#define __android_second(dummy, second, ...) second - -/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise - * returns nothing. - */ -#define __android_rest(first, ...) , ## __VA_ARGS__ - -#define android_printAssert(cond, tag, fmt...) \ - __android_log_assert(cond, tag, \ - __android_second(0, ## fmt, NULL) __android_rest(fmt)) - -#define android_writeLog(prio, tag, text) \ - __android_log_write(prio, tag, text) - -#define android_bWriteLog(tag, payload, len) \ - __android_log_bwrite(tag, payload, len) -#define android_btWriteLog(tag, type, payload, len) \ - __android_log_btwrite(tag, type, payload, len) - -// TODO: remove these prototypes and their users -#define android_testLog(prio, tag) (1) -#define android_writevLog(vec,num) do{}while(0) -#define android_write1Log(str,len) do{}while (0) -#define android_setMinPriority(tag, prio) do{}while(0) -//#define android_logToCallback(func) do{}while(0) -#define android_logToFile(tag, file) (0) -#define android_logToFd(tag, fd) (0) - -typedef enum { - LOG_ID_MAIN = 0, - LOG_ID_RADIO = 1, - LOG_ID_EVENTS = 2, - LOG_ID_SYSTEM = 3, - - LOG_ID_MAX -} log_id_t; - -/* - * Send a simple string to the log. - */ -int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text); -int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...); - - -#ifdef __cplusplus -} -#endif - -#endif // _LIBS_CUTILS_LOG_H diff --git a/widget/gonk/libui/cutils_trace.h b/widget/gonk/libui/cutils_trace.h deleted file mode 100644 index 29034cab5..000000000 --- a/widget/gonk/libui/cutils_trace.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _LIBS_CUTILS_TRACE_H -#define _LIBS_CUTILS_TRACE_H - -#include <sys/cdefs.h> -#include <sys/types.h> -#include <stdint.h> -#include <stdbool.h> -#include <unistd.h> -#include <cutils/compiler.h> - -#ifdef ANDROID_SMP -#include <cutils/atomic-inline.h> -#else -#include <cutils/atomic.h> -#endif - -__BEGIN_DECLS - -/** - * The ATRACE_TAG macro can be defined before including this header to trace - * using one of the tags defined below. It must be defined to one of the - * following ATRACE_TAG_* macros. The trace tag is used to filter tracing in - * userland to avoid some of the runtime cost of tracing when it is not desired. - * - * Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always - * being enabled - this should ONLY be done for debug code, as userland tracing - * has a performance cost even when the trace is not being recorded. Defining - * ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result - * in the tracing always being disabled. - * - * ATRACE_TAG_HAL should be bitwise ORed with the relevant tags for tracing - * within a hardware module. For example a camera hardware module would set: - * #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) - * - * Keep these in sync with frameworks/base/core/java/android/os/Trace.java. - */ -#define ATRACE_TAG_NEVER 0 // This tag is never enabled. -#define ATRACE_TAG_ALWAYS (1<<0) // This tag is always enabled. -#define ATRACE_TAG_GRAPHICS (1<<1) -#define ATRACE_TAG_INPUT (1<<2) -#define ATRACE_TAG_VIEW (1<<3) -#define ATRACE_TAG_WEBVIEW (1<<4) -#define ATRACE_TAG_WINDOW_MANAGER (1<<5) -#define ATRACE_TAG_ACTIVITY_MANAGER (1<<6) -#define ATRACE_TAG_SYNC_MANAGER (1<<7) -#define ATRACE_TAG_AUDIO (1<<8) -#define ATRACE_TAG_VIDEO (1<<9) -#define ATRACE_TAG_CAMERA (1<<10) -#define ATRACE_TAG_HAL (1<<11) -#define ATRACE_TAG_APP (1<<12) -#define ATRACE_TAG_RESOURCES (1<<13) -#define ATRACE_TAG_DALVIK (1<<14) -#define ATRACE_TAG_LAST ATRACE_TAG_DALVIK - -// Reserved for initialization. -#define ATRACE_TAG_NOT_READY (1LL<<63) - -#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST) - -#ifndef ATRACE_TAG -#define ATRACE_TAG ATRACE_TAG_NEVER -#elif ATRACE_TAG > ATRACE_TAG_VALID_MASK -#error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h -#endif - -#ifdef HAVE_ANDROID_OS -/** - * Maximum size of a message that can be logged to the trace buffer. - * Note this message includes a tag, the pid, and the string given as the name. - * Names should be kept short to get the most use of the trace buffer. - */ -#define ATRACE_MESSAGE_LENGTH 1024 - -/** - * Opens the trace file for writing and reads the property for initial tags. - * The atrace.tags.enableflags property sets the tags to trace. - * This function should not be explicitly called, the first call to any normal - * trace function will cause it to be run safely. - */ -void atrace_setup(); - -/** - * If tracing is ready, set atrace_enabled_tags to the system property - * debug.atrace.tags.enableflags. Can be used as a sysprop change callback. - */ -void atrace_update_tags(); - -/** - * Set whether the process is debuggable. By default the process is not - * considered debuggable. If the process is not debuggable then application- - * level tracing is not allowed unless the ro.debuggable system property is - * set to '1'. - */ -void atrace_set_debuggable(bool debuggable); - -/** - * Set whether tracing is enabled for the current process. This is used to - * prevent tracing within the Zygote process. - */ -void atrace_set_tracing_enabled(bool enabled); - -/** - * Flag indicating whether setup has been completed, initialized to 0. - * Nonzero indicates setup has completed. - * Note: This does NOT indicate whether or not setup was successful. - */ -extern volatile int32_t atrace_is_ready; - -/** - * Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY. - * A value of zero indicates setup has failed. - * Any other nonzero value indicates setup has succeeded, and tracing is on. - */ -extern uint64_t atrace_enabled_tags; - -/** - * Handle to the kernel's trace buffer, initialized to -1. - * Any other value indicates setup has succeeded, and is a valid fd for tracing. - */ -extern int atrace_marker_fd; - -/** - * atrace_init readies the process for tracing by opening the trace_marker file. - * Calling any trace function causes this to be run, so calling it is optional. - * This can be explicitly run to avoid setup delay on first trace function. - */ -#define ATRACE_INIT() atrace_init() -static inline void atrace_init() -{ - if (CC_UNLIKELY(!android_atomic_acquire_load(&atrace_is_ready))) { - atrace_setup(); - } -} - -/** - * Get the mask of all tags currently enabled. - * It can be used as a guard condition around more expensive trace calculations. - * Every trace function calls this, which ensures atrace_init is run. - */ -#define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags() -static inline uint64_t atrace_get_enabled_tags() -{ - atrace_init(); - return atrace_enabled_tags; -} - -/** - * Test if a given tag is currently enabled. - * Returns nonzero if the tag is enabled, otherwise zero. - * It can be used as a guard condition around more expensive trace calculations. - */ -#define ATRACE_ENABLED() atrace_is_tag_enabled(ATRACE_TAG) -static inline uint64_t atrace_is_tag_enabled(uint64_t tag) -{ - return atrace_get_enabled_tags() & tag; -} - -/** - * Trace the beginning of a context. name is used to identify the context. - * This is often used to time function execution. - */ -#define ATRACE_BEGIN(name) atrace_begin(ATRACE_TAG, name) -static inline void atrace_begin(uint64_t tag, const char* name) -{ - if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { - char buf[ATRACE_MESSAGE_LENGTH]; - size_t len; - - len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "B|%d|%s", getpid(), name); - write(atrace_marker_fd, buf, len); - } -} - -/** - * Trace the end of a context. - * This should match up (and occur after) a corresponding ATRACE_BEGIN. - */ -#define ATRACE_END() atrace_end(ATRACE_TAG) -static inline void atrace_end(uint64_t tag) -{ - if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { - char c = 'E'; - write(atrace_marker_fd, &c, 1); - } -} - -/** - * Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END - * contexts, asynchronous events do not need to be nested. The name describes - * the event, and the cookie provides a unique identifier for distinguishing - * simultaneous events. The name and cookie used to begin an event must be - * used to end it. - */ -#define ATRACE_ASYNC_BEGIN(name, cookie) \ - atrace_async_begin(ATRACE_TAG, name, cookie) -static inline void atrace_async_begin(uint64_t tag, const char* name, - int32_t cookie) -{ - if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { - char buf[ATRACE_MESSAGE_LENGTH]; - size_t len; - - len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "S|%d|%s|%d", getpid(), - name, cookie); - write(atrace_marker_fd, buf, len); - } -} - -/** - * Trace the end of an asynchronous event. - * This should have a corresponding ATRACE_ASYNC_BEGIN. - */ -#define ATRACE_ASYNC_END(name, cookie) atrace_async_end(ATRACE_TAG, name, cookie) -static inline void atrace_async_end(uint64_t tag, const char* name, - int32_t cookie) -{ - if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { - char buf[ATRACE_MESSAGE_LENGTH]; - size_t len; - - len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "F|%d|%s|%d", getpid(), - name, cookie); - write(atrace_marker_fd, buf, len); - } -} - - -/** - * Traces an integer counter value. name is used to identify the counter. - * This can be used to track how a value changes over time. - */ -#define ATRACE_INT(name, value) atrace_int(ATRACE_TAG, name, value) -static inline void atrace_int(uint64_t tag, const char* name, int32_t value) -{ - if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { - char buf[ATRACE_MESSAGE_LENGTH]; - size_t len; - - len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%d", - getpid(), name, value); - write(atrace_marker_fd, buf, len); - } -} - -#else // not HAVE_ANDROID_OS - -#define ATRACE_INIT() -#define ATRACE_GET_ENABLED_TAGS() -#define ATRACE_ENABLED() -#define ATRACE_BEGIN(name) -#define ATRACE_END() -#define ATRACE_ASYNC_BEGIN(name, cookie) -#define ATRACE_ASYNC_END(name, cookie) -#define ATRACE_INT(name, value) - -#endif // not HAVE_ANDROID_OS - -__END_DECLS - -#endif // _LIBS_CUTILS_TRACE_H diff --git a/widget/gonk/libui/linux_input.h b/widget/gonk/libui/linux_input.h deleted file mode 100644 index 2ba14973f..000000000 --- a/widget/gonk/libui/linux_input.h +++ /dev/null @@ -1,1029 +0,0 @@ -/**************************************************************************** - **************************************************************************** - *** - *** This header was automatically generated from a Linux kernel header - *** of the same name, to make information necessary for userspace to - *** call into the kernel available to libc. It contains only constants, - *** structures, and macros generated from the original header, and thus, - *** contains no copyrightable information. - *** - *** To edit the content of this header, modify the corresponding - *** source file (e.g. under external/kernel-headers/original/) then - *** run bionic/libc/kernel/tools/update_all.py - *** - *** Any manual change here will be lost the next time this script will - *** be run. You've been warned! - *** - **************************************************************************** - ****************************************************************************/ -#ifndef _INPUT_H -#define _INPUT_H -#include <sys/time.h> -#include <sys/ioctl.h> -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#include <sys/types.h> -#include <linux/types.h> -struct input_event { - struct timeval time; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __u16 type; - __u16 code; - __s32 value; -}; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EV_VERSION 0x010001 -struct input_id { - __u16 bustype; - __u16 vendor; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __u16 product; - __u16 version; -}; -struct input_absinfo { -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __s32 value; - __s32 minimum; - __s32 maximum; - __s32 fuzz; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __s32 flat; - __s32 resolution; -}; -struct input_keymap_entry { -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define INPUT_KEYMAP_BY_INDEX (1 << 0) - __u8 flags; - __u8 len; - __u16 index; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __u32 keycode; - __u8 scancode[32]; -}; -#define EVIOCGVERSION _IOR('E', 0x01, int) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EVIOCGID _IOR('E', 0x02, struct input_id) -#define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) -#define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) -#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EVIOCGKEYCODE_V2 _IOR('E', 0x04, struct input_keymap_entry) -#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) -#define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry) -#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) -#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) -#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) -#define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) -#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) -#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) -#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + (ev), len) -#define EVIOCGABS(abs) _IOR('E', 0x40 + (abs), struct input_absinfo) -#define EVIOCSABS(abs) _IOW('E', 0xc0 + (abs), struct input_absinfo) -#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EVIOCRMFF _IOW('E', 0x81, int) -#define EVIOCGEFFECTS _IOR('E', 0x84, int) -#define EVIOCGRAB _IOW('E', 0x90, int) -#define EVIOCGSUSPENDBLOCK _IOR('E', 0x91, int) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int) -#define EVIOCSCLOCKID _IOW('E', 0xa0, int) -#define INPUT_PROP_POINTER 0x00 -#define INPUT_PROP_DIRECT 0x01 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define INPUT_PROP_BUTTONPAD 0x02 -#define INPUT_PROP_SEMI_MT 0x03 -#define INPUT_PROP_MAX 0x1f -#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EV_SYN 0x00 -#define EV_KEY 0x01 -#define EV_REL 0x02 -#define EV_ABS 0x03 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EV_MSC 0x04 -#define EV_SW 0x05 -#define EV_LED 0x11 -#define EV_SND 0x12 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EV_REP 0x14 -#define EV_FF 0x15 -#define EV_PWR 0x16 -#define EV_FF_STATUS 0x17 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define EV_MAX 0x1f -#define EV_CNT (EV_MAX+1) -#define SYN_REPORT 0 -#define SYN_CONFIG 1 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define SYN_MT_REPORT 2 -#define SYN_DROPPED 3 -#define SYN_TIME_SEC 4 -#define SYN_TIME_NSEC 5 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_RESERVED 0 -#define KEY_ESC 1 -#define KEY_1 2 -#define KEY_2 3 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_3 4 -#define KEY_4 5 -#define KEY_5 6 -#define KEY_6 7 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_7 8 -#define KEY_8 9 -#define KEY_9 10 -#define KEY_0 11 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_MINUS 12 -#define KEY_EQUAL 13 -#define KEY_BACKSPACE 14 -#define KEY_TAB 15 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_Q 16 -#define KEY_W 17 -#define KEY_E 18 -#define KEY_R 19 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_T 20 -#define KEY_Y 21 -#define KEY_U 22 -#define KEY_I 23 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_O 24 -#define KEY_P 25 -#define KEY_LEFTBRACE 26 -#define KEY_RIGHTBRACE 27 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_ENTER 28 -#define KEY_LEFTCTRL 29 -#define KEY_A 30 -#define KEY_S 31 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_D 32 -#define KEY_F 33 -#define KEY_G 34 -#define KEY_H 35 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_J 36 -#define KEY_K 37 -#define KEY_L 38 -#define KEY_SEMICOLON 39 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_APOSTROPHE 40 -#define KEY_GRAVE 41 -#define KEY_LEFTSHIFT 42 -#define KEY_BACKSLASH 43 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_Z 44 -#define KEY_X 45 -#define KEY_C 46 -#define KEY_V 47 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_B 48 -#define KEY_N 49 -#define KEY_M 50 -#define KEY_COMMA 51 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_DOT 52 -#define KEY_SLASH 53 -#define KEY_RIGHTSHIFT 54 -#define KEY_KPASTERISK 55 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_LEFTALT 56 -#define KEY_SPACE 57 -#define KEY_CAPSLOCK 58 -#define KEY_F1 59 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_F2 60 -#define KEY_F3 61 -#define KEY_F4 62 -#define KEY_F5 63 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_F6 64 -#define KEY_F7 65 -#define KEY_F8 66 -#define KEY_F9 67 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_F10 68 -#define KEY_NUMLOCK 69 -#define KEY_SCROLLLOCK 70 -#define KEY_KP7 71 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KP8 72 -#define KEY_KP9 73 -#define KEY_KPMINUS 74 -#define KEY_KP4 75 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KP5 76 -#define KEY_KP6 77 -#define KEY_KPPLUS 78 -#define KEY_KP1 79 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KP2 80 -#define KEY_KP3 81 -#define KEY_KP0 82 -#define KEY_KPDOT 83 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_ZENKAKUHANKAKU 85 -#define KEY_102ND 86 -#define KEY_F11 87 -#define KEY_F12 88 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_RO 89 -#define KEY_KATAKANA 90 -#define KEY_HIRAGANA 91 -#define KEY_HENKAN 92 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KATAKANAHIRAGANA 93 -#define KEY_MUHENKAN 94 -#define KEY_KPJPCOMMA 95 -#define KEY_KPENTER 96 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_RIGHTCTRL 97 -#define KEY_KPSLASH 98 -#define KEY_SYSRQ 99 -#define KEY_RIGHTALT 100 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_LINEFEED 101 -#define KEY_HOME 102 -#define KEY_UP 103 -#define KEY_PAGEUP 104 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_LEFT 105 -#define KEY_RIGHT 106 -#define KEY_END 107 -#define KEY_DOWN 108 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_PAGEDOWN 109 -#define KEY_INSERT 110 -#define KEY_DELETE 111 -#define KEY_MACRO 112 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_MUTE 113 -#define KEY_VOLUMEDOWN 114 -#define KEY_VOLUMEUP 115 -#define KEY_POWER 116 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KPEQUAL 117 -#define KEY_KPPLUSMINUS 118 -#define KEY_PAUSE 119 -#define KEY_SCALE 120 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KPCOMMA 121 -#define KEY_HANGEUL 122 -#define KEY_HANGUEL KEY_HANGEUL -#define KEY_HANJA 123 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_YEN 124 -#define KEY_LEFTMETA 125 -#define KEY_RIGHTMETA 126 -#define KEY_COMPOSE 127 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_STOP 128 -#define KEY_AGAIN 129 -#define KEY_PROPS 130 -#define KEY_UNDO 131 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FRONT 132 -#define KEY_COPY 133 -#define KEY_OPEN 134 -#define KEY_PASTE 135 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FIND 136 -#define KEY_CUT 137 -#define KEY_HELP 138 -#define KEY_MENU 139 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_CALC 140 -#define KEY_SETUP 141 -#define KEY_SLEEP 142 -#define KEY_WAKEUP 143 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FILE 144 -#define KEY_SENDFILE 145 -#define KEY_DELETEFILE 146 -#define KEY_XFER 147 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_PROG1 148 -#define KEY_PROG2 149 -#define KEY_WWW 150 -#define KEY_MSDOS 151 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_COFFEE 152 -#define KEY_SCREENLOCK KEY_COFFEE -#define KEY_DIRECTION 153 -#define KEY_CYCLEWINDOWS 154 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_MAIL 155 -#define KEY_BOOKMARKS 156 -#define KEY_COMPUTER 157 -#define KEY_BACK 158 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FORWARD 159 -#define KEY_CLOSECD 160 -#define KEY_EJECTCD 161 -#define KEY_EJECTCLOSECD 162 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_NEXTSONG 163 -#define KEY_PLAYPAUSE 164 -#define KEY_PREVIOUSSONG 165 -#define KEY_STOPCD 166 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_RECORD 167 -#define KEY_REWIND 168 -#define KEY_PHONE 169 -#define KEY_ISO 170 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_CONFIG 171 -#define KEY_HOMEPAGE 172 -#define KEY_REFRESH 173 -#define KEY_EXIT 174 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_MOVE 175 -#define KEY_EDIT 176 -#define KEY_SCROLLUP 177 -#define KEY_SCROLLDOWN 178 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KPLEFTPAREN 179 -#define KEY_KPRIGHTPAREN 180 -#define KEY_NEW 181 -#define KEY_REDO 182 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_F13 183 -#define KEY_F14 184 -#define KEY_F15 185 -#define KEY_F16 186 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_F17 187 -#define KEY_F18 188 -#define KEY_F19 189 -#define KEY_F20 190 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_F21 191 -#define KEY_F22 192 -#define KEY_F23 193 -#define KEY_F24 194 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_PLAYCD 200 -#define KEY_PAUSECD 201 -#define KEY_PROG3 202 -#define KEY_PROG4 203 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_DASHBOARD 204 -#define KEY_SUSPEND 205 -#define KEY_CLOSE 206 -#define KEY_PLAY 207 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FASTFORWARD 208 -#define KEY_BASSBOOST 209 -#define KEY_PRINT 210 -#define KEY_HP 211 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_CAMERA 212 -#define KEY_SOUND 213 -#define KEY_QUESTION 214 -#define KEY_EMAIL 215 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_CHAT 216 -#define KEY_SEARCH 217 -#define KEY_CONNECT 218 -#define KEY_FINANCE 219 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_SPORT 220 -#define KEY_SHOP 221 -#define KEY_ALTERASE 222 -#define KEY_CANCEL 223 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_BRIGHTNESSDOWN 224 -#define KEY_BRIGHTNESSUP 225 -#define KEY_MEDIA 226 -#define KEY_SWITCHVIDEOMODE 227 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KBDILLUMTOGGLE 228 -#define KEY_KBDILLUMDOWN 229 -#define KEY_KBDILLUMUP 230 -#define KEY_SEND 231 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_REPLY 232 -#define KEY_FORWARDMAIL 233 -#define KEY_SAVE 234 -#define KEY_DOCUMENTS 235 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_BATTERY 236 -#define KEY_BLUETOOTH 237 -#define KEY_WLAN 238 -#define KEY_UWB 239 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_UNKNOWN 240 -#define KEY_VIDEO_NEXT 241 -#define KEY_VIDEO_PREV 242 -#define KEY_BRIGHTNESS_CYCLE 243 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_BRIGHTNESS_ZERO 244 -#define KEY_DISPLAY_OFF 245 -#define KEY_WIMAX 246 -#define KEY_RFKILL 247 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_MICMUTE 248 -#define BTN_MISC 0x100 -#define BTN_0 0x100 -#define BTN_1 0x101 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_2 0x102 -#define BTN_3 0x103 -#define BTN_4 0x104 -#define BTN_5 0x105 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_6 0x106 -#define BTN_7 0x107 -#define BTN_8 0x108 -#define BTN_9 0x109 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_MOUSE 0x110 -#define BTN_LEFT 0x110 -#define BTN_RIGHT 0x111 -#define BTN_MIDDLE 0x112 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_SIDE 0x113 -#define BTN_EXTRA 0x114 -#define BTN_FORWARD 0x115 -#define BTN_BACK 0x116 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TASK 0x117 -#define BTN_JOYSTICK 0x120 -#define BTN_TRIGGER 0x120 -#define BTN_THUMB 0x121 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_THUMB2 0x122 -#define BTN_TOP 0x123 -#define BTN_TOP2 0x124 -#define BTN_PINKIE 0x125 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_BASE 0x126 -#define BTN_BASE2 0x127 -#define BTN_BASE3 0x128 -#define BTN_BASE4 0x129 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_BASE5 0x12a -#define BTN_BASE6 0x12b -#define BTN_DEAD 0x12f -#define BTN_GAMEPAD 0x130 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_A 0x130 -#define BTN_B 0x131 -#define BTN_C 0x132 -#define BTN_X 0x133 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_Y 0x134 -#define BTN_Z 0x135 -#define BTN_TL 0x136 -#define BTN_TR 0x137 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TL2 0x138 -#define BTN_TR2 0x139 -#define BTN_SELECT 0x13a -#define BTN_START 0x13b -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_MODE 0x13c -#define BTN_THUMBL 0x13d -#define BTN_THUMBR 0x13e -#define BTN_DIGI 0x140 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TOOL_PEN 0x140 -#define BTN_TOOL_RUBBER 0x141 -#define BTN_TOOL_BRUSH 0x142 -#define BTN_TOOL_PENCIL 0x143 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TOOL_AIRBRUSH 0x144 -#define BTN_TOOL_FINGER 0x145 -#define BTN_TOOL_MOUSE 0x146 -#define BTN_TOOL_LENS 0x147 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TOOL_QUINTTAP 0x148 -#define BTN_TOUCH 0x14a -#define BTN_STYLUS 0x14b -#define BTN_STYLUS2 0x14c -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TOOL_DOUBLETAP 0x14d -#define BTN_TOOL_TRIPLETAP 0x14e -#define BTN_TOOL_QUADTAP 0x14f -#define BTN_WHEEL 0x150 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_GEAR_DOWN 0x150 -#define BTN_GEAR_UP 0x151 -#define KEY_OK 0x160 -#define KEY_SELECT 0x161 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_GOTO 0x162 -#define KEY_CLEAR 0x163 -#define KEY_POWER2 0x164 -#define KEY_OPTION 0x165 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_INFO 0x166 -#define KEY_TIME 0x167 -#define KEY_VENDOR 0x168 -#define KEY_ARCHIVE 0x169 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_PROGRAM 0x16a -#define KEY_CHANNEL 0x16b -#define KEY_FAVORITES 0x16c -#define KEY_EPG 0x16d -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_PVR 0x16e -#define KEY_MHP 0x16f -#define KEY_LANGUAGE 0x170 -#define KEY_TITLE 0x171 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_SUBTITLE 0x172 -#define KEY_ANGLE 0x173 -#define KEY_ZOOM 0x174 -#define KEY_MODE 0x175 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_KEYBOARD 0x176 -#define KEY_SCREEN 0x177 -#define KEY_PC 0x178 -#define KEY_TV 0x179 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_TV2 0x17a -#define KEY_VCR 0x17b -#define KEY_VCR2 0x17c -#define KEY_SAT 0x17d -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_SAT2 0x17e -#define KEY_CD 0x17f -#define KEY_TAPE 0x180 -#define KEY_RADIO 0x181 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_TUNER 0x182 -#define KEY_PLAYER 0x183 -#define KEY_TEXT 0x184 -#define KEY_DVD 0x185 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_AUX 0x186 -#define KEY_MP3 0x187 -#define KEY_AUDIO 0x188 -#define KEY_VIDEO 0x189 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_DIRECTORY 0x18a -#define KEY_LIST 0x18b -#define KEY_MEMO 0x18c -#define KEY_CALENDAR 0x18d -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_RED 0x18e -#define KEY_GREEN 0x18f -#define KEY_YELLOW 0x190 -#define KEY_BLUE 0x191 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_CHANNELUP 0x192 -#define KEY_CHANNELDOWN 0x193 -#define KEY_FIRST 0x194 -#define KEY_LAST 0x195 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_AB 0x196 -#define KEY_NEXT 0x197 -#define KEY_RESTART 0x198 -#define KEY_SLOW 0x199 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_SHUFFLE 0x19a -#define KEY_BREAK 0x19b -#define KEY_PREVIOUS 0x19c -#define KEY_DIGITS 0x19d -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_TEEN 0x19e -#define KEY_TWEN 0x19f -#define KEY_VIDEOPHONE 0x1a0 -#define KEY_GAMES 0x1a1 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_ZOOMIN 0x1a2 -#define KEY_ZOOMOUT 0x1a3 -#define KEY_ZOOMRESET 0x1a4 -#define KEY_WORDPROCESSOR 0x1a5 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_EDITOR 0x1a6 -#define KEY_SPREADSHEET 0x1a7 -#define KEY_GRAPHICSEDITOR 0x1a8 -#define KEY_PRESENTATION 0x1a9 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_DATABASE 0x1aa -#define KEY_NEWS 0x1ab -#define KEY_VOICEMAIL 0x1ac -#define KEY_ADDRESSBOOK 0x1ad -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_MESSENGER 0x1ae -#define KEY_DISPLAYTOGGLE 0x1af -#define KEY_SPELLCHECK 0x1b0 -#define KEY_LOGOFF 0x1b1 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_DOLLAR 0x1b2 -#define KEY_EURO 0x1b3 -#define KEY_FRAMEBACK 0x1b4 -#define KEY_FRAMEFORWARD 0x1b5 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_CONTEXT_MENU 0x1b6 -#define KEY_MEDIA_REPEAT 0x1b7 -#define KEY_10CHANNELSUP 0x1b8 -#define KEY_10CHANNELSDOWN 0x1b9 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_IMAGES 0x1ba -#define KEY_DEL_EOL 0x1c0 -#define KEY_DEL_EOS 0x1c1 -#define KEY_INS_LINE 0x1c2 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_DEL_LINE 0x1c3 -#define KEY_FN 0x1d0 -#define KEY_FN_ESC 0x1d1 -#define KEY_FN_F1 0x1d2 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FN_F2 0x1d3 -#define KEY_FN_F3 0x1d4 -#define KEY_FN_F4 0x1d5 -#define KEY_FN_F5 0x1d6 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FN_F6 0x1d7 -#define KEY_FN_F7 0x1d8 -#define KEY_FN_F8 0x1d9 -#define KEY_FN_F9 0x1da -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FN_F10 0x1db -#define KEY_FN_F11 0x1dc -#define KEY_FN_F12 0x1dd -#define KEY_FN_1 0x1de -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FN_2 0x1df -#define KEY_FN_D 0x1e0 -#define KEY_FN_E 0x1e1 -#define KEY_FN_F 0x1e2 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_FN_S 0x1e3 -#define KEY_FN_B 0x1e4 -#define KEY_BRL_DOT1 0x1f1 -#define KEY_BRL_DOT2 0x1f2 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_BRL_DOT3 0x1f3 -#define KEY_BRL_DOT4 0x1f4 -#define KEY_BRL_DOT5 0x1f5 -#define KEY_BRL_DOT6 0x1f6 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_BRL_DOT7 0x1f7 -#define KEY_BRL_DOT8 0x1f8 -#define KEY_BRL_DOT9 0x1f9 -#define KEY_BRL_DOT10 0x1fa -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_NUMERIC_0 0x200 -#define KEY_NUMERIC_1 0x201 -#define KEY_NUMERIC_2 0x202 -#define KEY_NUMERIC_3 0x203 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_NUMERIC_4 0x204 -#define KEY_NUMERIC_5 0x205 -#define KEY_NUMERIC_6 0x206 -#define KEY_NUMERIC_7 0x207 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_NUMERIC_8 0x208 -#define KEY_NUMERIC_9 0x209 -#define KEY_NUMERIC_STAR 0x20a -#define KEY_NUMERIC_POUND 0x20b -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_CAMERA_SNAPSHOT 0x2fe -#define KEY_CAMERA_FOCUS 0x210 -#define KEY_WPS_BUTTON 0x211 -#define KEY_TOUCHPAD_TOGGLE 0x212 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_TOUCHPAD_ON 0x213 -#define KEY_TOUCHPAD_OFF 0x214 -#define KEY_CAMERA_ZOOMIN 0x215 -#define KEY_CAMERA_ZOOMOUT 0x216 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define KEY_CAMERA_UP 0x217 -#define KEY_CAMERA_DOWN 0x218 -#define KEY_CAMERA_LEFT 0x219 -#define KEY_CAMERA_RIGHT 0x21a -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY 0x2c0 -#define BTN_TRIGGER_HAPPY1 0x2c0 -#define BTN_TRIGGER_HAPPY2 0x2c1 -#define BTN_TRIGGER_HAPPY3 0x2c2 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY4 0x2c3 -#define BTN_TRIGGER_HAPPY5 0x2c4 -#define BTN_TRIGGER_HAPPY6 0x2c5 -#define BTN_TRIGGER_HAPPY7 0x2c6 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY8 0x2c7 -#define BTN_TRIGGER_HAPPY9 0x2c8 -#define BTN_TRIGGER_HAPPY10 0x2c9 -#define BTN_TRIGGER_HAPPY11 0x2ca -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY12 0x2cb -#define BTN_TRIGGER_HAPPY13 0x2cc -#define BTN_TRIGGER_HAPPY14 0x2cd -#define BTN_TRIGGER_HAPPY15 0x2ce -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY16 0x2cf -#define BTN_TRIGGER_HAPPY17 0x2d0 -#define BTN_TRIGGER_HAPPY18 0x2d1 -#define BTN_TRIGGER_HAPPY19 0x2d2 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY20 0x2d3 -#define BTN_TRIGGER_HAPPY21 0x2d4 -#define BTN_TRIGGER_HAPPY22 0x2d5 -#define BTN_TRIGGER_HAPPY23 0x2d6 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY24 0x2d7 -#define BTN_TRIGGER_HAPPY25 0x2d8 -#define BTN_TRIGGER_HAPPY26 0x2d9 -#define BTN_TRIGGER_HAPPY27 0x2da -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY28 0x2db -#define BTN_TRIGGER_HAPPY29 0x2dc -#define BTN_TRIGGER_HAPPY30 0x2dd -#define BTN_TRIGGER_HAPPY31 0x2de -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY32 0x2df -#define BTN_TRIGGER_HAPPY33 0x2e0 -#define BTN_TRIGGER_HAPPY34 0x2e1 -#define BTN_TRIGGER_HAPPY35 0x2e2 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY36 0x2e3 -#define BTN_TRIGGER_HAPPY37 0x2e4 -#define BTN_TRIGGER_HAPPY38 0x2e5 -#define BTN_TRIGGER_HAPPY39 0x2e6 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BTN_TRIGGER_HAPPY40 0x2e7 -#define KEY_MIN_INTERESTING KEY_MUTE -#define KEY_MAX 0x2ff -#define KEY_CNT (KEY_MAX+1) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define REL_X 0x00 -#define REL_Y 0x01 -#define REL_Z 0x02 -#define REL_RX 0x03 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define REL_RY 0x04 -#define REL_RZ 0x05 -#define REL_HWHEEL 0x06 -#define REL_DIAL 0x07 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define REL_WHEEL 0x08 -#define REL_MISC 0x09 -#define REL_MAX 0x0f -#define REL_CNT (REL_MAX+1) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_X 0x00 -#define ABS_Y 0x01 -#define ABS_Z 0x02 -#define ABS_RX 0x03 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_RY 0x04 -#define ABS_RZ 0x05 -#define ABS_THROTTLE 0x06 -#define ABS_RUDDER 0x07 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_WHEEL 0x08 -#define ABS_GAS 0x09 -#define ABS_BRAKE 0x0a -#define ABS_HAT0X 0x10 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_HAT0Y 0x11 -#define ABS_HAT1X 0x12 -#define ABS_HAT1Y 0x13 -#define ABS_HAT2X 0x14 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_HAT2Y 0x15 -#define ABS_HAT3X 0x16 -#define ABS_HAT3Y 0x17 -#define ABS_PRESSURE 0x18 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_DISTANCE 0x19 -#define ABS_TILT_X 0x1a -#define ABS_TILT_Y 0x1b -#define ABS_TOOL_WIDTH 0x1c -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_VOLUME 0x20 -#define ABS_MISC 0x28 -#define ABS_MT_SLOT 0x2f -#define ABS_MT_TOUCH_MAJOR 0x30 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_MT_TOUCH_MINOR 0x31 -#define ABS_MT_WIDTH_MAJOR 0x32 -#define ABS_MT_WIDTH_MINOR 0x33 -#define ABS_MT_ORIENTATION 0x34 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_MT_POSITION_X 0x35 -#define ABS_MT_POSITION_Y 0x36 -#define ABS_MT_TOOL_TYPE 0x37 -#define ABS_MT_BLOB_ID 0x38 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_MT_TRACKING_ID 0x39 -#define ABS_MT_PRESSURE 0x3a -#define ABS_MT_DISTANCE 0x3b -#define ABS_MAX 0x3f -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ABS_CNT (ABS_MAX+1) -#define SW_LID 0x00 -#define SW_TABLET_MODE 0x01 -#define SW_HEADPHONE_INSERT 0x02 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define SW_RFKILL_ALL 0x03 -#define SW_RADIO SW_RFKILL_ALL -#define SW_MICROPHONE_INSERT 0x04 -#define SW_DOCK 0x05 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define SW_LINEOUT_INSERT 0x06 -#define SW_JACK_PHYSICAL_INSERT 0x07 -#define SW_VIDEOOUT_INSERT 0x08 -#define SW_CAMERA_LENS_COVER 0x09 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define SW_KEYPAD_SLIDE 0x0a -#define SW_FRONT_PROXIMITY 0x0b -#define SW_ROTATE_LOCK 0x0c -#define SW_LINEIN_INSERT 0x0d -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define SW_HPHL_OVERCURRENT 0x0e -#define SW_HPHR_OVERCURRENT 0x0f -#define SW_UNSUPPORT_INSERT 0x10 -#define SW_MAX 0x20 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define SW_CNT (SW_MAX+1) -#define MSC_SERIAL 0x00 -#define MSC_PULSELED 0x01 -#define MSC_GESTURE 0x02 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define MSC_RAW 0x03 -#define MSC_SCAN 0x04 -#define MSC_MAX 0x07 -#define MSC_CNT (MSC_MAX+1) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define LED_NUML 0x00 -#define LED_CAPSL 0x01 -#define LED_SCROLLL 0x02 -#define LED_COMPOSE 0x03 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define LED_KANA 0x04 -#define LED_SLEEP 0x05 -#define LED_SUSPEND 0x06 -#define LED_MUTE 0x07 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define LED_MISC 0x08 -#define LED_MAIL 0x09 -#define LED_CHARGING 0x0a -#define LED_MAX 0x0f -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define LED_CNT (LED_MAX+1) -#define REP_DELAY 0x00 -#define REP_PERIOD 0x01 -#define REP_MAX 0x01 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define REP_CNT (REP_MAX+1) -#define SND_CLICK 0x00 -#define SND_BELL 0x01 -#define SND_TONE 0x02 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define SND_MAX 0x07 -#define SND_CNT (SND_MAX+1) -#define ID_BUS 0 -#define ID_VENDOR 1 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define ID_PRODUCT 2 -#define ID_VERSION 3 -#define BUS_PCI 0x01 -#define BUS_ISAPNP 0x02 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BUS_USB 0x03 -#define BUS_HIL 0x04 -#define BUS_BLUETOOTH 0x05 -#define BUS_VIRTUAL 0x06 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BUS_ISA 0x10 -#define BUS_I8042 0x11 -#define BUS_XTKBD 0x12 -#define BUS_RS232 0x13 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BUS_GAMEPORT 0x14 -#define BUS_PARPORT 0x15 -#define BUS_AMIGA 0x16 -#define BUS_ADB 0x17 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BUS_I2C 0x18 -#define BUS_HOST 0x19 -#define BUS_GSC 0x1A -#define BUS_ATARI 0x1B -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define BUS_SPI 0x1C -#define MT_TOOL_FINGER 0 -#define MT_TOOL_PEN 1 -#define MT_TOOL_MAX 1 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define FF_STATUS_STOPPED 0x00 -#define FF_STATUS_PLAYING 0x01 -#define FF_STATUS_MAX 0x01 -struct ff_replay { -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __u16 length; - __u16 delay; -}; -struct ff_trigger { -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __u16 button; - __u16 interval; -}; -struct ff_envelope { -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __u16 attack_length; - __u16 attack_level; - __u16 fade_length; - __u16 fade_level; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -}; -struct ff_constant_effect { - __s16 level; - struct ff_envelope envelope; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -}; -struct ff_ramp_effect { - __s16 start_level; - __s16 end_level; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - struct ff_envelope envelope; -}; -struct ff_condition_effect { - __u16 right_saturation; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __u16 left_saturation; - __s16 right_coeff; - __s16 left_coeff; - __u16 deadband; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __s16 center; -}; -struct ff_periodic_effect { - __u16 waveform; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - __u16 period; - __s16 magnitude; - __s16 offset; - __u16 phase; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - struct ff_envelope envelope; - __u32 custom_len; - __s16 __user *custom_data; -}; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -struct ff_rumble_effect { - __u16 strong_magnitude; - __u16 weak_magnitude; -}; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -struct ff_effect { - __u16 type; - __s16 id; - __u16 direction; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - struct ff_trigger trigger; - struct ff_replay replay; - union { - struct ff_constant_effect constant; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - struct ff_ramp_effect ramp; - struct ff_periodic_effect periodic; - struct ff_condition_effect condition[2]; - struct ff_rumble_effect rumble; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ - } u; -}; -#define FF_RUMBLE 0x50 -#define FF_PERIODIC 0x51 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define FF_CONSTANT 0x52 -#define FF_SPRING 0x53 -#define FF_FRICTION 0x54 -#define FF_DAMPER 0x55 -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define FF_INERTIA 0x56 -#define FF_RAMP 0x57 -#define FF_EFFECT_MIN FF_RUMBLE -#define FF_EFFECT_MAX FF_RAMP -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define FF_SQUARE 0x58 -#define FF_TRIANGLE 0x59 -#define FF_SINE 0x5a -#define FF_SAW_UP 0x5b -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define FF_SAW_DOWN 0x5c -#define FF_CUSTOM 0x5d -#define FF_WAVEFORM_MIN FF_SQUARE -#define FF_WAVEFORM_MAX FF_CUSTOM -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#define FF_GAIN 0x60 -#define FF_AUTOCENTER 0x61 -#define FF_MAX 0x7f -#define FF_CNT (FF_MAX+1) -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ -#endif diff --git a/widget/gonk/libui/sha1.c b/widget/gonk/libui/sha1.c deleted file mode 100644 index 40a4ecaa3..000000000 --- a/widget/gonk/libui/sha1.c +++ /dev/null @@ -1,289 +0,0 @@ -/* $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $ */ -/* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ - -/* - * SHA-1 in C - * By Steve Reid <steve@edmweb.com> - * 100% Public Domain - * - * Test Vectors (from FIPS PUB 180-1) - * "abc" - * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D - * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 - * A million repetitions of "a" - * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F - */ - -#define SHA1HANDSOFF /* Copies data before messing with it. */ - -#include <sys/cdefs.h> - -#if defined(_KERNEL) || defined(_STANDALONE) -__KERNEL_RCSID(0, "$NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $"); - -#include <lib/libkern/libkern.h> - -#else - -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $"); -#endif /* LIBC_SCCS and not lint */ - -#include <assert.h> -#include <string.h> - -#endif - -#include <sys/types.h> -#include "sha1.h" - -#define _DIAGASSERT assert - -#if HAVE_NBTOOL_CONFIG_H -#include "nbtool_config.h" -#endif - -#if !HAVE_SHA1_H - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* - * blk0() and blk() perform the initial expand. - * I got the idea of expanding during the round function from SSLeay - */ -#if BYTE_ORDER == LITTLE_ENDIAN -# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) -#else -# define blk0(i) block->l[i] -#endif -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* - * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 - */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -#if !defined(_KERNEL) && !defined(_STANDALONE) -#if defined(__weak_alias) -__weak_alias(SHA1Transform,_SHA1Transform) -__weak_alias(SHA1Init,_SHA1Init) -__weak_alias(SHA1Update,_SHA1Update) -__weak_alias(SHA1Final,_SHA1Final) -#endif -#endif - -typedef union { - uint8_t c[64]; - uint32_t l[16]; -} CHAR64LONG16; - -/* old sparc64 gcc could not compile this */ -#undef SPARC64_GCC_WORKAROUND -#if defined(__sparc64__) && defined(__GNUC__) && __GNUC__ < 3 -#define SPARC64_GCC_WORKAROUND -#endif - -#ifdef SPARC64_GCC_WORKAROUND -void do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); -void do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); -void do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); -void do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); - -#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i) -#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i) -#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i) -#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i) -#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i) - -void -do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) -{ - nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); nR0(c,d,e,a,b, 3); - nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); - nR0(c,d,e,a,b, 8); nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11); - nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); nR0(a,b,c,d,e,15); - nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19); -} - -void -do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) -{ - nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); nR2(c,d,e,a,b,23); - nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); - nR2(c,d,e,a,b,28); nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31); - nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); nR2(a,b,c,d,e,35); - nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39); -} - -void -do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) -{ - nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); nR3(c,d,e,a,b,43); - nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); - nR3(c,d,e,a,b,48); nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51); - nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); nR3(a,b,c,d,e,55); - nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59); -} - -void -do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) -{ - nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); nR4(c,d,e,a,b,63); - nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); - nR4(c,d,e,a,b,68); nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71); - nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); nR4(a,b,c,d,e,75); - nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79); -} -#endif - -/* - * Hash a single 512-bit block. This is the core of the algorithm. - */ -void SHA1Transform(uint32_t state[5], const uint8_t buffer[64]) -{ - uint32_t a, b, c, d, e; - CHAR64LONG16 *block; - -#ifdef SHA1HANDSOFF - CHAR64LONG16 workspace; -#endif - - _DIAGASSERT(buffer != 0); - _DIAGASSERT(state != 0); - -#ifdef SHA1HANDSOFF - block = &workspace; - (void)memcpy(block, buffer, 64); -#else - block = (CHAR64LONG16 *)(void *)buffer; -#endif - - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - -#ifdef SPARC64_GCC_WORKAROUND - do_R01(&a, &b, &c, &d, &e, block); - do_R2(&a, &b, &c, &d, &e, block); - do_R3(&a, &b, &c, &d, &e, block); - do_R4(&a, &b, &c, &d, &e, block); -#else - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); -#endif - - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - - /* Wipe variables */ - a = b = c = d = e = 0; -} - - -/* - * SHA1Init - Initialize new context - */ -void SHA1Init(SHA1_CTX *context) -{ - - _DIAGASSERT(context != 0); - - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* - * Run your data through this. - */ -void SHA1Update(SHA1_CTX *context, const uint8_t *data, unsigned int len) -{ - unsigned int i, j; - - _DIAGASSERT(context != 0); - _DIAGASSERT(data != 0); - - j = context->count[0]; - if ((context->count[0] += len << 3) < j) - context->count[1] += (len>>29)+1; - j = (j >> 3) & 63; - if ((j + len) > 63) { - (void)memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) - SHA1Transform(context->state, &data[i]); - j = 0; - } else { - i = 0; - } - (void)memcpy(&context->buffer[j], &data[i], len - i); -} - - -/* - * Add padding and return the message digest. - */ -void SHA1Final(uint8_t digest[20], SHA1_CTX *context) -{ - unsigned int i; - uint8_t finalcount[8]; - - _DIAGASSERT(digest != 0); - _DIAGASSERT(context != 0); - - for (i = 0; i < 8; i++) { - finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1Update(context, (const uint8_t *)"\200", 1); - while ((context->count[0] & 504) != 448) - SHA1Update(context, (const uint8_t *)"\0", 1); - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - - if (digest) { - for (i = 0; i < 20; i++) - digest[i] = (uint8_t) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } -} - -#endif /* HAVE_SHA1_H */ diff --git a/widget/gonk/libui/sha1.h b/widget/gonk/libui/sha1.h deleted file mode 100644 index f7ada46a5..000000000 --- a/widget/gonk/libui/sha1.h +++ /dev/null @@ -1,31 +0,0 @@ -/* $NetBSD: sha1.h,v 1.13 2005/12/26 18:41:36 perry Exp $ */ - -/* - * SHA-1 in C - * By Steve Reid <steve@edmweb.com> - * 100% Public Domain - */ - -#ifndef _SYS_SHA1_H_ -#define _SYS_SHA1_H_ - -#include <sys/cdefs.h> -#include <sys/types.h> - -#define SHA1_DIGEST_LENGTH 20 -#define SHA1_DIGEST_STRING_LENGTH 41 - -typedef struct { - uint32_t state[5]; - uint32_t count[2]; - u_char buffer[64]; -} SHA1_CTX; - -__BEGIN_DECLS -void SHA1Transform(uint32_t[5], const u_char[64]); -void SHA1Init(SHA1_CTX *); -void SHA1Update(SHA1_CTX *, const u_char *, u_int); -void SHA1Final(u_char[SHA1_DIGEST_LENGTH], SHA1_CTX *); -__END_DECLS - -#endif /* _SYS_SHA1_H_ */ |