diff options
Diffstat (limited to 'services')
25 files changed, 4105 insertions, 2434 deletions
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index b03649e..e193be0 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -350,10 +350,9 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, dataCallbackTimestamp, (void *)cameraId); - // Enable zoom, error, and focus messages by default - enableMsgType(CAMERA_MSG_ERROR | - CAMERA_MSG_ZOOM | - CAMERA_MSG_FOCUS); + // Enable zoom, error, focus, and metadata messages by default + enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS | + CAMERA_MSG_PREVIEW_METADATA); // Callback is disabled by default mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP; @@ -460,10 +459,10 @@ status_t CameraService::Client::connect(const sp<ICameraClient>& client) { static void disconnectWindow(const sp<ANativeWindow>& window) { if (window != 0) { - status_t result = native_window_disconnect(window.get(), + status_t result = native_window_api_disconnect(window.get(), NATIVE_WINDOW_API_CAMERA); if (result != NO_ERROR) { - LOGW("native_window_disconnect failed: %s (%d)", strerror(-result), + LOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result), result); } } @@ -526,9 +525,9 @@ status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder, } if (window != 0) { - result = native_window_connect(window.get(), NATIVE_WINDOW_API_CAMERA); + result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA); if (result != NO_ERROR) { - LOGE("native_window_connect failed: %s (%d)", strerror(-result), + LOGE("native_window_api_connect failed: %s (%d)", strerror(-result), result); return result; } @@ -995,15 +994,15 @@ void CameraService::Client::dataCallback(int32_t msgType, if (client == 0) return; if (!client->lockIfMessageWanted(msgType)) return; - if (dataPtr == 0) { + if (dataPtr == 0 && metadata == NULL) { LOGE("Null data returned in data callback"); client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); return; } - switch (msgType) { + switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) { case CAMERA_MSG_PREVIEW_FRAME: - client->handlePreviewData(dataPtr); + client->handlePreviewData(msgType, dataPtr, metadata); break; case CAMERA_MSG_POSTVIEW_FRAME: client->handlePostview(dataPtr); @@ -1015,7 +1014,7 @@ void CameraService::Client::dataCallback(int32_t msgType, client->handleCompressedPicture(dataPtr); break; default: - client->handleGenericData(msgType, dataPtr); + client->handleGenericData(msgType, dataPtr, metadata); break; } } @@ -1055,7 +1054,9 @@ void CameraService::Client::handleShutter(void) { } // preview callback - frame buffer update -void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) { +void CameraService::Client::handlePreviewData(int32_t msgType, + const sp<IMemory>& mem, + camera_frame_metadata_t *metadata) { ssize_t offset; size_t size; sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); @@ -1087,11 +1088,11 @@ void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) { // Is the received frame copied out or not? if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) { LOG2("frame is copied"); - copyFrameAndPostCopiedFrame(c, heap, offset, size); + copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata); } else { LOG2("frame is forwarded"); mLock.unlock(); - c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem); + c->dataCallback(msgType, mem, metadata); } } else { mLock.unlock(); @@ -1105,7 +1106,7 @@ void CameraService::Client::handlePostview(const sp<IMemory>& mem) { sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { - c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem); + c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL); } } @@ -1120,7 +1121,7 @@ void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) { sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { - c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem); + c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL); } } @@ -1131,7 +1132,7 @@ void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) { sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { - c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem); + c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL); } } @@ -1146,11 +1147,11 @@ void CameraService::Client::handleGenericNotify(int32_t msgType, } void CameraService::Client::handleGenericData(int32_t msgType, - const sp<IMemory>& dataPtr) { + const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { - c->dataCallback(msgType, dataPtr); + c->dataCallback(msgType, dataPtr, metadata); } } @@ -1164,8 +1165,9 @@ void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp, } void CameraService::Client::copyFrameAndPostCopiedFrame( - const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, - size_t offset, size_t size) { + int32_t msgType, const sp<ICameraClient>& client, + const sp<IMemoryHeap>& heap, size_t offset, size_t size, + camera_frame_metadata_t *metadata) { LOG2("copyFrameAndPostCopiedFrame"); // It is necessary to copy out of pmem before sending this to // the callback. For efficiency, reuse the same MemoryHeapBase @@ -1197,7 +1199,7 @@ void CameraService::Client::copyFrameAndPostCopiedFrame( } mLock.unlock(); - client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame); + client->dataCallback(msgType, frame, metadata); } int CameraService::Client::getOrientation(int degrees, bool mirror) { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index af7f06e..57abf83 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -147,18 +147,22 @@ private: static sp<Client> getClientFromCookie(void* user); // handlers for messages void handleShutter(void); - void handlePreviewData(const sp<IMemory>& mem); + void handlePreviewData(int32_t msgType, const sp<IMemory>& mem, + camera_frame_metadata_t *metadata); void handlePostview(const sp<IMemory>& mem); void handleRawPicture(const sp<IMemory>& mem); void handleCompressedPicture(const sp<IMemory>& mem); void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2); - void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr); + void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr, + camera_frame_metadata_t *metadata); void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); void copyFrameAndPostCopiedFrame( + int32_t msgType, const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, - size_t offset, size_t size); + size_t offset, size_t size, + camera_frame_metadata_t *metadata); int getOrientation(int orientation, bool mirror); diff --git a/services/input/Android.mk b/services/input/Android.mk index e36507a..afbe546 100644 --- a/services/input/Android.mk +++ b/services/input/Android.mk @@ -19,6 +19,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ EventHub.cpp \ InputDispatcher.cpp \ + InputListener.cpp \ InputManager.cpp \ InputReader.cpp \ InputWindow.cpp \ diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index af13945..ce9e14f 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -2550,16 +2550,16 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet return splitMotionEntry; } -void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) { +void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS - LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime); + LOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime); #endif bool needWake; { // acquire lock AutoMutex _l(mLock); - ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(eventTime); + ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime); needWake = enqueueInboundEventLocked(newEntry); } // release lock @@ -2568,19 +2568,21 @@ void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) { } } -void InputDispatcher::notifyKey(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) { +void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS LOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, " "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld", - eventTime, deviceId, source, policyFlags, action, flags, - keyCode, scanCode, metaState, downTime); + args->eventTime, args->deviceId, args->source, args->policyFlags, + args->action, args->flags, args->keyCode, args->scanCode, + args->metaState, args->downTime); #endif - if (! validateKeyEvent(action)) { + 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; @@ -2604,8 +2606,9 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t so policyFlags |= POLICY_FLAG_TRUSTED; KeyEvent event; - event.initialize(deviceId, source, action, flags, keyCode, scanCode, - metaState, 0, downTime, eventTime); + event.initialize(args->deviceId, args->source, args->action, + flags, args->keyCode, args->scanCode, metaState, 0, + args->downTime, args->eventTime); mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); @@ -2629,9 +2632,10 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t so } int32_t repeatCount = 0; - KeyEntry* newEntry = new KeyEntry(eventTime, - deviceId, source, policyFlags, action, flags, keyCode, scanCode, - metaState, repeatCount, downTime); + 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(); @@ -2642,43 +2646,39 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t so } } -void InputDispatcher::notifyMotion(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, - uint32_t pointerCount, const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords, - float xPrecision, float yPrecision, nsecs_t downTime) { +void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, " "xPrecision=%f, yPrecision=%f, downTime=%lld", - eventTime, deviceId, source, policyFlags, action, flags, - metaState, buttonState, edgeFlags, - xPrecision, yPrecision, downTime); - for (uint32_t i = 0; i < pointerCount; i++) { + 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++) { LOGD(" 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, pointerProperties[i].id, - pointerProperties[i].toolType, - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y), - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE), - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), - pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); + 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(action, pointerCount, pointerProperties)) { + if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) { return; } + uint32_t policyFlags = args->policyFlags; policyFlags |= POLICY_FLAG_TRUSTED; - mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags); + mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags); bool needWake; { // acquire lock @@ -2688,10 +2688,11 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t mLock.unlock(); MotionEvent event; - event.initialize(deviceId, source, action, flags, edgeFlags, metaState, - buttonState, 0, 0, - xPrecision, yPrecision, downTime, eventTime, - pointerCount, pointerProperties, pointerCoords); + 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)) { @@ -2702,8 +2703,8 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t } // Attempt batching and streaming of move events. - if (action == AMOTION_EVENT_ACTION_MOVE - || action == AMOTION_EVENT_ACTION_HOVER_MOVE) { + if (args->action == AMOTION_EVENT_ACTION_MOVE + || args->action == AMOTION_EVENT_ACTION_HOVER_MOVE) { // BATCHING CASE // // Try to append a move sample to the tail of the inbound queue for this device. @@ -2716,20 +2717,22 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t } MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); - if (motionEntry->deviceId != deviceId - || motionEntry->source != source) { + if (motionEntry->deviceId != args->deviceId + || motionEntry->source != args->source) { // Keep looking for this device and source. continue; } - if (!motionEntry->canAppendSamples(action, pointerCount, pointerProperties)) { + if (!motionEntry->canAppendSamples(args->action, + args->pointerCount, args->pointerProperties)) { // Last motion event in the queue for this device and source is // not compatible for appending new samples. Stop here. goto NoBatchingOrStreaming; } // Do the batching magic. - batchMotionLocked(motionEntry, eventTime, metaState, pointerCoords, + batchMotionLocked(motionEntry, args->eventTime, + args->metaState, args->pointerCoords, "most recent motion event for this device and source in the inbound queue"); mLock.unlock(); return; // done! @@ -2744,15 +2747,18 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t && (!mPendingEvent->dispatchInProgress || !mCurrentInputTargetsValid) && mPendingEvent->type == EventEntry::TYPE_MOTION) { MotionEntry* motionEntry = static_cast<MotionEntry*>(mPendingEvent); - if (motionEntry->deviceId == deviceId && motionEntry->source == source) { - if (!motionEntry->canAppendSamples(action, pointerCount, pointerProperties)) { + if (motionEntry->deviceId == args->deviceId + && motionEntry->source == args->source) { + if (!motionEntry->canAppendSamples(args->action, + args->pointerCount, args->pointerProperties)) { // Pending motion event is for this device and source but it is // not compatible for appending new samples. Stop here. goto NoBatchingOrStreaming; } // Do the batching magic. - batchMotionLocked(motionEntry, eventTime, metaState, pointerCoords, + batchMotionLocked(motionEntry, args->eventTime, + args->metaState, args->pointerCoords, "pending motion event"); mLock.unlock(); return; // done! @@ -2799,16 +2805,16 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t MotionEntry* motionEntry = static_cast<MotionEntry*>( dispatchEntry->eventEntry); - if (motionEntry->action != action - || motionEntry->deviceId != deviceId - || motionEntry->source != source - || motionEntry->pointerCount != pointerCount + if (motionEntry->action != args->action + || motionEntry->deviceId != args->deviceId + || motionEntry->source != args->source + || motionEntry->pointerCount != args->pointerCount || motionEntry->isInjected()) { // The motion event is not compatible with this move. continue; } - if (action == AMOTION_EVENT_ACTION_HOVER_MOVE) { + if (args->action == AMOTION_EVENT_ACTION_HOVER_MOVE) { if (mLastHoverWindowHandle == NULL) { #if DEBUG_BATCHING LOGD("Not streaming hover move because there is no " @@ -2818,8 +2824,8 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t } sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked( - pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), - pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); + args->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), + args->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); if (mLastHoverWindowHandle != hoverWindowHandle) { #if DEBUG_BATCHING LOGD("Not streaming hover move because the last hovered window " @@ -2834,7 +2840,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t // Hurray! This foreground target is currently dispatching a move event // that we can stream onto. Append the motion sample and resume dispatch. - motionEntry->appendSample(eventTime, pointerCoords); + motionEntry->appendSample(args->eventTime, args->pointerCoords); #if DEBUG_BATCHING LOGD("Appended motion sample onto batch for most recently dispatched " "motion event for this device and source in the outbound queues. " @@ -2854,10 +2860,11 @@ NoBatchingOrStreaming:; } // Just enqueue a new motion event. - MotionEntry* newEntry = new MotionEntry(eventTime, - deviceId, source, policyFlags, action, flags, metaState, buttonState, edgeFlags, - xPrecision, yPrecision, downTime, - pointerCount, pointerProperties, pointerCoords); + 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->pointerCount, args->pointerProperties, args->pointerCoords); needWake = enqueueInboundEventLocked(newEntry); mLock.unlock(); @@ -2898,15 +2905,17 @@ void InputDispatcher::batchMotionLocked(MotionEntry* entry, nsecs_t eventTime, #endif } -void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue, - uint32_t policyFlags) { +void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS - LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x", - switchCode, switchValue, policyFlags); + LOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchCode=%d, switchValue=%d", + args->eventTime, args->policyFlags, + args->switchCode, args->switchValue); #endif + uint32_t policyFlags = args->policyFlags; policyFlags |= POLICY_FLAG_TRUSTED; - mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags); + mPolicy->notifySwitch(args->eventTime, + args->switchCode, args->switchValue, policyFlags); } int32_t InputDispatcher::injectInputEvent(const InputEvent* event, diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h index 1d39b2e..01c7b35 100644 --- a/services/input/InputDispatcher.h +++ b/services/input/InputDispatcher.h @@ -34,6 +34,7 @@ #include "InputWindow.h" #include "InputApplication.h" +#include "InputListener.h" namespace android { @@ -270,7 +271,7 @@ public: /* Notifies the system about input events generated by the input reader. * The dispatcher is expected to be mostly asynchronous. */ -class InputDispatcherInterface : public virtual RefBase { +class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface { protected: InputDispatcherInterface() { } virtual ~InputDispatcherInterface() { } @@ -288,23 +289,6 @@ public: */ virtual void dispatchOnce() = 0; - /* Notifies the dispatcher about new events. - * - * These methods should only be called on the input reader thread. - */ - virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0; - virtual void notifyKey(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) = 0; - virtual void notifyMotion(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, - uint32_t pointerCount, const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords, - float xPrecision, float yPrecision, nsecs_t downTime) = 0; - virtual void notifySwitch(nsecs_t when, - int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 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. @@ -389,18 +373,10 @@ public: virtual void dispatchOnce(); - virtual void notifyConfigurationChanged(nsecs_t eventTime); - virtual void notifyKey(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); - virtual void notifyMotion(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, - uint32_t pointerCount, const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords, - float xPrecision, float yPrecision, nsecs_t downTime); - virtual void notifySwitch(nsecs_t when, - int32_t switchCode, int32_t switchValue, uint32_t policyFlags) ; + 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 int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, diff --git a/services/input/InputListener.cpp b/services/input/InputListener.cpp new file mode 100644 index 0000000..4f9fe90 --- /dev/null +++ b/services/input/InputListener.cpp @@ -0,0 +1,162 @@ +/* + * 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, 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), 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), 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, + int32_t switchCode, int32_t switchValue) : + eventTime(eventTime), policyFlags(policyFlags), + switchCode(switchCode), switchValue(switchValue) { +} + +NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) : + eventTime(other.eventTime), policyFlags(other.policyFlags), + switchCode(other.switchCode), switchValue(other.switchValue) { +} + +void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const { + listener->notifySwitch(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::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/services/input/InputListener.h b/services/input/InputListener.h new file mode 100644 index 0000000..3fef132 --- /dev/null +++ b/services/input/InputListener.h @@ -0,0 +1,175 @@ +/* + * 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 <ui/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; + 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, 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; + int32_t switchCode; + int32_t switchValue; + + inline NotifySwitchArgs() { } + + NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags, + int32_t switchCode, int32_t switchValue); + + NotifySwitchArgs(const NotifySwitchArgs& other); + + virtual ~NotifySwitchArgs() { } + + 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; +}; + + +/* + * 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); + + void flush(); + +private: + sp<InputListenerInterface> mInnerListener; + Vector<NotifyArgs*> mArgsQueue; +}; + +} // namespace android + +#endif // _UI_INPUT_LISTENER_H diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index db312ad..8786c24 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -180,8 +180,9 @@ static void synthesizeButtonKey(InputReaderContext* context, int32_t action, || (action == AKEY_EVENT_ACTION_UP && (lastButtonState & buttonState) && !(currentButtonState & buttonState))) { - context->getDispatcher()->notifyKey(when, deviceId, source, policyFlags, + NotifyKeyArgs args(when, deviceId, source, policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when); + context->getListener()->notifyKey(&args); } } @@ -201,13 +202,19 @@ static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, - const sp<InputDispatcherInterface>& dispatcher) : - mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher), + const sp<InputListenerInterface>& listener) : + mContext(this), mEventHub(eventHub), mPolicy(policy), mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), mConfigurationChangesToRefresh(0) { - refreshConfiguration(0); - updateGlobalMetaState(); - updateInputConfiguration(); + mQueuedListener = new QueuedInputListener(listener); + + { // acquire lock + AutoMutex _l(mLock); + + refreshConfigurationLocked(0); + updateGlobalMetaStateLocked(); + updateInputConfigurationLocked(); + } // release lock } InputReader::~InputReader() { @@ -217,39 +224,52 @@ InputReader::~InputReader() { } void InputReader::loopOnce() { - uint32_t changes; + int32_t timeoutMillis; { // acquire lock - AutoMutex _l(mStateLock); + AutoMutex _l(mLock); + + uint32_t changes = mConfigurationChangesToRefresh; + if (changes) { + mConfigurationChangesToRefresh = 0; + refreshConfigurationLocked(changes); + } - changes = mConfigurationChangesToRefresh; - mConfigurationChangesToRefresh = 0; + timeoutMillis = -1; + if (mNextTimeout != LLONG_MAX) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); + } } // release lock - if (changes) { - refreshConfiguration(changes); - } + size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); - int32_t timeoutMillis = -1; - if (mNextTimeout != LLONG_MAX) { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); - } + { // acquire lock + AutoMutex _l(mLock); - size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); - if (count) { - processEvents(mEventBuffer, count); - } - if (!count || timeoutMillis == 0) { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + if (count) { + processEventsLocked(mEventBuffer, count); + } + if (!count || timeoutMillis == 0) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); #if DEBUG_RAW_EVENTS - LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f); + LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f); #endif - mNextTimeout = LLONG_MAX; - timeoutExpired(now); - } + mNextTimeout = LLONG_MAX; + timeoutExpiredLocked(now); + } + } // release lock + + // 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::processEvents(const RawEvent* rawEvents, size_t count) { +void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) { for (const RawEvent* rawEvent = rawEvents; count;) { int32_t type = rawEvent->type; size_t batchSize = 1; @@ -265,17 +285,17 @@ void InputReader::processEvents(const RawEvent* rawEvents, size_t count) { #if DEBUG_RAW_EVENTS LOGD("BatchSize: %d Count: %d", batchSize, count); #endif - processEventsForDevice(deviceId, rawEvent, batchSize); + processEventsForDeviceLocked(deviceId, rawEvent, batchSize); } else { switch (rawEvent->type) { case EventHubInterface::DEVICE_ADDED: - addDevice(rawEvent->deviceId); + addDeviceLocked(rawEvent->deviceId); break; case EventHubInterface::DEVICE_REMOVED: - removeDevice(rawEvent->deviceId); + removeDeviceLocked(rawEvent->deviceId); break; case EventHubInterface::FINISHED_DEVICE_SCAN: - handleConfigurationChanged(rawEvent->when); + handleConfigurationChangedLocked(rawEvent->when); break; default: LOG_ASSERT(false); // can't happen @@ -287,11 +307,11 @@ void InputReader::processEvents(const RawEvent* rawEvents, size_t count) { } } -void InputReader::addDevice(int32_t deviceId) { +void InputReader::addDeviceLocked(int32_t deviceId) { String8 name = mEventHub->getDeviceName(deviceId); uint32_t classes = mEventHub->getDeviceClasses(deviceId); - InputDevice* device = createDevice(deviceId, name, classes); + InputDevice* device = createDeviceLocked(deviceId, name, classes); device->configure(&mConfig, 0); if (device->isIgnored()) { @@ -301,39 +321,23 @@ void InputReader::addDevice(int32_t deviceId) { device->getSources()); } - bool added = false; - { // acquire device registry writer lock - RWLock::AutoWLock _wl(mDeviceRegistryLock); - - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex < 0) { - mDevices.add(deviceId, device); - added = true; - } - } // release device registry writer lock - - if (! added) { + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); + if (deviceIndex < 0) { + mDevices.add(deviceId, device); + } else { LOGW("Ignoring spurious device added event for deviceId %d.", deviceId); delete device; return; } } -void InputReader::removeDevice(int32_t deviceId) { - bool removed = false; +void InputReader::removeDeviceLocked(int32_t deviceId) { InputDevice* device = NULL; - { // acquire device registry writer lock - RWLock::AutoWLock _wl(mDeviceRegistryLock); - - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex >= 0) { - device = mDevices.valueAt(deviceIndex); - mDevices.removeItemsAt(deviceIndex, 1); - removed = true; - } - } // release device registry writer lock - - if (! removed) { + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); + if (deviceIndex >= 0) { + device = mDevices.valueAt(deviceIndex); + mDevices.removeItemsAt(deviceIndex, 1); + } else { LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId); return; } @@ -351,8 +355,9 @@ void InputReader::removeDevice(int32_t deviceId) { delete device; } -InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) { - InputDevice* device = new InputDevice(this, deviceId, name); +InputDevice* InputReader::createDeviceLocked(int32_t deviceId, + const String8& name, uint32_t classes) { + InputDevice* device = new InputDevice(&mContext, deviceId, name); // External devices. if (classes & INPUT_DEVICE_CLASS_EXTERNAL) { @@ -404,52 +409,45 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui return device; } -void InputReader::processEventsForDevice(int32_t deviceId, +void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count) { - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); - - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex < 0) { - LOGW("Discarding event for unknown deviceId %d.", deviceId); - return; - } + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); + if (deviceIndex < 0) { + LOGW("Discarding event for unknown deviceId %d.", deviceId); + return; + } - InputDevice* device = mDevices.valueAt(deviceIndex); - if (device->isIgnored()) { - //LOGD("Discarding event for ignored deviceId %d.", deviceId); - return; - } + InputDevice* device = mDevices.valueAt(deviceIndex); + if (device->isIgnored()) { + //LOGD("Discarding event for ignored deviceId %d.", deviceId); + return; + } - device->process(rawEvents, count); - } // release device registry reader lock + device->process(rawEvents, count); } -void InputReader::timeoutExpired(nsecs_t when) { - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); - - for (size_t i = 0; i < mDevices.size(); i++) { - InputDevice* device = mDevices.valueAt(i); - if (!device->isIgnored()) { - device->timeoutExpired(when); - } +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); } - } // release device registry reader lock + } } -void InputReader::handleConfigurationChanged(nsecs_t when) { +void InputReader::handleConfigurationChangedLocked(nsecs_t when) { // Reset global meta state because it depends on the list of all configured devices. - updateGlobalMetaState(); + updateGlobalMetaStateLocked(); // Update input configuration. - updateInputConfiguration(); + updateInputConfigurationLocked(); // Enqueue configuration changed. - mDispatcher->notifyConfigurationChanged(when); + NotifyConfigurationChangedArgs args(when); + mQueuedListener->notifyConfigurationChanged(&args); } -void InputReader::refreshConfiguration(uint32_t changes) { +void InputReader::refreshConfigurationLocked(uint32_t changes) { mPolicy->getReaderConfiguration(&mConfig); mEventHub->setExcludedDevices(mConfig.excludedDeviceNames); @@ -459,84 +457,60 @@ void InputReader::refreshConfiguration(uint32_t changes) { if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) { mEventHub->requestReopenDevices(); } else { - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); - - for (size_t i = 0; i < mDevices.size(); i++) { - InputDevice* device = mDevices.valueAt(i); - device->configure(&mConfig, changes); - } - } // release device registry reader lock - } - } -} - -void InputReader::updateGlobalMetaState() { - { // acquire state lock - AutoMutex _l(mStateLock); - - mGlobalMetaState = 0; - - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); - for (size_t i = 0; i < mDevices.size(); i++) { InputDevice* device = mDevices.valueAt(i); - mGlobalMetaState |= device->getMetaState(); + device->configure(&mConfig, changes); } - } // release device registry reader lock - } // release state lock + } + } } -int32_t InputReader::getGlobalMetaState() { - { // acquire state lock - AutoMutex _l(mStateLock); +void InputReader::updateGlobalMetaStateLocked() { + mGlobalMetaState = 0; - return mGlobalMetaState; - } // release state lock + for (size_t i = 0; i < mDevices.size(); i++) { + InputDevice* device = mDevices.valueAt(i); + mGlobalMetaState |= device->getMetaState(); + } } -void InputReader::updateInputConfiguration() { - { // acquire state lock - AutoMutex _l(mStateLock); - - int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH; - int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS; - int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV; - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); +int32_t InputReader::getGlobalMetaStateLocked() { + return mGlobalMetaState; +} - InputDeviceInfo deviceInfo; - for (size_t i = 0; i < mDevices.size(); i++) { - InputDevice* device = mDevices.valueAt(i); - device->getDeviceInfo(& deviceInfo); - uint32_t sources = deviceInfo.getSources(); +void InputReader::updateInputConfigurationLocked() { + int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH; + int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS; + int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV; + InputDeviceInfo deviceInfo; + for (size_t i = 0; i < mDevices.size(); i++) { + InputDevice* device = mDevices.valueAt(i); + device->getDeviceInfo(& deviceInfo); + uint32_t sources = deviceInfo.getSources(); - if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) { - touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER; - } - if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) { - navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL; - } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) { - navigationConfig = InputConfiguration::NAVIGATION_DPAD; - } - if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) { - keyboardConfig = InputConfiguration::KEYBOARD_QWERTY; - } - } - } // release device registry reader lock + if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) { + touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER; + } + if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) { + navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL; + } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) { + navigationConfig = InputConfiguration::NAVIGATION_DPAD; + } + if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) { + keyboardConfig = InputConfiguration::KEYBOARD_QWERTY; + } + } - mInputConfiguration.touchScreen = touchScreenConfig; - mInputConfiguration.keyboard = keyboardConfig; - mInputConfiguration.navigation = navigationConfig; - } // release state lock + mInputConfiguration.touchScreen = touchScreenConfig; + mInputConfiguration.keyboard = keyboardConfig; + mInputConfiguration.navigation = navigationConfig; } -void InputReader::disableVirtualKeysUntil(nsecs_t time) { +void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) { mDisableVirtualKeysTimeout = time; } -bool InputReader::shouldDropVirtualKey(nsecs_t now, +bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode) { if (now < mDisableVirtualKeysTimeout) { LOGI("Dropping virtual key from device %s because virtual keys are " @@ -550,153 +524,141 @@ bool InputReader::shouldDropVirtualKey(nsecs_t now, } } -void InputReader::fadePointer() { - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); - - for (size_t i = 0; i < mDevices.size(); i++) { - InputDevice* device = mDevices.valueAt(i); - device->fadePointer(); - } - } // release device registry reader lock +void InputReader::fadePointerLocked() { + for (size_t i = 0; i < mDevices.size(); i++) { + InputDevice* device = mDevices.valueAt(i); + device->fadePointer(); + } } -void InputReader::requestTimeoutAtTime(nsecs_t when) { +void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) { if (when < mNextTimeout) { mNextTimeout = when; } } void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) { - { // acquire state lock - AutoMutex _l(mStateLock); + AutoMutex _l(mLock); - *outConfiguration = mInputConfiguration; - } // release state lock + *outConfiguration = mInputConfiguration; } status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) { - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); + AutoMutex _l(mLock); - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex < 0) { - return NAME_NOT_FOUND; - } + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); + if (deviceIndex < 0) { + return NAME_NOT_FOUND; + } - InputDevice* device = mDevices.valueAt(deviceIndex); - if (device->isIgnored()) { - return NAME_NOT_FOUND; - } + InputDevice* device = mDevices.valueAt(deviceIndex); + if (device->isIgnored()) { + return NAME_NOT_FOUND; + } - device->getDeviceInfo(outDeviceInfo); - return OK; - } // release device registy reader lock + device->getDeviceInfo(outDeviceInfo); + return OK; } void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) { - outDeviceIds.clear(); + AutoMutex _l(mLock); - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); + outDeviceIds.clear(); - size_t numDevices = mDevices.size(); - for (size_t i = 0; i < numDevices; i++) { - InputDevice* device = mDevices.valueAt(i); - if (! device->isIgnored()) { - outDeviceIds.add(device->getId()); - } + size_t numDevices = mDevices.size(); + for (size_t i = 0; i < numDevices; i++) { + InputDevice* device = mDevices.valueAt(i); + if (!device->isIgnored()) { + outDeviceIds.add(device->getId()); } - } // release device registy reader lock + } } int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) { - return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState); + AutoMutex _l(mLock); + + return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState); } int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) { - return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState); + AutoMutex _l(mLock); + + return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState); } int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) { - return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState); + AutoMutex _l(mLock); + + return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState); } -int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code, +int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) { - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); - - int32_t result = AKEY_STATE_UNKNOWN; - if (deviceId >= 0) { - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex >= 0) { - InputDevice* device = mDevices.valueAt(deviceIndex); - if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { - result = (device->*getStateFunc)(sourceMask, code); - } + int32_t result = AKEY_STATE_UNKNOWN; + if (deviceId >= 0) { + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); + if (deviceIndex >= 0) { + InputDevice* device = mDevices.valueAt(deviceIndex); + if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { + result = (device->*getStateFunc)(sourceMask, code); } - } else { - size_t numDevices = mDevices.size(); - for (size_t i = 0; i < numDevices; i++) { - InputDevice* device = mDevices.valueAt(i); - if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { - result = (device->*getStateFunc)(sourceMask, code); - if (result >= AKEY_STATE_DOWN) { - return result; - } + } + } else { + size_t numDevices = mDevices.size(); + for (size_t i = 0; i < numDevices; i++) { + InputDevice* device = mDevices.valueAt(i); + if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { + result = (device->*getStateFunc)(sourceMask, code); + if (result >= AKEY_STATE_DOWN) { + return result; } } } - return result; - } // release device registy reader lock + } + 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 markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags); + return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags); } -bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes, - const int32_t* keyCodes, uint8_t* outFlags) { - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); - bool result = false; - if (deviceId >= 0) { - ssize_t deviceIndex = mDevices.indexOfKey(deviceId); - if (deviceIndex >= 0) { - InputDevice* device = mDevices.valueAt(deviceIndex); - if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { - result = device->markSupportedKeyCodes(sourceMask, - numCodes, keyCodes, outFlags); - } +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); - } + } + } else { + size_t numDevices = mDevices.size(); + for (size_t i = 0; i < numDevices; i++) { + InputDevice* device = mDevices.valueAt(i); + if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { + result |= device->markSupportedKeyCodes(sourceMask, + numCodes, keyCodes, outFlags); } } - return result; - } // release device registy reader lock + } + return result; } void InputReader::requestRefreshConfiguration(uint32_t changes) { - if (changes) { - bool needWake; - { // acquire lock - AutoMutex _l(mStateLock); + AutoMutex _l(mLock); - needWake = !mConfigurationChangesToRefresh; - mConfigurationChangesToRefresh |= changes; - } // release lock + if (changes) { + bool needWake = !mConfigurationChangesToRefresh; + mConfigurationChangesToRefresh |= changes; if (needWake) { mEventHub->wake(); @@ -705,18 +667,16 @@ void InputReader::requestRefreshConfiguration(uint32_t changes) { } void InputReader::dump(String8& dump) { + AutoMutex _l(mLock); + mEventHub->dump(dump); dump.append("\n"); dump.append("Input Reader State:\n"); - { // acquire device registry reader lock - RWLock::AutoRLock _rl(mDeviceRegistryLock); - - for (size_t i = 0; i < mDevices.size(); i++) { - mDevices.valueAt(i)->dump(dump); - } - } // release device registy reader lock + for (size_t i = 0; i < mDevices.size(); i++) { + mDevices.valueAt(i)->dump(dump); + } dump.append(INDENT "Configuration:\n"); dump.append(INDENT2 "ExcludedDeviceNames: ["); @@ -772,6 +732,56 @@ void InputReader::dump(String8& dump) { } +// --- 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); +} + +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) : @@ -1170,6 +1180,96 @@ bool TouchButtonAccumulator::isHovering() const { } +// --- 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(); + 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() { @@ -1298,6 +1398,10 @@ void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { 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; @@ -1338,8 +1442,8 @@ void MultiTouchMotionAccumulator::Slot::clear() { mAbsMTOrientation = 0; mAbsMTTrackingId = -1; mAbsMTPressure = 0; - mAbsMTToolType = 0; mAbsMTDistance = 0; + mAbsMTToolType = 0; } int32_t MultiTouchMotionAccumulator::Slot::getToolType() const { @@ -1404,6 +1508,10 @@ int32_t InputMapper::getMetaState() { void InputMapper::fadePointer() { } +status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) { + return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo); +} + void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump, const RawAbsoluteAxisInfo& axis, const char* name) { if (axis.valid) { @@ -1437,7 +1545,8 @@ void SwitchInputMapper::process(const RawEvent* rawEvent) { } void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) { - getDispatcher()->notifySwitch(when, switchCode, switchValue, 0); + NotifySwitchArgs args(when, 0, switchCode, switchValue); + getListener()->notifySwitch(&args); } int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) { @@ -1451,15 +1560,15 @@ KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType) : InputMapper(device), mSource(source), mKeyboardType(keyboardType) { - initializeLocked(); + initialize(); } KeyboardInputMapper::~KeyboardInputMapper() { } -void KeyboardInputMapper::initializeLocked() { - mLocked.metaState = AMETA_NONE; - mLocked.downTime = 0; +void KeyboardInputMapper::initialize() { + mMetaState = AMETA_NONE; + mDownTime = 0; } uint32_t KeyboardInputMapper::getSources() { @@ -1473,15 +1582,12 @@ void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { } void KeyboardInputMapper::dump(String8& dump) { - { // acquire lock - AutoMutex _l(mLock); - dump.append(INDENT2 "Keyboard Input Mapper:\n"); - dumpParameters(dump); - dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType); - dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size()); - dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState); - dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime); - } // release lock + dump.append(INDENT2 "Keyboard Input Mapper:\n"); + dumpParameters(dump); + dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType); + dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size()); + dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState); + dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime); } @@ -1493,10 +1599,7 @@ void KeyboardInputMapper::configure(const InputReaderConfiguration* config, uint configureParameters(); // Reset LEDs. - { - AutoMutex _l(mLock); - resetLedStateLocked(); - } + resetLedState(); } } @@ -1520,27 +1623,16 @@ void KeyboardInputMapper::dumpParameters(String8& dump) { } void KeyboardInputMapper::reset() { - for (;;) { - int32_t keyCode, scanCode; - { // acquire lock - AutoMutex _l(mLock); - - // Synthesize key up event on reset if keys are currently down. - if (mLocked.keyDowns.isEmpty()) { - initializeLocked(); - resetLedStateLocked(); - break; // done - } - - const KeyDown& keyDown = mLocked.keyDowns.top(); - keyCode = keyDown.keyCode; - scanCode = keyDown.scanCode; - } // release lock - + // Synthesize key up event on reset if keys are currently down. + while (!mKeyDowns.isEmpty()) { + const KeyDown& keyDown = mKeyDowns.top(); nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); - processKey(when, false, keyCode, scanCode, 0); + processKey(when, false, keyDown.keyCode, keyDown.scanCode, 0); } + initialize(); + resetLedState(); + InputMapper::reset(); getContext()->updateGlobalMetaState(); } @@ -1567,72 +1659,66 @@ bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) { void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) { - int32_t newMetaState; - nsecs_t downTime; - bool metaStateChanged = false; - - { // acquire lock - AutoMutex _l(mLock); - - if (down) { - // Rotate key codes according to orientation if needed. - // Note: getDisplayInfo is non-reentrant so we can continue holding the lock. - if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) { - int32_t orientation; - if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId, - false /*external*/, NULL, NULL, & orientation)) { - orientation = DISPLAY_ORIENTATION_0; - } - keyCode = rotateKeyCode(keyCode, orientation); + if (down) { + // Rotate key codes according to orientation if needed. + // Note: getDisplayInfo is non-reentrant so we can continue holding the lock. + if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) { + int32_t orientation; + if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId, + false /*external*/, NULL, NULL, & orientation)) { + orientation = DISPLAY_ORIENTATION_0; } - // Add key down. - ssize_t keyDownIndex = findKeyDownLocked(scanCode); - if (keyDownIndex >= 0) { - // key repeat, be sure to use same keycode as before in case of rotation - keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode; - } else { - // key down - if ((policyFlags & POLICY_FLAG_VIRTUAL) - && mContext->shouldDropVirtualKey(when, - getDevice(), keyCode, scanCode)) { - return; - } - - mLocked.keyDowns.push(); - KeyDown& keyDown = mLocked.keyDowns.editTop(); - keyDown.keyCode = keyCode; - keyDown.scanCode = scanCode; - } + keyCode = rotateKeyCode(keyCode, orientation); + } - mLocked.downTime = when; + // 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 { - // Remove key down. - ssize_t keyDownIndex = findKeyDownLocked(scanCode); - if (keyDownIndex >= 0) { - // key up, be sure to use same keycode as before in case of rotation - keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode; - mLocked.keyDowns.removeAt(size_t(keyDownIndex)); - } else { - // key was not actually down - LOGI("Dropping key up from device %s because the key was not down. " - "keyCode=%d, scanCode=%d", - getDeviceName().string(), keyCode, scanCode); + // 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; } - int32_t oldMetaState = mLocked.metaState; - newMetaState = updateMetaState(keyCode, down, oldMetaState); - if (oldMetaState != newMetaState) { - mLocked.metaState = newMetaState; - metaStateChanged = true; - updateLedStateLocked(false); + 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 + LOGI("Dropping key up from device %s because the key was not down. " + "keyCode=%d, scanCode=%d", + getDeviceName().string(), keyCode, scanCode); + return; } + } - downTime = mLocked.downTime; - } // release lock + 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. @@ -1652,15 +1738,16 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, getContext()->fadePointer(); } - getDispatcher()->notifyKey(when, getDeviceId(), mSource, policyFlags, + 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::findKeyDownLocked(int32_t scanCode) { - size_t n = mLocked.keyDowns.size(); +ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) { + size_t n = mKeyDowns.size(); for (size_t i = 0; i < n; i++) { - if (mLocked.keyDowns[i].scanCode == scanCode) { + if (mKeyDowns[i].scanCode == scanCode) { return i; } } @@ -1681,38 +1768,35 @@ bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numC } int32_t KeyboardInputMapper::getMetaState() { - { // acquire lock - AutoMutex _l(mLock); - return mLocked.metaState; - } // release lock + return mMetaState; } -void KeyboardInputMapper::resetLedStateLocked() { - initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL); - initializeLedStateLocked(mLocked.numLockLedState, LED_NUML); - initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL); +void KeyboardInputMapper::resetLedState() { + initializeLedState(mCapsLockLedState, LED_CAPSL); + initializeLedState(mNumLockLedState, LED_NUML); + initializeLedState(mScrollLockLedState, LED_SCROLLL); - updateLedStateLocked(true); + updateLedState(true); } -void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) { +void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) { ledState.avail = getEventHub()->hasLed(getDeviceId(), led); ledState.on = false; } -void KeyboardInputMapper::updateLedStateLocked(bool reset) { - updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL, +void KeyboardInputMapper::updateLedState(bool reset) { + updateLedStateForModifier(mCapsLockLedState, LED_CAPSL, AMETA_CAPS_LOCK_ON, reset); - updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML, + updateLedStateForModifier(mNumLockLedState, LED_NUML, AMETA_NUM_LOCK_ON, reset); - updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL, + updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL, AMETA_SCROLL_LOCK_ON, reset); } -void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState, +void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset) { if (ledState.avail) { - bool desiredState = (mLocked.metaState & modifier) != 0; + bool desiredState = (mMetaState & modifier) != 0; if (reset || ledState.on != desiredState) { getEventHub()->setLedState(getDeviceId(), led, desiredState); ledState.on = desiredState; @@ -1725,7 +1809,7 @@ void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& CursorInputMapper::CursorInputMapper(InputDevice* device) : InputMapper(device) { - initializeLocked(); + initialize(); } CursorInputMapper::~CursorInputMapper() { @@ -1759,24 +1843,21 @@ void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { } void CursorInputMapper::dump(String8& dump) { - { // acquire lock - AutoMutex _l(mLock); - 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(mCursorMotionAccumulator.haveRelativeVWheel())); - dump.appendFormat(INDENT3 "HaveHWheel: %s\n", - toString(mCursorMotionAccumulator.haveRelativeHWheel())); - dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale); - dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale); - dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState); - dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mLocked.buttonState))); - dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime); - } // release lock + 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(mCursorMotionAccumulator.haveRelativeVWheel())); + dump.appendFormat(INDENT3 "HaveHWheel: %s\n", + toString(mCursorMotionAccumulator.haveRelativeHWheel())); + dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale); + dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale); + 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(const InputReaderConfiguration* config, uint32_t changes) { @@ -1859,38 +1940,27 @@ void CursorInputMapper::dumpParameters(String8& dump) { toString(mParameters.orientationAware)); } -void CursorInputMapper::initializeLocked() { +void CursorInputMapper::initialize() { mCursorButtonAccumulator.clearButtons(); mCursorMotionAccumulator.clearRelativeAxes(); - mLocked.buttonState = 0; - mLocked.downTime = 0; + mButtonState = 0; + mDownTime = 0; } void CursorInputMapper::reset() { - for (;;) { - int32_t buttonState; - { // acquire lock - AutoMutex _l(mLock); - - buttonState = mLocked.buttonState; - if (!buttonState) { - initializeLocked(); - break; // done - } - } // release lock + // Reset velocity. + mPointerVelocityControl.reset(); + mWheelXVelocityControl.reset(); + mWheelYVelocityControl.reset(); - // Reset velocity. - mPointerVelocityControl.reset(); - mWheelXVelocityControl.reset(); - mWheelYVelocityControl.reset(); + // Synthesize button up event on reset. + nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); + mCursorButtonAccumulator.clearButtons(); + mCursorMotionAccumulator.clearRelativeAxes(); + sync(when); - // Synthesize button up event on reset. - nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); - mCursorButtonAccumulator.clearButtons(); - mCursorMotionAccumulator.clearRelativeAxes(); - sync(when); - } + initialize(); InputMapper::reset(); } @@ -1905,98 +1975,84 @@ void CursorInputMapper::process(const RawEvent* rawEvent) { } void CursorInputMapper::sync(nsecs_t when) { - int32_t motionEventAction; - int32_t lastButtonState, currentButtonState; - PointerProperties pointerProperties; - PointerCoords pointerCoords; - nsecs_t downTime; - float vscroll, hscroll; - { // acquire lock - AutoMutex _l(mLock); - - lastButtonState = mLocked.buttonState; - currentButtonState = mCursorButtonAccumulator.getButtonState(); - mLocked.buttonState = currentButtonState; - - bool wasDown = isPointerDown(lastButtonState); - bool down = isPointerDown(currentButtonState); - bool downChanged; - if (!wasDown && down) { - mLocked.downTime = when; - downChanged = true; - } else if (wasDown && !down) { - downChanged = true; - } else { - downChanged = false; - } - downTime = mLocked.downTime; - - 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; - } - - float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale; - float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale; + 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; - if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0 - && (deltaX != 0.0f || deltaY != 0.0f)) { - // Rotate motion based on display orientation if needed. - // Note: getDisplayInfo is non-reentrant so we can continue holding the lock. - int32_t orientation; - if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId, - false /*external*/, NULL, NULL, & orientation)) { - orientation = DISPLAY_ORIENTATION_0; - } + float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale; + float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale; + bool moved = deltaX != 0 || deltaY != 0; - rotateDelta(orientation, &deltaX, &deltaY); + if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0 + && (deltaX != 0.0f || deltaY != 0.0f)) { + // Rotate motion based on display orientation if needed. + // Note: getDisplayInfo is non-reentrant so we can continue holding the lock. + int32_t orientation; + if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId, + false /*external*/, NULL, NULL, & orientation)) { + orientation = DISPLAY_ORIENTATION_0; } - pointerProperties.clear(); - pointerProperties.id = 0; - pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE; + rotateDelta(orientation, &deltaX, &deltaY); + } - pointerCoords.clear(); + PointerProperties pointerProperties; + pointerProperties.clear(); + pointerProperties.id = 0; + pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE; - vscroll = mCursorMotionAccumulator.getRelativeVWheel(); - hscroll = mCursorMotionAccumulator.getRelativeHWheel(); + PointerCoords pointerCoords; + pointerCoords.clear(); - mWheelYVelocityControl.move(when, NULL, &vscroll); - mWheelXVelocityControl.move(when, &hscroll, NULL); + float vscroll = mCursorMotionAccumulator.getRelativeVWheel(); + float hscroll = mCursorMotionAccumulator.getRelativeHWheel(); + bool scrolled = vscroll != 0 || hscroll != 0; - mPointerVelocityControl.move(when, &deltaX, &deltaY); + mWheelYVelocityControl.move(when, NULL, &vscroll); + mWheelXVelocityControl.move(when, &hscroll, NULL); - if (mPointerController != NULL) { - if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0 - || currentButtonState != lastButtonState) { - mPointerController->setPresentation( - PointerControllerInterface::PRESENTATION_POINTER); + mPointerVelocityControl.move(when, &deltaX, &deltaY); - if (deltaX != 0 || deltaY != 0) { - mPointerController->move(deltaX, deltaY); - } + if (mPointerController != NULL) { + if (moved || scrolled || buttonsChanged) { + mPointerController->setPresentation( + PointerControllerInterface::PRESENTATION_POINTER); - if (currentButtonState != lastButtonState) { - mPointerController->setButtonState(currentButtonState); - } + if (moved) { + mPointerController->move(deltaX, deltaY); + } - mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); + if (buttonsChanged) { + mPointerController->setButtonState(currentButtonState); } - float x, y; - mPointerController->getPosition(&x, &y); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); - } else { - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); + mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); } - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); - } // release lock + float x, y; + mPointerController->getPosition(&x, &y); + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); + } else { + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); + } + + 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 @@ -2012,29 +2068,43 @@ void CursorInputMapper::sync(nsecs_t when) { policyFlags, lastButtonState, currentButtonState); // Send motion event. - int32_t metaState = mContext->getGlobalMetaState(); - getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags, - motionEventAction, 0, metaState, currentButtonState, 0, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); - - // Send hover move after UP to tell the application that the mouse is hovering now. - if (motionEventAction == AMOTION_EVENT_ACTION_UP - && mPointerController != NULL) { - getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_HOVER_MOVE, 0, - metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, + 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, 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, + 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + getListener()->notifyMotion(&hoverArgs); + } - // Send scroll events. - if (vscroll != 0 || hscroll != 0) { - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); + // Send scroll events. + if (scrolled) { + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags, - AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState, - AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags, + AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState, + AMOTION_EVENT_EDGE_FLAG_NONE, + 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + getListener()->notifyMotion(&scrollArgs); + } } // Synthesize key up from buttons if needed. @@ -2053,24 +2123,18 @@ int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCod } void CursorInputMapper::fadePointer() { - { // acquire lock - AutoMutex _l(mLock); - if (mPointerController != NULL) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - } - } // release lock + if (mPointerController != NULL) { + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); + } } // --- TouchInputMapper --- TouchInputMapper::TouchInputMapper(InputDevice* device) : - InputMapper(device) { - mLocked.surfaceOrientation = -1; - mLocked.surfaceWidth = -1; - mLocked.surfaceHeight = -1; - - initializeLocked(); + InputMapper(device), + mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) { + initialize(); } TouchInputMapper::~TouchInputMapper() { @@ -2083,126 +2147,148 @@ uint32_t TouchInputMapper::getSources() { void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { InputMapper::populateDeviceInfo(info); - { // acquire lock - AutoMutex _l(mLock); - - // Ensure surface information is up to date so that orientation changes are - // noticed immediately. - if (!configureSurfaceLocked()) { - return; - } + // Ensure surface information is up to date so that orientation changes are + // noticed immediately. + if (!configureSurface()) { + return; + } - info->addMotionRange(mLocked.orientedRanges.x); - info->addMotionRange(mLocked.orientedRanges.y); + info->addMotionRange(mOrientedRanges.x); + info->addMotionRange(mOrientedRanges.y); - if (mLocked.orientedRanges.havePressure) { - info->addMotionRange(mLocked.orientedRanges.pressure); - } + if (mOrientedRanges.havePressure) { + info->addMotionRange(mOrientedRanges.pressure); + } - if (mLocked.orientedRanges.haveSize) { - info->addMotionRange(mLocked.orientedRanges.size); - } + if (mOrientedRanges.haveSize) { + info->addMotionRange(mOrientedRanges.size); + } - if (mLocked.orientedRanges.haveTouchSize) { - info->addMotionRange(mLocked.orientedRanges.touchMajor); - info->addMotionRange(mLocked.orientedRanges.touchMinor); - } + if (mOrientedRanges.haveTouchSize) { + info->addMotionRange(mOrientedRanges.touchMajor); + info->addMotionRange(mOrientedRanges.touchMinor); + } - if (mLocked.orientedRanges.haveToolSize) { - info->addMotionRange(mLocked.orientedRanges.toolMajor); - info->addMotionRange(mLocked.orientedRanges.toolMinor); - } + if (mOrientedRanges.haveToolSize) { + info->addMotionRange(mOrientedRanges.toolMajor); + info->addMotionRange(mOrientedRanges.toolMinor); + } - if (mLocked.orientedRanges.haveOrientation) { - info->addMotionRange(mLocked.orientedRanges.orientation); - } + if (mOrientedRanges.haveOrientation) { + info->addMotionRange(mOrientedRanges.orientation); + } - if (mLocked.orientedRanges.haveDistance) { - info->addMotionRange(mLocked.orientedRanges.distance); - } + if (mOrientedRanges.haveDistance) { + info->addMotionRange(mOrientedRanges.distance); + } - if (mPointerController != NULL) { - float minX, minY, maxX, maxY; - if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) { - info->addMotionRange(AMOTION_EVENT_AXIS_X, mPointerSource, - minX, maxX, 0.0f, 0.0f); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, mPointerSource, - minY, maxY, 0.0f, 0.0f); - } - info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mPointerSource, - 0.0f, 1.0f, 0.0f, 0.0f); + if (mPointerController != NULL) { + float minX, minY, maxX, maxY; + if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) { + info->addMotionRange(AMOTION_EVENT_AXIS_X, mPointerSource, + minX, maxX, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_Y, mPointerSource, + minY, maxY, 0.0f, 0.0f); } - } // release lock + info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mPointerSource, + 0.0f, 1.0f, 0.0f, 0.0f); + } } void TouchInputMapper::dump(String8& dump) { - { // acquire lock - AutoMutex _l(mLock); - dump.append(INDENT2 "Touch Input Mapper:\n"); - dumpParameters(dump); - dumpVirtualKeysLocked(dump); - dumpRawAxes(dump); - dumpCalibration(dump); - dumpSurfaceLocked(dump); - - dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n"); - dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale); - dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale); - dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision); - dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision); - dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale); - dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale); - dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias); - dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale); - dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias); - dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale); - dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale); - dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mLocked.orientationScale); - dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mLocked.distanceScale); - - dump.appendFormat(INDENT3 "Last Touch:\n"); - dump.appendFormat(INDENT4 "Button State: 0x%08x\n", mLastTouch.buttonState); - dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount); - for (uint32_t i = 0; i < mLastTouch.pointerCount; i++) { - const PointerData& pointer = mLastTouch.pointers[i]; - dump.appendFormat(INDENT5 "[%d]: id=%d, x=%d, y=%d, pressure=%d, " - "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, " - "orientation=%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.distance, - pointer.toolType, toString(pointer.isHovering)); - } - - if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { - dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n"); - dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n", - mLocked.pointerGestureXMovementScale); - dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n", - mLocked.pointerGestureYMovementScale); - dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n", - mLocked.pointerGestureXZoomScale); - dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n", - mLocked.pointerGestureYZoomScale); - dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n", - mLocked.pointerGestureMaxSwipeWidth); - } - } // release lock -} - -void TouchInputMapper::initializeLocked() { - mCurrentTouch.clear(); - mLastTouch.clear(); + 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 "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 "ToolSizeLinearScale: %0.3f\n", mToolSizeLinearScale); + dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mToolSizeLinearBias); + dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mToolSizeAreaScale); + dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mToolSizeAreaBias); + 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(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, 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.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, 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_DISTANCE), + pointerProperties.toolType, + toString(mLastCookedPointerData.isHovering(i))); + } + + if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { + dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n"); + dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n", + mPointerGestureXMovementScale); + dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n", + mPointerGestureYMovementScale); + dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n", + mPointerGestureXZoomScale); + dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n", + mPointerGestureYZoomScale); + dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n", + mPointerGestureMaxSwipeWidth); + } +} + +void TouchInputMapper::initialize() { + mCurrentRawPointerData.clear(); + mLastRawPointerData.clear(); + mCurrentCookedPointerData.clear(); + mLastCookedPointerData.clear(); + mCurrentButtonState = 0; + mLastButtonState = 0; + mSentHoverEnter = false; mDownTime = 0; - mLocked.currentVirtualKey.down = false; + mCurrentVirtualKey.down = false; - mLocked.orientedRanges.havePressure = false; - mLocked.orientedRanges.haveSize = false; - mLocked.orientedRanges.haveTouchSize = false; - mLocked.orientedRanges.haveToolSize = false; - mLocked.orientedRanges.haveOrientation = false; - mLocked.orientedRanges.haveDistance = false; + mOrientedRanges.havePressure = false; + mOrientedRanges.haveSize = false; + mOrientedRanges.haveTouchSize = false; + mOrientedRanges.haveToolSize = false; + mOrientedRanges.haveOrientation = false; + mOrientedRanges.haveDistance = false; mPointerGesture.reset(); } @@ -2235,18 +2321,14 @@ void TouchInputMapper::configure(const InputReaderConfiguration* config, uint32_ } // Configure absolute axis information. - configureRawAxes(); + configureRawPointerAxes(); // Prepare input device calibration. parseCalibration(); resolveCalibration(); - { // acquire lock - AutoMutex _l(mLock); - - // Configure surface dimensions and orientation. - configureSurfaceLocked(); - } // release lock + // Configure surface dimensions and orientation. + configureSurface(); } if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { @@ -2359,38 +2441,28 @@ void TouchInputMapper::dumpParameters(String8& dump) { toString(mParameters.orientationAware)); } -void TouchInputMapper::configureRawAxes() { - mRawAxes.x.clear(); - mRawAxes.y.clear(); - mRawAxes.pressure.clear(); - mRawAxes.touchMajor.clear(); - mRawAxes.touchMinor.clear(); - mRawAxes.toolMajor.clear(); - mRawAxes.toolMinor.clear(); - mRawAxes.orientation.clear(); - mRawAxes.distance.clear(); - mRawAxes.trackingId.clear(); - mRawAxes.slot.clear(); -} - -void TouchInputMapper::dumpRawAxes(String8& dump) { - dump.append(INDENT3 "Raw Axes:\n"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.distance, "Distance"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.trackingId, "TrackingId"); - dumpRawAbsoluteAxisInfo(dump, mRawAxes.slot, "Slot"); -} - -bool TouchInputMapper::configureSurfaceLocked() { +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.trackingId, "TrackingId"); + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot"); +} + +bool TouchInputMapper::configureSurface() { // Ensure we have valid X and Y axes. - if (!mRawAxes.x.valid || !mRawAxes.y.valid) { + if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) { LOGW(INDENT "Touch device '%s' did not report support for X or Y axis! " "The device will be inoperable.", getDeviceName().string()); return false; @@ -2398,27 +2470,27 @@ bool TouchInputMapper::configureSurfaceLocked() { // Update orientation and dimensions if needed. int32_t orientation = DISPLAY_ORIENTATION_0; - int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1; - int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1; + int32_t width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; + int32_t height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; if (mParameters.associatedDisplayId >= 0) { // Note: getDisplayInfo is non-reentrant so we can continue holding the lock. if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId, mParameters.associatedDisplayIsExternal, - &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight, - &mLocked.associatedDisplayOrientation)) { + &mAssociatedDisplayWidth, &mAssociatedDisplayHeight, + &mAssociatedDisplayOrientation)) { return false; } // A touch screen inherits the dimensions of the display. if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) { - width = mLocked.associatedDisplayWidth; - height = mLocked.associatedDisplayHeight; + width = mAssociatedDisplayWidth; + height = mAssociatedDisplayHeight; } // The device inherits the orientation of the display if it is orientation aware. if (mParameters.orientationAware) { - orientation = mLocked.associatedDisplayOrientation; + orientation = mAssociatedDisplayOrientation; } } @@ -2427,118 +2499,120 @@ bool TouchInputMapper::configureSurfaceLocked() { mPointerController = getPolicy()->obtainPointerController(getDeviceId()); } - bool orientationChanged = mLocked.surfaceOrientation != orientation; + bool orientationChanged = mSurfaceOrientation != orientation; if (orientationChanged) { - mLocked.surfaceOrientation = orientation; + mSurfaceOrientation = orientation; } - bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height; + bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height; if (sizeChanged) { LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d", getDeviceId(), getDeviceName().string(), width, height); - mLocked.surfaceWidth = width; - mLocked.surfaceHeight = height; + mSurfaceWidth = width; + mSurfaceHeight = height; // Configure X and Y factors. - mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1); - mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1); - mLocked.xPrecision = 1.0f / mLocked.xScale; - mLocked.yPrecision = 1.0f / mLocked.yScale; + mXScale = float(width) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1); + mYScale = float(height) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1); + mXPrecision = 1.0f / mXScale; + mYPrecision = 1.0f / mYScale; - mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X; - mLocked.orientedRanges.x.source = mTouchSource; - mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y; - mLocked.orientedRanges.y.source = mTouchSource; + mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X; + mOrientedRanges.x.source = mTouchSource; + mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y; + mOrientedRanges.y.source = mTouchSource; - configureVirtualKeysLocked(); + 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. - mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale); + mGeometricScale = avg(mXScale, mYScale); // Size of diagonal axis. float diagonalSize = hypotf(width, height); // TouchMajor and TouchMinor factors. if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) { - mLocked.orientedRanges.haveTouchSize = true; + mOrientedRanges.haveTouchSize = true; - mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR; - mLocked.orientedRanges.touchMajor.source = mTouchSource; - mLocked.orientedRanges.touchMajor.min = 0; - mLocked.orientedRanges.touchMajor.max = diagonalSize; - mLocked.orientedRanges.touchMajor.flat = 0; - mLocked.orientedRanges.touchMajor.fuzz = 0; + mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR; + mOrientedRanges.touchMajor.source = mTouchSource; + mOrientedRanges.touchMajor.min = 0; + mOrientedRanges.touchMajor.max = diagonalSize; + mOrientedRanges.touchMajor.flat = 0; + mOrientedRanges.touchMajor.fuzz = 0; - mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor; - mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR; + mOrientedRanges.touchMinor = mOrientedRanges.touchMajor; + mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR; } // ToolMajor and ToolMinor factors. - mLocked.toolSizeLinearScale = 0; - mLocked.toolSizeLinearBias = 0; - mLocked.toolSizeAreaScale = 0; - mLocked.toolSizeAreaBias = 0; + mToolSizeLinearScale = 0; + mToolSizeLinearBias = 0; + mToolSizeAreaScale = 0; + mToolSizeAreaBias = 0; if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) { if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) { if (mCalibration.haveToolSizeLinearScale) { - mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale; - } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) { - mLocked.toolSizeLinearScale = float(min(width, height)) - / mRawAxes.toolMajor.maxValue; + mToolSizeLinearScale = mCalibration.toolSizeLinearScale; + } else if (mRawPointerAxes.toolMajor.valid + && mRawPointerAxes.toolMajor.maxValue != 0) { + mToolSizeLinearScale = float(min(width, height)) + / mRawPointerAxes.toolMajor.maxValue; } if (mCalibration.haveToolSizeLinearBias) { - mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias; + mToolSizeLinearBias = mCalibration.toolSizeLinearBias; } } else if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_AREA) { if (mCalibration.haveToolSizeLinearScale) { - mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale; + mToolSizeLinearScale = mCalibration.toolSizeLinearScale; } else { - mLocked.toolSizeLinearScale = min(width, height); + mToolSizeLinearScale = min(width, height); } if (mCalibration.haveToolSizeLinearBias) { - mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias; + mToolSizeLinearBias = mCalibration.toolSizeLinearBias; } if (mCalibration.haveToolSizeAreaScale) { - mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale; - } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) { - mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue; + mToolSizeAreaScale = mCalibration.toolSizeAreaScale; + } else if (mRawPointerAxes.toolMajor.valid + && mRawPointerAxes.toolMajor.maxValue != 0) { + mToolSizeAreaScale = 1.0f / mRawPointerAxes.toolMajor.maxValue; } if (mCalibration.haveToolSizeAreaBias) { - mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias; + mToolSizeAreaBias = mCalibration.toolSizeAreaBias; } } - mLocked.orientedRanges.haveToolSize = true; + mOrientedRanges.haveToolSize = true; - mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR; - mLocked.orientedRanges.toolMajor.source = mTouchSource; - mLocked.orientedRanges.toolMajor.min = 0; - mLocked.orientedRanges.toolMajor.max = diagonalSize; - mLocked.orientedRanges.toolMajor.flat = 0; - mLocked.orientedRanges.toolMajor.fuzz = 0; + mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR; + mOrientedRanges.toolMajor.source = mTouchSource; + mOrientedRanges.toolMajor.min = 0; + mOrientedRanges.toolMajor.max = diagonalSize; + mOrientedRanges.toolMajor.flat = 0; + mOrientedRanges.toolMajor.fuzz = 0; - mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor; - mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR; + mOrientedRanges.toolMinor = mOrientedRanges.toolMajor; + mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR; } // Pressure factors. - mLocked.pressureScale = 0; + mPressureScale = 0; if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) { RawAbsoluteAxisInfo rawPressureAxis; switch (mCalibration.pressureSource) { case Calibration::PRESSURE_SOURCE_PRESSURE: - rawPressureAxis = mRawAxes.pressure; + rawPressureAxis = mRawPointerAxes.pressure; break; case Calibration::PRESSURE_SOURCE_TOUCH: - rawPressureAxis = mRawAxes.touchMajor; + rawPressureAxis = mRawPointerAxes.touchMajor; break; default: rawPressureAxis.clear(); @@ -2548,84 +2622,84 @@ bool TouchInputMapper::configureSurfaceLocked() { || mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) { if (mCalibration.havePressureScale) { - mLocked.pressureScale = mCalibration.pressureScale; + mPressureScale = mCalibration.pressureScale; } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) { - mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue; + mPressureScale = 1.0f / rawPressureAxis.maxValue; } } - mLocked.orientedRanges.havePressure = true; + mOrientedRanges.havePressure = true; - mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE; - mLocked.orientedRanges.pressure.source = mTouchSource; - mLocked.orientedRanges.pressure.min = 0; - mLocked.orientedRanges.pressure.max = 1.0; - mLocked.orientedRanges.pressure.flat = 0; - mLocked.orientedRanges.pressure.fuzz = 0; + mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE; + mOrientedRanges.pressure.source = mTouchSource; + mOrientedRanges.pressure.min = 0; + mOrientedRanges.pressure.max = 1.0; + mOrientedRanges.pressure.flat = 0; + mOrientedRanges.pressure.fuzz = 0; } // Size factors. - mLocked.sizeScale = 0; + mSizeScale = 0; if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) { if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) { - if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) { - mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue; + if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) { + mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue; } } - mLocked.orientedRanges.haveSize = true; + mOrientedRanges.haveSize = true; - mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE; - mLocked.orientedRanges.size.source = mTouchSource; - mLocked.orientedRanges.size.min = 0; - mLocked.orientedRanges.size.max = 1.0; - mLocked.orientedRanges.size.flat = 0; - mLocked.orientedRanges.size.fuzz = 0; + mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE; + mOrientedRanges.size.source = mTouchSource; + mOrientedRanges.size.min = 0; + mOrientedRanges.size.max = 1.0; + mOrientedRanges.size.flat = 0; + mOrientedRanges.size.fuzz = 0; } // Orientation - mLocked.orientationScale = 0; + mOrientationScale = 0; if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) { if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) { - if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) { - mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue; + if (mRawPointerAxes.orientation.valid && mRawPointerAxes.orientation.maxValue != 0) { + mOrientationScale = float(M_PI_2) / mRawPointerAxes.orientation.maxValue; } } - mLocked.orientedRanges.haveOrientation = true; + mOrientedRanges.haveOrientation = true; - mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION; - mLocked.orientedRanges.orientation.source = mTouchSource; - mLocked.orientedRanges.orientation.min = - M_PI_2; - mLocked.orientedRanges.orientation.max = M_PI_2; - mLocked.orientedRanges.orientation.flat = 0; - mLocked.orientedRanges.orientation.fuzz = 0; + mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION; + mOrientedRanges.orientation.source = mTouchSource; + mOrientedRanges.orientation.min = - M_PI_2; + mOrientedRanges.orientation.max = M_PI_2; + mOrientedRanges.orientation.flat = 0; + mOrientedRanges.orientation.fuzz = 0; } // Distance - mLocked.distanceScale = 0; + mDistanceScale = 0; if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) { if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_SCALED) { if (mCalibration.haveDistanceScale) { - mLocked.distanceScale = mCalibration.distanceScale; + mDistanceScale = mCalibration.distanceScale; } else { - mLocked.distanceScale = 1.0f; + mDistanceScale = 1.0f; } } - mLocked.orientedRanges.haveDistance = true; + mOrientedRanges.haveDistance = true; - mLocked.orientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE; - mLocked.orientedRanges.distance.source = mTouchSource; - mLocked.orientedRanges.distance.min = - mRawAxes.distance.minValue * mLocked.distanceScale; - mLocked.orientedRanges.distance.max = - mRawAxes.distance.minValue * mLocked.distanceScale; - mLocked.orientedRanges.distance.flat = 0; - mLocked.orientedRanges.distance.fuzz = - mRawAxes.distance.fuzz * mLocked.distanceScale; + mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE; + mOrientedRanges.distance.source = mTouchSource; + mOrientedRanges.distance.min = + mRawPointerAxes.distance.minValue * mDistanceScale; + mOrientedRanges.distance.max = + mRawPointerAxes.distance.minValue * mDistanceScale; + mOrientedRanges.distance.flat = 0; + mOrientedRanges.distance.fuzz = + mRawPointerAxes.distance.fuzz * mDistanceScale; } } @@ -2633,78 +2707,77 @@ bool TouchInputMapper::configureSurfaceLocked() { // Compute oriented surface dimensions, 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 (mLocked.surfaceOrientation) { + switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: case DISPLAY_ORIENTATION_270: - mLocked.orientedSurfaceWidth = mLocked.surfaceHeight; - mLocked.orientedSurfaceHeight = mLocked.surfaceWidth; - - mLocked.orientedXPrecision = mLocked.yPrecision; - mLocked.orientedYPrecision = mLocked.xPrecision; - - mLocked.orientedRanges.x.min = 0; - mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue) - * mLocked.yScale; - mLocked.orientedRanges.x.flat = 0; - mLocked.orientedRanges.x.fuzz = mLocked.yScale; - - mLocked.orientedRanges.y.min = 0; - mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue) - * mLocked.xScale; - mLocked.orientedRanges.y.flat = 0; - mLocked.orientedRanges.y.fuzz = mLocked.xScale; + mOrientedSurfaceWidth = mSurfaceHeight; + mOrientedSurfaceHeight = mSurfaceWidth; + + mOrientedXPrecision = mYPrecision; + mOrientedYPrecision = mXPrecision; + + mOrientedRanges.x.min = 0; + mOrientedRanges.x.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue) + * mYScale; + mOrientedRanges.x.flat = 0; + mOrientedRanges.x.fuzz = mYScale; + + mOrientedRanges.y.min = 0; + mOrientedRanges.y.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue) + * mXScale; + mOrientedRanges.y.flat = 0; + mOrientedRanges.y.fuzz = mXScale; break; default: - mLocked.orientedSurfaceWidth = mLocked.surfaceWidth; - mLocked.orientedSurfaceHeight = mLocked.surfaceHeight; - - mLocked.orientedXPrecision = mLocked.xPrecision; - mLocked.orientedYPrecision = mLocked.yPrecision; - - mLocked.orientedRanges.x.min = 0; - mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue) - * mLocked.xScale; - mLocked.orientedRanges.x.flat = 0; - mLocked.orientedRanges.x.fuzz = mLocked.xScale; - - mLocked.orientedRanges.y.min = 0; - mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue) - * mLocked.yScale; - mLocked.orientedRanges.y.flat = 0; - mLocked.orientedRanges.y.fuzz = mLocked.yScale; + mOrientedSurfaceWidth = mSurfaceWidth; + mOrientedSurfaceHeight = mSurfaceHeight; + + mOrientedXPrecision = mXPrecision; + mOrientedYPrecision = mYPrecision; + + mOrientedRanges.x.min = 0; + mOrientedRanges.x.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue) + * mXScale; + mOrientedRanges.x.flat = 0; + mOrientedRanges.x.fuzz = mXScale; + + mOrientedRanges.y.min = 0; + mOrientedRanges.y.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue) + * mYScale; + mOrientedRanges.y.flat = 0; + mOrientedRanges.y.fuzz = mYScale; break; } // Compute pointer gesture detection parameters. - // TODO: These factors should not be hardcoded. if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { - int32_t rawWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1; - int32_t rawHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1; + int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; + int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; float rawDiagonal = hypotf(rawWidth, rawHeight); - float displayDiagonal = hypotf(mLocked.associatedDisplayWidth, - mLocked.associatedDisplayHeight); + float displayDiagonal = hypotf(mAssociatedDisplayWidth, + mAssociatedDisplayHeight); // 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. - mLocked.pointerGestureXMovementScale = mConfig.pointerGestureMovementSpeedRatio + mPointerGestureXMovementScale = mConfig.pointerGestureMovementSpeedRatio * displayDiagonal / rawDiagonal; - mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale; + mPointerGestureYMovementScale = mPointerGestureXMovementScale; // 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. - mLocked.pointerGestureXZoomScale = mConfig.pointerGestureZoomSpeedRatio + mPointerGestureXZoomScale = mConfig.pointerGestureZoomSpeedRatio * displayDiagonal / rawDiagonal; - mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale; + mPointerGestureYZoomScale = mPointerGestureXZoomScale; // 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. - mLocked.pointerGestureMaxSwipeWidth = + mPointerGestureMaxSwipeWidth = mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal; // Reset the current pointer gesture. @@ -2720,35 +2793,35 @@ bool TouchInputMapper::configureSurfaceLocked() { return true; } -void TouchInputMapper::dumpSurfaceLocked(String8& dump) { - dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth); - dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight); - dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation); +void TouchInputMapper::dumpSurface(String8& dump) { + dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth); + dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); + dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation); } -void TouchInputMapper::configureVirtualKeysLocked() { +void TouchInputMapper::configureVirtualKeys() { Vector<VirtualKeyDefinition> virtualKeyDefinitions; getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions); - mLocked.virtualKeys.clear(); + mVirtualKeys.clear(); if (virtualKeyDefinitions.size() == 0) { return; } - mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size()); + mVirtualKeys.setCapacity(virtualKeyDefinitions.size()); - int32_t touchScreenLeft = mRawAxes.x.minValue; - int32_t touchScreenTop = mRawAxes.y.minValue; - int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1; - int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1; + 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]; - mLocked.virtualKeys.add(); - VirtualKey& virtualKey = mLocked.virtualKeys.editTop(); + mVirtualKeys.add(); + VirtualKey& virtualKey = mVirtualKeys.editTop(); virtualKey.scanCode = virtualKeyDefinition.scanCode; int32_t keyCode; @@ -2757,7 +2830,7 @@ void TouchInputMapper::configureVirtualKeysLocked() { & keyCode, & flags)) { LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode); - mLocked.virtualKeys.pop(); // drop the key + mVirtualKeys.pop(); // drop the key continue; } @@ -2769,22 +2842,22 @@ void TouchInputMapper::configureVirtualKeysLocked() { int32_t halfHeight = virtualKeyDefinition.height / 2; virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth) - * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft; + * touchScreenWidth / mSurfaceWidth + touchScreenLeft; virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth) - * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft; + * touchScreenWidth / mSurfaceWidth + touchScreenLeft; virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight) - * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop; + * touchScreenHeight / mSurfaceHeight + touchScreenTop; virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) - * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop; + * touchScreenHeight / mSurfaceHeight + touchScreenTop; } } -void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) { - if (!mLocked.virtualKeys.isEmpty()) { +void TouchInputMapper::dumpVirtualKeys(String8& dump) { + if (!mVirtualKeys.isEmpty()) { dump.append(INDENT3 "Virtual Keys:\n"); - for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) { - const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i); + 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, @@ -2927,22 +3000,22 @@ void TouchInputMapper::resolveCalibration() { // Pressure switch (mCalibration.pressureSource) { case Calibration::PRESSURE_SOURCE_DEFAULT: - if (mRawAxes.pressure.valid) { + if (mRawPointerAxes.pressure.valid) { mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE; - } else if (mRawAxes.touchMajor.valid) { + } else if (mRawPointerAxes.touchMajor.valid) { mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH; } break; case Calibration::PRESSURE_SOURCE_PRESSURE: - if (! mRawAxes.pressure.valid) { + if (! mRawPointerAxes.pressure.valid) { LOGW("Calibration property touch.pressure.source is 'pressure' but " "the pressure axis is not available."); } break; case Calibration::PRESSURE_SOURCE_TOUCH: - if (! mRawAxes.touchMajor.valid) { + if (! mRawPointerAxes.touchMajor.valid) { LOGW("Calibration property touch.pressure.source is 'touch' but " "the touchMajor axis is not available."); } @@ -2968,7 +3041,7 @@ void TouchInputMapper::resolveCalibration() { // Tool Size switch (mCalibration.toolSizeCalibration) { case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT: - if (mRawAxes.toolMajor.valid) { + if (mRawPointerAxes.toolMajor.valid) { mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR; } else { mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE; @@ -2997,7 +3070,7 @@ void TouchInputMapper::resolveCalibration() { // Size switch (mCalibration.sizeCalibration) { case Calibration::SIZE_CALIBRATION_DEFAULT: - if (mRawAxes.toolMajor.valid) { + if (mRawPointerAxes.toolMajor.valid) { mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED; } else { mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE; @@ -3011,7 +3084,7 @@ void TouchInputMapper::resolveCalibration() { // Orientation switch (mCalibration.orientationCalibration) { case Calibration::ORIENTATION_CALIBRATION_DEFAULT: - if (mRawAxes.orientation.valid) { + if (mRawPointerAxes.orientation.valid) { mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED; } else { mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE; @@ -3025,7 +3098,7 @@ void TouchInputMapper::resolveCalibration() { // Distance switch (mCalibration.distanceCalibration) { case Calibration::DISTANCE_CALIBRATION_DEFAULT: - if (mRawAxes.distance.valid) { + if (mRawPointerAxes.distance.valid) { mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED; } else { mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE; @@ -3177,24 +3250,20 @@ void TouchInputMapper::dumpCalibration(String8& dump) { } void TouchInputMapper::reset() { - // Synthesize touch up event if touch is currently down. + // Synthesize touch up event. // This will also take care of finishing virtual key processing if needed. - if (mLastTouch.pointerCount != 0) { - nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); - mCurrentTouch.clear(); - syncTouch(when, true); - } + nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); + mCurrentRawPointerData.clear(); + mCurrentButtonState = 0; + syncTouch(when, true); - { // acquire lock - AutoMutex _l(mLock); - initializeLocked(); + initialize(); - if (mPointerController != NULL - && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - mPointerController->clearSpots(); - } - } // release lock + if (mPointerController != NULL + && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); + mPointerController->clearSpots(); + } InputMapper::reset(); } @@ -3202,25 +3271,37 @@ void TouchInputMapper::reset() { void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { #if DEBUG_RAW_EVENTS if (!havePointerIds) { - LOGD("syncTouch: pointerCount=%d, no pointer ids", mCurrentTouch.pointerCount); + LOGD("syncTouch: pointerCount %d -> %d, no pointer ids", + mLastRawPointerData.pointerCount, + mCurrentRawPointerData.pointerCount); } else { - LOGD("syncTouch: pointerCount=%d, up=0x%08x, down=0x%08x, move=0x%08x, " - "last=0x%08x, current=0x%08x", mCurrentTouch.pointerCount, - mLastTouch.idBits.value & ~mCurrentTouch.idBits.value, - mCurrentTouch.idBits.value & ~mLastTouch.idBits.value, - mLastTouch.idBits.value & mCurrentTouch.idBits.value, - mLastTouch.idBits.value, mCurrentTouch.idBits.value); + LOGD("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 + // Configure the surface now, if possible. + if (!configureSurface()) { + mLastRawPointerData.clear(); + mLastCookedPointerData.clear(); + mLastButtonState = 0; + return; + } + // Preprocess pointer data. if (!havePointerIds) { - calculatePointerIds(); + assignPointerIds(); } - // Handle initial down events. + // Handle policy on initial down or hover events. uint32_t policyFlags = 0; - if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) { + if (mLastRawPointerData.pointerCount == 0 && mCurrentRawPointerData.pointerCount != 0) { if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) { // If this is a touch screen, hide the pointer on an initial down. getContext()->fadePointer(); @@ -3235,40 +3316,31 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { } } - // Synthesize key down from buttons if needed. + // Synthesize key down from raw buttons if needed. synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mTouchSource, - policyFlags, mLastTouch.buttonState, mCurrentTouch.buttonState); - - // Send motion events. - TouchResult touchResult; - if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0 - && mLastTouch.buttonState == mCurrentTouch.buttonState) { - // Drop spurious syncs. - touchResult = DROP_STROKE; - } else { - // Process touches and virtual keys. - touchResult = consumeOffScreenTouches(when, policyFlags); - if (touchResult == DISPATCH_TOUCH) { - suppressSwipeOntoVirtualKeys(when); - if (mPointerController != NULL && mConfig.pointerGesturesEnabled) { - dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); - } - dispatchTouches(when, policyFlags); - } + policyFlags, mLastButtonState, mCurrentButtonState); + + if (consumeRawTouches(when, policyFlags)) { + mCurrentRawPointerData.clear(); } - // Synthesize key up from buttons if needed. + if (mPointerController != NULL && mConfig.pointerGesturesEnabled) { + dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); + } + + cookPointerData(); + 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(), mTouchSource, - policyFlags, mLastTouch.buttonState, mCurrentTouch.buttonState); + policyFlags, mLastButtonState, mCurrentButtonState); // Copy current touch to last touch in preparation for the next cycle. - // Keep the button state so we can track edge-triggered button state changes. - if (touchResult == DROP_STROKE) { - mLastTouch.clear(); - mLastTouch.buttonState = mCurrentTouch.buttonState; - } else { - mLastTouch.copyFrom(mCurrentTouch); - } + mLastRawPointerData.copyFrom(mCurrentRawPointerData); + mLastCookedPointerData.copyFrom(mCurrentCookedPointerData); + mLastButtonState = mCurrentButtonState; } void TouchInputMapper::timeoutExpired(nsecs_t when) { @@ -3277,125 +3349,88 @@ void TouchInputMapper::timeoutExpired(nsecs_t when) { } } -TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( - nsecs_t when, uint32_t policyFlags) { - int32_t keyEventAction, keyEventFlags; - int32_t keyCode, scanCode, downTime; - TouchResult touchResult; - - { // acquire lock - AutoMutex _l(mLock); - - // Update surface size and orientation, including virtual key positions. - if (! configureSurfaceLocked()) { - return DROP_STROKE; - } - - // Check for virtual key press. - if (mLocked.currentVirtualKey.down) { - if (mCurrentTouch.pointerCount == 0) { - // Pointer went up while virtual key was down. - mLocked.currentVirtualKey.down = false; +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 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d", - mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode); + mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); #endif - keyEventAction = AKEY_EVENT_ACTION_UP; - keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; - touchResult = SKIP_TOUCH; - goto DispatchVirtualKey; + dispatchVirtualKey(when, policyFlags, + AKEY_EVENT_ACTION_UP, + AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); } + return true; + } - if (mCurrentTouch.pointerCount == 1) { - int32_t x = mCurrentTouch.pointers[0].x; - int32_t y = mCurrentTouch.pointers[0].y; - const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y); - if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) { - // Pointer is still within the space of the virtual key. - return SKIP_TOUCH; - } + 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 and drop the stroke so subsequent motions will be - // considered fresh downs. This is useful when the user swipes away from the - // virtual key area into the main display surface. - mLocked.currentVirtualKey.down = false; + // 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 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", - mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode); + mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); #endif - keyEventAction = AKEY_EVENT_ACTION_UP; - keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY - | AKEY_EVENT_FLAG_CANCELED; - - // Check whether the pointer moved inside the display area where we should - // start a new stroke. - int32_t x = mCurrentTouch.pointers[0].x; - int32_t y = mCurrentTouch.pointers[0].y; - if (isPointInsideSurfaceLocked(x, y)) { - mLastTouch.clear(); - touchResult = DISPATCH_TOUCH; - } else { - touchResult = DROP_STROKE; - } - } else { - if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) { - // Pointer just went down. Handle off-screen touches, if needed. - int32_t x = mCurrentTouch.pointers[0].x; - int32_t y = mCurrentTouch.pointers[0].y; - if (! isPointInsideSurfaceLocked(x, y)) { - // If exactly one pointer went down, check for virtual key hit. - // Otherwise we will drop the entire stroke. - if (mCurrentTouch.pointerCount == 1) { - const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y); - if (virtualKey) { - if (mContext->shouldDropVirtualKey(when, getDevice(), - virtualKey->keyCode, virtualKey->scanCode)) { - return DROP_STROKE; - } - - mLocked.currentVirtualKey.down = true; - mLocked.currentVirtualKey.downTime = when; - mLocked.currentVirtualKey.keyCode = virtualKey->keyCode; - mLocked.currentVirtualKey.scanCode = virtualKey->scanCode; + 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 - LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d", - mLocked.currentVirtualKey.keyCode, - mLocked.currentVirtualKey.scanCode); + LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d", + mCurrentVirtualKey.keyCode, + mCurrentVirtualKey.scanCode); #endif - keyEventAction = AKEY_EVENT_ACTION_DOWN; - keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM - | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; - touchResult = SKIP_TOUCH; - goto DispatchVirtualKey; - } + dispatchVirtualKey(when, policyFlags, + AKEY_EVENT_ACTION_DOWN, + AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); } - return DROP_STROKE; } } - return DISPATCH_TOUCH; + return true; } + } - DispatchVirtualKey: - // Collect remaining state needed to dispatch virtual key. - keyCode = mLocked.currentVirtualKey.keyCode; - scanCode = mLocked.currentVirtualKey.scanCode; - downTime = mLocked.currentVirtualKey.downTime; - } // release lock - - // Dispatch virtual key. - int32_t metaState = mContext->getGlobalMetaState(); - policyFlags |= POLICY_FLAG_VIRTUAL; - getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags, - keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime); - return touchResult; -} - -void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) { // Disable all virtual key touches that happen within a short time interval of the - // most recent touch. The idea is to filter out stray virtual key presses when - // interacting with the touch screen. + // 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: // @@ -3407,37 +3442,44 @@ void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) { // 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 && mCurrentTouch.pointerCount != 0) { + if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) { mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime); } + return false; } -void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { - uint32_t currentPointerCount = mCurrentTouch.pointerCount; - uint32_t lastPointerCount = mLastTouch.pointerCount; - if (currentPointerCount == 0 && lastPointerCount == 0) { - return; // nothing to do! - } +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; - // Update current touch coordinates. - float xPrecision, yPrecision; - prepareTouches(&xPrecision, &yPrecision); + NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags, + keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime); + getListener()->notifyKey(&args); +} - // Dispatch motions. - BitSet32 currentIdBits = mCurrentTouch.idBits; - BitSet32 lastIdBits = mLastTouch.idBits; +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 = mCurrentTouch.buttonState; + int32_t buttonState = mCurrentButtonState; if (currentIdBits == lastIdBits) { - // No pointer id changes so this is a move event. - // The dispatcher takes care of batching moves so we don't have to deal with that here. - dispatchMotion(when, policyFlags, mTouchSource, - AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, - AMOTION_EVENT_EDGE_FLAG_NONE, - mCurrentTouchProperties, mCurrentTouchCoords, - mCurrentTouch.idToIndex, currentIdBits, -1, - xPrecision, yPrecision, mDownTime); + 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, mTouchSource, + 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. @@ -3449,23 +3491,28 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { // 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( - mCurrentTouchProperties, mCurrentTouchCoords, mCurrentTouch.idToIndex, - mLastTouchProperties, mLastTouchCoords, mLastTouch.idToIndex, + mCurrentCookedPointerData.pointerProperties, + mCurrentCookedPointerData.pointerCoords, + mCurrentCookedPointerData.idToIndex, + mLastCookedPointerData.pointerProperties, + mLastCookedPointerData.pointerCoords, + mLastCookedPointerData.idToIndex, moveIdBits); - if (buttonState != mLastTouch.buttonState) { + if (buttonState != mLastButtonState) { moveNeeded = true; } // Dispatch pointer up events. while (!upIdBits.isEmpty()) { - uint32_t upId = upIdBits.firstMarkedBit(); - upIdBits.clearBit(upId); + uint32_t upId = upIdBits.clearFirstMarkedBit(); dispatchMotion(when, policyFlags, mTouchSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0, - mLastTouchProperties, mLastTouchCoords, - mLastTouch.idToIndex, dispatchedIdBits, upId, - xPrecision, yPrecision, mDownTime); + mLastCookedPointerData.pointerProperties, + mLastCookedPointerData.pointerCoords, + mLastCookedPointerData.idToIndex, + dispatchedIdBits, upId, + mOrientedXPrecision, mOrientedYPrecision, mDownTime); dispatchedIdBits.clearBit(upId); } @@ -3476,15 +3523,16 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { LOG_ASSERT(moveIdBits.value == dispatchedIdBits.value); dispatchMotion(when, policyFlags, mTouchSource, AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0, - mCurrentTouchProperties, mCurrentTouchCoords, - mCurrentTouch.idToIndex, dispatchedIdBits, -1, - xPrecision, yPrecision, mDownTime); + 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.firstMarkedBit(); - downIdBits.clearBit(downId); + uint32_t downId = downIdBits.clearFirstMarkedBit(); dispatchedIdBits.markBit(downId); if (dispatchedIdBits.count() == 1) { @@ -3494,49 +3542,88 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { dispatchMotion(when, policyFlags, mTouchSource, AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0, - mCurrentTouchProperties, mCurrentTouchCoords, - mCurrentTouch.idToIndex, dispatchedIdBits, downId, - xPrecision, yPrecision, mDownTime); + mCurrentCookedPointerData.pointerProperties, + mCurrentCookedPointerData.pointerCoords, + mCurrentCookedPointerData.idToIndex, + dispatchedIdBits, downId, + mOrientedXPrecision, mOrientedYPrecision, mDownTime); } } +} - // Update state for next time. - for (uint32_t i = 0; i < currentPointerCount; i++) { - mLastTouchProperties[i].copyFrom(mCurrentTouchProperties[i]); - mLastTouchCoords[i].copyFrom(mCurrentTouchCoords[i]); +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, mTouchSource, + 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::prepareTouches(float* outXPrecision, float* outYPrecision) { - uint32_t currentPointerCount = mCurrentTouch.pointerCount; - uint32_t lastPointerCount = mLastTouch.pointerCount; +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, mTouchSource, + AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0, + mCurrentCookedPointerData.pointerProperties, + mCurrentCookedPointerData.pointerCoords, + mCurrentCookedPointerData.idToIndex, + mCurrentCookedPointerData.hoveringIdBits, -1, + mOrientedXPrecision, mOrientedYPrecision, mDownTime); + mSentHoverEnter = true; + } - AutoMutex _l(mLock); + dispatchMotion(when, policyFlags, mTouchSource, + 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 touch screen coordinates (TouchData) into - // display or surface coordinates (PointerCoords) and adjust for display orientation. + // 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 PointerData& in = mCurrentTouch.pointers[i]; + const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i]; // ToolMajor and ToolMinor float toolMajor, toolMinor; switch (mCalibration.toolSizeCalibration) { case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC: - toolMajor = in.toolMajor * mLocked.geometricScale; - if (mRawAxes.toolMinor.valid) { - toolMinor = in.toolMinor * mLocked.geometricScale; + toolMajor = in.toolMajor * mGeometricScale; + if (mRawPointerAxes.toolMinor.valid) { + toolMinor = in.toolMinor * mGeometricScale; } else { toolMinor = toolMajor; } break; case Calibration::TOOL_SIZE_CALIBRATION_LINEAR: toolMajor = in.toolMajor != 0 - ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias + ? in.toolMajor * mToolSizeLinearScale + mToolSizeLinearBias : 0; - if (mRawAxes.toolMinor.valid) { + if (mRawPointerAxes.toolMinor.valid) { toolMinor = in.toolMinor != 0 - ? in.toolMinor * mLocked.toolSizeLinearScale - + mLocked.toolSizeLinearBias + ? in.toolMinor * mToolSizeLinearScale + + mToolSizeLinearBias : 0; } else { toolMinor = toolMajor; @@ -3545,8 +3632,8 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision case Calibration::TOOL_SIZE_CALIBRATION_AREA: if (in.toolMajor != 0) { float diameter = sqrtf(in.toolMajor - * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias); - toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias; + * mToolSizeAreaScale + mToolSizeAreaBias); + toolMajor = diameter * mToolSizeLinearScale + mToolSizeLinearBias; } else { toolMajor = 0; } @@ -3559,8 +3646,9 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision } if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) { - toolMajor /= currentPointerCount; - toolMinor /= currentPointerCount; + uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count(); + toolMajor /= touchingCount; + toolMinor /= touchingCount; } // Pressure @@ -3580,10 +3668,10 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision switch (mCalibration.pressureCalibration) { case Calibration::PRESSURE_CALIBRATION_PHYSICAL: case Calibration::PRESSURE_CALIBRATION_AMPLITUDE: - pressure = rawPressure * mLocked.pressureScale; + pressure = rawPressure * mPressureScale; break; default: - pressure = 1; + pressure = in.isHovering ? 0 : 1; break; } @@ -3591,9 +3679,9 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision float touchMajor, touchMinor; switch (mCalibration.touchSizeCalibration) { case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC: - touchMajor = in.touchMajor * mLocked.geometricScale; - if (mRawAxes.touchMinor.valid) { - touchMinor = in.touchMinor * mLocked.geometricScale; + touchMajor = in.touchMajor * mGeometricScale; + if (mRawPointerAxes.touchMinor.valid) { + touchMinor = in.touchMinor * mGeometricScale; } else { touchMinor = touchMajor; } @@ -3619,10 +3707,10 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision float size; switch (mCalibration.sizeCalibration) { case Calibration::SIZE_CALIBRATION_NORMALIZED: { - float rawSize = mRawAxes.toolMinor.valid + float rawSize = mRawPointerAxes.toolMinor.valid ? avg(in.toolMajor, in.toolMinor) : in.toolMajor; - size = rawSize * mLocked.sizeScale; + size = rawSize * mSizeScale; break; } default: @@ -3634,7 +3722,7 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision float orientation; switch (mCalibration.orientationCalibration) { case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED: - orientation = in.orientation * mLocked.orientationScale; + orientation = in.orientation * mOrientationScale; break; case Calibration::ORIENTATION_CALIBRATION_VECTOR: { int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4); @@ -3659,7 +3747,7 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision float distance; switch (mCalibration.distanceCalibration) { case Calibration::DISTANCE_CALIBRATION_SCALED: - distance = in.distance * mLocked.distanceScale; + distance = in.distance * mDistanceScale; break; default: distance = 0; @@ -3668,35 +3756,35 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision // X and Y // Adjust coords for surface orientation. float x, y; - switch (mLocked.surfaceOrientation) { + switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: - x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale; - y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale; + x = float(in.y - mRawPointerAxes.y.minValue) * mYScale; + y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale; orientation -= M_PI_2; if (orientation < - M_PI_2) { orientation += M_PI; } break; case DISPLAY_ORIENTATION_180: - x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale; - y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale; + x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale; + y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale; break; case DISPLAY_ORIENTATION_270: - x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale; - y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale; + x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale; + y = float(in.x - mRawPointerAxes.x.minValue) * mXScale; orientation += M_PI_2; if (orientation > M_PI_2) { orientation -= M_PI; } break; default: - x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale; - y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale; + x = float(in.x - mRawPointerAxes.x.minValue) * mXScale; + y = float(in.y - mRawPointerAxes.y.minValue) * mYScale; break; } // Write output coords. - PointerCoords& out = mCurrentTouchCoords[i]; + PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i]; out.clear(); out.setAxisValue(AMOTION_EVENT_AXIS_X, x); out.setAxisValue(AMOTION_EVENT_AXIS_Y, y); @@ -3707,19 +3795,18 @@ void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor); out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor); out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation); - if (distance != 0) { - out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance); - } + out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance); // Write output properties. - PointerProperties& properties = mCurrentTouchProperties[i]; + PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i]; + uint32_t id = in.id; properties.clear(); - properties.id = mCurrentTouch.pointers[i].id; - properties.toolType = mCurrentTouch.pointers[i].toolType; - } + properties.id = id; + properties.toolType = in.toolType; - *outXPrecision = mLocked.orientedXPrecision; - *outYPrecision = mLocked.orientedYPrecision; + // Write id index. + mCurrentCookedPointerData.idToIndex[id] = i; + } } void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, @@ -3782,7 +3869,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag // Send events! int32_t metaState = getContext()->getGlobalMetaState(); - int32_t buttonState = mCurrentTouch.buttonState; + 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. @@ -3803,7 +3890,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, movedGestureIdBits); - if (buttonState != mLastTouch.buttonState) { + if (buttonState != mLastButtonState) { moveNeeded = true; } } @@ -3830,8 +3917,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag & ~mPointerGesture.currentGestureIdBits.value; } while (!upGestureIdBits.isEmpty()) { - uint32_t id = upGestureIdBits.firstMarkedBit(); - upGestureIdBits.clearBit(id); + uint32_t id = upGestureIdBits.clearFirstMarkedBit(); dispatchMotion(when, policyFlags, mPointerSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, @@ -3861,8 +3947,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value & ~dispatchedGestureIdBits.value); while (!downGestureIdBits.isEmpty()) { - uint32_t id = downGestureIdBits.firstMarkedBit(); - downGestureIdBits.clearBit(id); + uint32_t id = downGestureIdBits.clearFirstMarkedBit(); dispatchedGestureIdBits.markBit(id); if (dispatchedGestureIdBits.count() == 1) { @@ -3906,10 +3991,11 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); - getDispatcher()->notifyMotion(when, getDeviceId(), mPointerSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mPointerSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime); + getListener()->notifyMotion(&args); } // Update state. @@ -3919,8 +4005,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag } else { mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits; for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); + uint32_t id = idBits.clearFirstMarkedBit(); uint32_t index = mPointerGesture.currentGestureIdToIndex[id]; mPointerGesture.lastGestureProperties[index].copyFrom( mPointerGesture.currentGestureProperties[index]); @@ -3936,8 +4021,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, *outCancelPreviousGesture = false; *outFinishPreviousGesture = false; - AutoMutex _l(mLock); - // Handle TAP timeout. if (isTimeout) { #if DEBUG_GESTURES @@ -3973,16 +4056,14 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, { VelocityTracker::Position positions[MAX_POINTERS]; uint32_t count = 0; - for (BitSet32 idBits(mCurrentTouch.idBits); !idBits.isEmpty(); count++) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - uint32_t index = mCurrentTouch.idToIndex[id]; - positions[count].x = mCurrentTouch.pointers[index].x - * mLocked.pointerGestureXMovementScale; - positions[count].y = mCurrentTouch.pointers[index].y - * mLocked.pointerGestureYMovementScale; + for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); count++) { + uint32_t id = idBits.clearFirstMarkedBit(); + const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); + positions[count].x = pointer.x * mPointerGestureXMovementScale; + positions[count].y = pointer.y * mPointerGestureYMovementScale; } - mPointerGesture.velocityTracker.addMovement(when, mCurrentTouch.idBits, positions); + mPointerGesture.velocityTracker.addMovement(when, + mCurrentRawPointerData.touchingIdBits, positions); } // Pick a new active touch id if needed. @@ -3994,20 +4075,25 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, int32_t lastActiveTouchId = mPointerGesture.activeTouchId; int32_t activeTouchId = lastActiveTouchId; if (activeTouchId < 0) { - if (!mCurrentTouch.idBits.isEmpty()) { + if (!mCurrentRawPointerData.touchingIdBits.isEmpty()) { activeTouchChanged = true; - activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit(); + activeTouchId = mPointerGesture.activeTouchId = + mCurrentRawPointerData.touchingIdBits.firstMarkedBit(); mPointerGesture.firstTouchTime = when; } - } else if (!mCurrentTouch.idBits.hasBit(activeTouchId)) { + } else if (!mCurrentRawPointerData.touchingIdBits.hasBit(activeTouchId)) { activeTouchChanged = true; - if (!mCurrentTouch.idBits.isEmpty()) { - activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit(); + if (!mCurrentRawPointerData.touchingIdBits.isEmpty()) { + activeTouchId = mPointerGesture.activeTouchId = + mCurrentRawPointerData.touchingIdBits.firstMarkedBit(); } else { activeTouchId = mPointerGesture.activeTouchId = -1; } } + uint32_t currentTouchingPointerCount = mCurrentRawPointerData.touchingIdBits.count(); + uint32_t lastTouchingPointerCount = mLastRawPointerData.touchingIdBits.count(); + // Determine whether we are in quiet time. bool isQuietTime = false; if (activeTouchId < 0) { @@ -4018,14 +4104,14 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS || mPointerGesture.lastGestureMode == PointerGesture::SWIPE || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) - && mCurrentTouch.pointerCount < 2) { + && currentTouchingPointerCount < 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 - && mCurrentTouch.pointerCount >= 2 - && !isPointerDown(mCurrentTouch.buttonState)) { + && currentTouchingPointerCount >= 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. @@ -4053,7 +4139,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureIdBits.clear(); mPointerGesture.pointerVelocityControl.reset(); - } else if (isPointerDown(mCurrentTouch.buttonState)) { + } 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. @@ -4069,7 +4155,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // being dragged. #if DEBUG_GESTURES LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, " - "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount); + "currentTouchingPointerCount=%d", activeTouchId, currentTouchingPointerCount); #endif // Reset state when just starting. if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) { @@ -4079,11 +4165,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // Switch pointers if needed. // Find the fastest pointer and follow it. - if (activeTouchId >= 0 && mCurrentTouch.pointerCount > 1) { + if (activeTouchId >= 0 && currentTouchingPointerCount > 1) { int32_t bestId = -1; float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed; - for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) { - uint32_t id = mCurrentTouch.pointers[i].id; + for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) { + uint32_t id = idBits.clearFirstMarkedBit(); float vx, vy; if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) { float speed = hypotf(vx, vy); @@ -4103,17 +4189,15 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } } - if (activeTouchId >= 0 && mLastTouch.idBits.hasBit(activeTouchId)) { - const PointerData& currentPointer = - mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]]; - const PointerData& lastPointer = - mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]]; - float deltaX = (currentPointer.x - lastPointer.x) - * mLocked.pointerGestureXMovementScale; - float deltaY = (currentPointer.y - lastPointer.y) - * mLocked.pointerGestureYMovementScale; + if (activeTouchId >= 0 && mLastRawPointerData.touchingIdBits.hasBit(activeTouchId)) { + const RawPointerData::Pointer& currentPointer = + mCurrentRawPointerData.pointerForId(activeTouchId); + const RawPointerData::Pointer& lastPointer = + mLastRawPointerData.pointerForId(activeTouchId); + float deltaX = (currentPointer.x - lastPointer.x) * mPointerGestureXMovementScale; + float deltaY = (currentPointer.y - lastPointer.y) * mPointerGestureYMovementScale; - rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY); + rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY); // Move the pointer using a relative motion. @@ -4138,7 +4222,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, 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 (mCurrentTouch.pointerCount == 0) { + } else if (currentTouchingPointerCount == 0) { // Case 3. No fingers down and button is not pressed. (NEUTRAL) if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) { *outFinishPreviousGesture = true; @@ -4149,7 +4233,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool tapped = false; if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) - && mLastTouch.pointerCount == 1) { + && lastTouchingPointerCount == 1) { if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) { float x, y; mPointerController->getPosition(&x, &y); @@ -4209,7 +4293,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL; mPointerGesture.currentGestureIdBits.clear(); } - } else if (mCurrentTouch.pointerCount == 1) { + } else if (currentTouchingPointerCount == 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. @@ -4241,17 +4325,17 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG; } - if (mLastTouch.idBits.hasBit(activeTouchId)) { - const PointerData& currentPointer = - mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]]; - const PointerData& lastPointer = - mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]]; + if (mLastRawPointerData.touchingIdBits.hasBit(activeTouchId)) { + const RawPointerData::Pointer& currentPointer = + mCurrentRawPointerData.pointerForId(activeTouchId); + const RawPointerData::Pointer& lastPointer = + mLastRawPointerData.pointerForId(activeTouchId); float deltaX = (currentPointer.x - lastPointer.x) - * mLocked.pointerGestureXMovementScale; + * mPointerGestureXMovementScale; float deltaY = (currentPointer.y - lastPointer.y) - * mLocked.pointerGestureYMovementScale; + * mPointerGestureYMovementScale; - rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY); + rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY); // Move the pointer using a relative motion. @@ -4294,7 +4378,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); - if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) { + if (lastTouchingPointerCount == 0 && currentTouchingPointerCount != 0) { mPointerGesture.resetTap(); mPointerGesture.tapDownTime = when; mPointerGesture.tapX = x; @@ -4322,7 +4406,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, && mPointerGesture.lastGestureMode != PointerGesture::SWIPE && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) { *outFinishPreviousGesture = true; - } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) { + } else if (!settled && currentTouchingPointerCount > lastTouchingPointerCount) { // Additional pointers have gone down but not yet settled. // Reset the gesture. #if DEBUG_GESTURES @@ -4350,33 +4434,31 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, + mConfig.pointerGestureMultitouchSettleInterval - when) * 0.000001f); #endif - mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX, + 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(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value); - !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - + for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits.value + & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) { + uint32_t id = idBits.clearFirstMarkedBit(); mPointerGesture.referenceDeltas[id].dx = 0; mPointerGesture.referenceDeltas[id].dy = 0; } - mPointerGesture.referenceIdBits = mCurrentTouch.idBits; + mPointerGesture.referenceIdBits = mCurrentRawPointerData.touchingIdBits; // Add delta for all fingers and calculate a common movement delta. float commonDeltaX = 0, commonDeltaY = 0; - BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value); + BitSet32 commonIdBits(mLastRawPointerData.touchingIdBits.value + & mCurrentRawPointerData.touchingIdBits.value); for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { bool first = (idBits == commonIdBits); - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - - const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]]; - const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]]; + 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; @@ -4395,12 +4477,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, float dist[MAX_POINTER_ID + 1]; int32_t distOverThreshold = 0; for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - + uint32_t id = idBits.clearFirstMarkedBit(); PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; - dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale, - delta.dy * mLocked.pointerGestureYZoomScale); + dist[id] = hypotf(delta.dx * mPointerGestureXZoomScale, + delta.dy * mPointerGestureYZoomScale); if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) { distOverThreshold += 1; } @@ -4409,71 +4489,74 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // Only transition when at least two pointers have moved further than // the minimum distance threshold. if (distOverThreshold >= 2) { - float d; - if (mCurrentTouch.pointerCount > 2) { + if (currentTouchingPointerCount > 2) { // There are more than two pointers, switch to FREEFORM. #if DEBUG_GESTURES LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", - mCurrentTouch.pointerCount); + currentTouchingPointerCount); #endif *outCancelPreviousGesture = true; mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } else if (((d = distance( - mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y, - mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y)) - > mLocked.pointerGestureMaxSwipeWidth)) { - // There are two pointers but they are too far apart for a SWIPE, - // switch to FREEFORM. + } else { + // There are exactly two pointers. + BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); + 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 - LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f", - d, mLocked.pointerGestureMaxSwipeWidth); + LOGD("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. - uint32_t id1 = mCurrentTouch.pointers[0].id; - uint32_t id2 = mCurrentTouch.pointers[1].id; - 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 * mLocked.pointerGestureXZoomScale; - float dy1 = delta1.dy * mLocked.pointerGestureYZoomScale; - float dx2 = delta2.dx * mLocked.pointerGestureXZoomScale; - float dy2 = delta2.dy * mLocked.pointerGestureYZoomScale; - 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. + *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 * mPointerGestureXZoomScale; + float dy1 = delta1.dy * mPointerGestureYZoomScale; + float dx2 = delta2.dx * mPointerGestureXZoomScale; + float dy2 = delta2.dy * mPointerGestureYZoomScale; + 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 - LOGD("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); + LOGD("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. + mPointerGesture.currentGestureMode = PointerGesture::SWIPE; + } else { + // Pointers are moving in different directions. Switch to FREEFORM. #if DEBUG_GESTURES - LOGD("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); + LOGD("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; + *outCancelPreviousGesture = true; + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + } } } } @@ -4481,10 +4564,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) { // Switch from SWIPE to FREEFORM if additional pointers go down. // Cancel previous gesture. - if (mCurrentTouch.pointerCount > 2) { + if (currentTouchingPointerCount > 2) { #if DEBUG_GESTURES LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2", - mCurrentTouch.pointerCount); + currentTouchingPointerCount); #endif *outCancelPreviousGesture = true; mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; @@ -4496,9 +4579,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if (mPointerGesture.currentGestureMode != PointerGesture::PRESS && (commonDeltaX || commonDeltaY)) { for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - + uint32_t id = idBits.clearFirstMarkedBit(); PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; delta.dx = 0; delta.dy = 0; @@ -4507,10 +4588,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.referenceTouchX += commonDeltaX; mPointerGesture.referenceTouchY += commonDeltaY; - commonDeltaX *= mLocked.pointerGestureXMovementScale; - commonDeltaY *= mLocked.pointerGestureYMovementScale; + commonDeltaX *= mPointerGestureXMovementScale; + commonDeltaY *= mPointerGestureYMovementScale; - rotateDelta(mLocked.surfaceOrientation, &commonDeltaX, &commonDeltaY); + rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY); mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); mPointerGesture.referenceGestureX += commonDeltaX; @@ -4524,7 +4605,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, #if DEBUG_GESTURES LOGD("Gestures: PRESS or SWIPE activeTouchId=%d," "activeGestureId=%d, currentTouchPointerCount=%d", - activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount); + activeTouchId, mPointerGesture.activeGestureId, currentTouchingPointerCount); #endif LOG_ASSERT(mPointerGesture.activeGestureId >= 0); @@ -4546,7 +4627,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, #if DEBUG_GESTURES LOGD("Gestures: FREEFORM activeTouchId=%d," "activeGestureId=%d, currentTouchPointerCount=%d", - activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount); + activeTouchId, mPointerGesture.activeGestureId, currentTouchingPointerCount); #endif LOG_ASSERT(mPointerGesture.activeGestureId >= 0); @@ -4568,15 +4649,16 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } else { // Otherwise, assume we mapped all touches from the previous frame. // Reuse all mappings that are still applicable. - mappedTouchIdBits.value = mLastTouch.idBits.value & mCurrentTouch.idBits.value; + mappedTouchIdBits.value = mLastRawPointerData.touchingIdBits.value + & mCurrentRawPointerData.touchingIdBits.value; usedGestureIdBits = mPointerGesture.lastGestureIdBits; // Check whether we need to choose a new active gesture id because the // current went went up. - for (BitSet32 upTouchIdBits(mLastTouch.idBits.value & ~mCurrentTouch.idBits.value); + for (BitSet32 upTouchIdBits(mLastRawPointerData.touchingIdBits.value + & ~mCurrentRawPointerData.touchingIdBits.value); !upTouchIdBits.isEmpty(); ) { - uint32_t upTouchId = upTouchIdBits.firstMarkedBit(); - upTouchIdBits.clearBit(upTouchId); + uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit(); uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId]; if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) { mPointerGesture.activeGestureId = -1; @@ -4593,12 +4675,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.activeGestureId); #endif - for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) { - uint32_t touchId = mCurrentTouch.pointers[i].id; + BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); + for (uint32_t i = 0; i < currentTouchingPointerCount; i++) { + uint32_t touchId = idBits.clearFirstMarkedBit(); uint32_t gestureId; if (!mappedTouchIdBits.hasBit(touchId)) { - gestureId = usedGestureIdBits.firstUnmarkedBit(); - usedGestureIdBits.markBit(gestureId); + gestureId = usedGestureIdBits.markFirstUnmarkedBit(); mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId; #if DEBUG_GESTURES LOGD("Gestures: FREEFORM " @@ -4616,11 +4698,13 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureIdBits.markBit(gestureId); mPointerGesture.currentGestureIdToIndex[gestureId] = i; - float deltaX = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX) - * mLocked.pointerGestureXZoomScale; - float deltaY = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY) - * mLocked.pointerGestureYZoomScale; - rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY); + const RawPointerData::Pointer& pointer = + mCurrentRawPointerData.pointerForId(touchId); + float deltaX = (pointer.x - mPointerGesture.referenceTouchX) + * mPointerGestureXZoomScale; + float deltaY = (pointer.y - mPointerGesture.referenceTouchY) + * mPointerGestureYZoomScale; + rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); mPointerGesture.currentGestureProperties[i].clear(); mPointerGesture.currentGestureProperties[i].id = gestureId; @@ -4646,7 +4730,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } } - mPointerController->setButtonState(mCurrentTouch.buttonState); + mPointerController->setButtonState(mCurrentButtonState); #if DEBUG_GESTURES LOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, " @@ -4656,8 +4740,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value, mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value); for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); + uint32_t id = idBits.clearFirstMarkedBit(); uint32_t index = mPointerGesture.currentGestureIdToIndex[id]; const PointerProperties& properties = mPointerGesture.currentGestureProperties[index]; const PointerCoords& coords = mPointerGesture.currentGestureCoords[index]; @@ -4669,8 +4752,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); } for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); + uint32_t id = idBits.clearFirstMarkedBit(); uint32_t index = mPointerGesture.lastGestureIdToIndex[id]; const PointerProperties& properties = mPointerGesture.lastGestureProperties[index]; const PointerCoords& coords = mPointerGesture.lastGestureCoords[index]; @@ -4694,8 +4776,7 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 PointerProperties pointerProperties[MAX_POINTERS]; uint32_t pointerCount = 0; while (!idBits.isEmpty()) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); + uint32_t id = idBits.clearFirstMarkedBit(); uint32_t index = idToIndex[id]; pointerProperties[pointerCount].copyFrom(properties[index]); pointerCoords[pointerCount].copyFrom(coords[index]); @@ -4723,9 +4804,10 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 } } - getDispatcher()->notifyMotion(when, getDeviceId(), source, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), source, policyFlags, action, flags, metaState, buttonState, edgeFlags, pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime); + getListener()->notifyMotion(&args); } bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties, @@ -4734,9 +4816,7 @@ bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties BitSet32 idBits) const { bool changed = false; while (!idBits.isEmpty()) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - + uint32_t id = idBits.clearFirstMarkedBit(); uint32_t inIndex = inIdToIndex[id]; uint32_t outIndex = outIdToIndex[id]; @@ -4759,24 +4839,21 @@ bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties } void TouchInputMapper::fadePointer() { - { // acquire lock - AutoMutex _l(mLock); - if (mPointerController != NULL) { - mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); - } - } // release lock + if (mPointerController != NULL) { + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); + } } -bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) { - return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue - && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue; +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::findVirtualKeyHitLocked( +const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit( int32_t x, int32_t y) { - size_t numVirtualKeys = mLocked.virtualKeys.size(); + size_t numVirtualKeys = mVirtualKeys.size(); for (size_t i = 0; i < numVirtualKeys; i++) { - const VirtualKey& virtualKey = mLocked.virtualKeys[i]; + const VirtualKey& virtualKey = mVirtualKeys[i]; #if DEBUG_VIRTUAL_KEYS LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, " @@ -4795,43 +4872,59 @@ const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked( return NULL; } -void TouchInputMapper::calculatePointerIds() { - uint32_t currentPointerCount = mCurrentTouch.pointerCount; - uint32_t lastPointerCount = mLastTouch.pointerCount; +void TouchInputMapper::assignPointerIds() { + uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount; + uint32_t lastPointerCount = mLastRawPointerData.pointerCount; + + mCurrentRawPointerData.clearIdBits(); if (currentPointerCount == 0) { // No pointers to assign. - mCurrentTouch.idBits.clear(); - } else if (lastPointerCount == 0) { + return; + } + + if (lastPointerCount == 0) { // All pointers are new. - mCurrentTouch.idBits.clear(); for (uint32_t i = 0; i < currentPointerCount; i++) { - mCurrentTouch.pointers[i].id = i; - mCurrentTouch.idToIndex[i] = i; - mCurrentTouch.idBits.markBit(i); + uint32_t id = i; + mCurrentRawPointerData.pointers[i].id = id; + mCurrentRawPointerData.idToIndex[id] = i; + mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i)); } - } else if (currentPointerCount == 1 && lastPointerCount == 1) { + 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 = mLastTouch.pointers[0].id; - mCurrentTouch.pointers[0].id = id; - mCurrentTouch.idToIndex[id] = 0; - mCurrentTouch.idBits.value = BitSet32::valueForBit(id); - } else { - // General case. - // We build a heap of squared euclidean distances between current and last pointers - // associated with the current and last pointer indices. Then, we find the best - // match (by distance) for each current pointer. - PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS]; - - uint32_t heapSize = 0; - for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount; - currentPointerIndex++) { - for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount; - lastPointerIndex++) { - int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x - - mLastTouch.pointers[lastPointerIndex].x; - int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y - - mLastTouch.pointers[lastPointerIndex].y; + 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); @@ -4842,193 +4935,174 @@ void TouchInputMapper::calculatePointerIds() { 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; - } + // 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 (heap[parentIndex].distance <= heap[childIndex].distance) { - break; - } + if (childIndex + 1 < heapSize + && heap[childIndex + 1].distance < heap[childIndex].distance) { + childIndex += 1; + } - swap(heap[parentIndex], heap[childIndex]); - parentIndex = childIndex; + if (heap[parentIndex].distance <= heap[childIndex].distance) { + break; } + + swap(heap[parentIndex], heap[childIndex]); + parentIndex = childIndex; } + } #if DEBUG_POINTER_ASSIGNMENT - LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize); - for (size_t i = 0; i < heapSize; i++) { - LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld", - i, heap[i].currentPointerIndex, heap[i].lastPointerIndex, - heap[i].distance); - } + LOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize); + for (size_t i = 0; i < heapSize; i++) { + LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld", + i, heap[i].currentPointerIndex, heap[i].lastPointerIndex, + heap[i].distance); + } #endif - // Pull matches out by increasing order of distance. - // To avoid reassigning pointers that have already been matched, the loop keeps track - // of which last and current pointers have been matched using the matchedXXXBits variables. - // It also tracks the used pointer id bits. - BitSet32 matchedLastBits(0); - BitSet32 matchedCurrentBits(0); - BitSet32 usedIdBits(0); - bool first = true; - for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) { - for (;;) { - if (first) { - // The first time through the loop, we just consume the root element of - // the heap (the one with smallest distance). - first = false; - } else { - // Previous iterations consumed the root element of the heap. - // Pop root element off of the heap (sift down). - heapSize -= 1; - LOG_ASSERT(heapSize > 0); - - // Sift down. - heap[0] = heap[heapSize]; - for (uint32_t parentIndex = 0; ;) { - uint32_t childIndex = parentIndex * 2 + 1; - if (childIndex >= heapSize) { - break; - } - - if (childIndex + 1 < heapSize - && heap[childIndex + 1].distance < heap[childIndex].distance) { - childIndex += 1; - } + // 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 (heap[parentIndex].distance <= heap[childIndex].distance) { - break; - } + if (childIndex + 1 < heapSize + && heap[childIndex + 1].distance < heap[childIndex].distance) { + childIndex += 1; + } - swap(heap[parentIndex], heap[childIndex]); - parentIndex = childIndex; + if (heap[parentIndex].distance <= heap[childIndex].distance) { + break; } + swap(heap[parentIndex], heap[childIndex]); + parentIndex = childIndex; + } + #if DEBUG_POINTER_ASSIGNMENT - LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize); - for (size_t i = 0; i < heapSize; i++) { - LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld", - i, heap[i].currentPointerIndex, heap[i].lastPointerIndex, - heap[i].distance); - } -#endif + LOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize); + for (size_t i = 0; i < heapSize; i++) { + LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld", + i, heap[i].currentPointerIndex, heap[i].lastPointerIndex, + heap[i].distance); } +#endif + } - uint32_t currentPointerIndex = heap[0].currentPointerIndex; - if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched + heapSize -= 1; - uint32_t lastPointerIndex = heap[0].lastPointerIndex; - if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched + uint32_t currentPointerIndex = heap[0].currentPointerIndex; + if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched - matchedCurrentBits.markBit(currentPointerIndex); - matchedLastBits.markBit(lastPointerIndex); + uint32_t lastPointerIndex = heap[0].lastPointerIndex; + if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched - uint32_t id = mLastTouch.pointers[lastPointerIndex].id; - mCurrentTouch.pointers[currentPointerIndex].id = id; - mCurrentTouch.idToIndex[id] = currentPointerIndex; - usedIdBits.markBit(id); + 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 - LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld", - lastPointerIndex, currentPointerIndex, id, heap[0].distance); + LOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld", + lastPointerIndex, currentPointerIndex, id, heap[0].distance); #endif - break; - } + break; } + } - // Assign fresh ids to new pointers. - if (currentPointerCount > lastPointerCount) { - for (uint32_t i = currentPointerCount - lastPointerCount; ;) { - uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit(); - uint32_t id = usedIdBits.firstUnmarkedBit(); + // 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(); - mCurrentTouch.pointers[currentPointerIndex].id = id; - mCurrentTouch.idToIndex[id] = currentPointerIndex; - usedIdBits.markBit(id); + mCurrentRawPointerData.pointers[currentPointerIndex].id = id; + mCurrentRawPointerData.idToIndex[id] = currentPointerIndex; + mCurrentRawPointerData.markIdBit(id, + mCurrentRawPointerData.isHovering(currentPointerIndex)); #if DEBUG_POINTER_ASSIGNMENT - LOGD("calculatePointerIds - assigned: cur=%d, id=%d", - currentPointerIndex, id); + LOGD("assignPointerIds - assigned: cur=%d, id=%d", + currentPointerIndex, id); #endif - - if (--i == 0) break; // done - matchedCurrentBits.markBit(currentPointerIndex); - } - } - - // Fix id bits. - mCurrentTouch.idBits = usedIdBits; } } int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { - { // acquire lock - AutoMutex _l(mLock); - - if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) { - return AKEY_STATE_VIRTUAL; - } + if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) { + return AKEY_STATE_VIRTUAL; + } - size_t numVirtualKeys = mLocked.virtualKeys.size(); - for (size_t i = 0; i < numVirtualKeys; i++) { - const VirtualKey& virtualKey = mLocked.virtualKeys[i]; - if (virtualKey.keyCode == keyCode) { - return AKEY_STATE_UP; - } + 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; } - } // release lock + } return AKEY_STATE_UNKNOWN; } int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { - { // acquire lock - AutoMutex _l(mLock); - - if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) { - return AKEY_STATE_VIRTUAL; - } + if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) { + return AKEY_STATE_VIRTUAL; + } - size_t numVirtualKeys = mLocked.virtualKeys.size(); - for (size_t i = 0; i < numVirtualKeys; i++) { - const VirtualKey& virtualKey = mLocked.virtualKeys[i]; - if (virtualKey.scanCode == scanCode) { - return AKEY_STATE_UP; - } + 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; } - } // release lock + } return AKEY_STATE_UNKNOWN; } bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) { - { // acquire lock - AutoMutex _l(mLock); - - size_t numVirtualKeys = mLocked.virtualKeys.size(); - for (size_t i = 0; i < numVirtualKeys; i++) { - const VirtualKey& virtualKey = mLocked.virtualKeys[i]; + 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; - } + for (size_t i = 0; i < numCodes; i++) { + if (virtualKey.keyCode == keyCodes[i]) { + outFlags[i] = 1; } } - } // release lock + } return true; } @@ -5067,21 +5141,18 @@ void SingleTouchInputMapper::process(const RawEvent* rawEvent) { } void SingleTouchInputMapper::sync(nsecs_t when) { - mCurrentTouch.clear(); + mCurrentRawPointerData.clear(); + mCurrentButtonState = 0; if (mTouchButtonAccumulator.isActive()) { - uint32_t buttonState = mTouchButtonAccumulator.getButtonState(); - bool isHovering = mTouchButtonAccumulator.isHovering(); - if (mSingleTouchMotionAccumulator.getAbsoluteDistance() > 0) { - isHovering = true; - } + mCurrentRawPointerData.pointerCount = 1; + mCurrentRawPointerData.idToIndex[0] = 0; - mCurrentTouch.pointerCount = 1; - mCurrentTouch.idToIndex[0] = 0; - mCurrentTouch.idBits.markBit(0); - mCurrentTouch.buttonState = buttonState; + bool isHovering = mTouchButtonAccumulator.isHovering() + || mSingleTouchMotionAccumulator.getAbsoluteDistance() > 0; + mCurrentRawPointerData.markIdBit(0, isHovering); - PointerData& outPointer = mCurrentTouch.pointers[0]; + RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0]; outPointer.id = 0; outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX(); outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY(); @@ -5097,21 +5168,24 @@ void SingleTouchInputMapper::sync(nsecs_t when) { outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; } outPointer.isHovering = isHovering; + + mCurrentButtonState = mTouchButtonAccumulator.getButtonState() + | mCursorButtonAccumulator.getButtonState(); } syncTouch(when, true); } -void SingleTouchInputMapper::configureRawAxes() { - TouchInputMapper::configureRawAxes(); +void SingleTouchInputMapper::configureRawPointerAxes() { + TouchInputMapper::configureRawPointerAxes(); mTouchButtonAccumulator.configure(getDevice()); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_DISTANCE, & mRawAxes.distance); + 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); } @@ -5172,8 +5246,9 @@ void MultiTouchInputMapper::sync(nsecs_t when) { size_t inCount = mMultiTouchMotionAccumulator.getSlotCount(); size_t outCount = 0; bool havePointerIds = true; + BitSet32 newPointerIdBits; - mCurrentTouch.clear(); + mCurrentRawPointerData.clear(); for (size_t inIndex = 0; inIndex < inCount; inIndex++) { const MultiTouchMotionAccumulator::Slot* inSlot = @@ -5191,7 +5266,7 @@ void MultiTouchInputMapper::sync(nsecs_t when) { break; // too many fingers! } - PointerData& outPointer = mCurrentTouch.pointers[outCount]; + RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount]; outPointer.x = inSlot->getX(); outPointer.y = inSlot->getY(); outPointer.pressure = inSlot->getPressure(); @@ -5210,8 +5285,9 @@ void MultiTouchInputMapper::sync(nsecs_t when) { } } - outPointer.isHovering = mTouchButtonAccumulator.isHovering() + bool isHovering = mTouchButtonAccumulator.isHovering() || inSlot->getDistance() > 0; + outPointer.isHovering = isHovering; // Assign pointer id using tracking id if available. if (havePointerIds) { @@ -5219,37 +5295,37 @@ void MultiTouchInputMapper::sync(nsecs_t when) { int32_t id = -1; if (trackingId >= 0) { for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) { - uint32_t n = idBits.firstMarkedBit(); - idBits.clearBit(n); - + uint32_t n = idBits.clearFirstMarkedBit(); if (mPointerTrackingIdMap[n] == trackingId) { id = n; } } if (id < 0 && !mPointerIdBits.isFull()) { - id = mPointerIdBits.firstUnmarkedBit(); - mPointerIdBits.markBit(id); + id = mPointerIdBits.markFirstUnmarkedBit(); mPointerTrackingIdMap[id] = trackingId; } } if (id < 0) { havePointerIds = false; - mCurrentTouch.idBits.clear(); + mCurrentRawPointerData.clearIdBits(); + newPointerIdBits.clear(); } else { outPointer.id = id; - mCurrentTouch.idToIndex[id] = outCount; - mCurrentTouch.idBits.markBit(id); + mCurrentRawPointerData.idToIndex[id] = outCount; + mCurrentRawPointerData.markIdBit(id, isHovering); + newPointerIdBits.markBit(id); } } outCount += 1; } - mCurrentTouch.pointerCount = outCount; - mCurrentTouch.buttonState = mTouchButtonAccumulator.getButtonState(); + mCurrentRawPointerData.pointerCount = outCount; + mCurrentButtonState = mTouchButtonAccumulator.getButtonState() + | mCursorButtonAccumulator.getButtonState(); - mPointerIdBits = mCurrentTouch.idBits; + mPointerIdBits = newPointerIdBits; syncTouch(when, havePointerIds); @@ -5258,26 +5334,27 @@ void MultiTouchInputMapper::sync(nsecs_t when) { } } -void MultiTouchInputMapper::configureRawAxes() { - TouchInputMapper::configureRawAxes(); +void MultiTouchInputMapper::configureRawPointerAxes() { + TouchInputMapper::configureRawPointerAxes(); mTouchButtonAccumulator.configure(getDevice()); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, &mRawAxes.x); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, &mRawAxes.y); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, &mRawAxes.touchMajor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, &mRawAxes.touchMinor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, &mRawAxes.toolMajor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, &mRawAxes.toolMinor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, &mRawAxes.orientation); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, &mRawAxes.pressure); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_DISTANCE, &mRawAxes.distance); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TRACKING_ID, &mRawAxes.trackingId); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_SLOT, &mRawAxes.slot); - - if (mRawAxes.trackingId.valid - && mRawAxes.slot.valid && mRawAxes.slot.minValue == 0 && mRawAxes.slot.maxValue > 0) { - size_t slotCount = mRawAxes.slot.maxValue + 1; + 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) { LOGW("MultiTouch Device %s reported %d slots but the framework " "only supports a maximum of %d slots at this time.", @@ -5364,7 +5441,7 @@ void JoystickInputMapper::configure(const InputReaderConfiguration* config, uint // Collect all axes. for (int32_t abs = 0; abs <= ABS_MAX; abs++) { RawAbsoluteAxisInfo rawAxisInfo; - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo); + getAbsoluteAxisInfo(abs, &rawAxisInfo); if (rawAxisInfo.valid) { // Map axis. AxisInfo axisInfo; @@ -5581,9 +5658,10 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { // TODO: Use the input device configuration to control this behavior more finely. uint32_t policyFlags = 0; - getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0); + getListener()->notifyMotion(&args); } bool JoystickInputMapper::filterAxes(bool force) { diff --git a/services/input/InputReader.h b/services/input/InputReader.h index ee6990b..f5d095d 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -18,8 +18,8 @@ #define _UI_INPUT_READER_H #include "EventHub.h" -#include "InputDispatcher.h" #include "PointerController.h" +#include "InputListener.h" #include <ui/Input.h> #include <ui/DisplayInfo.h> @@ -164,6 +164,9 @@ struct InputReaderConfiguration { * * 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: @@ -195,7 +198,7 @@ public: }; -/* Processes raw input events and sends cooked event data to an input dispatcher. */ +/* Processes raw input events and sends cooked event data to an input listener. */ class InputReaderInterface : public virtual RefBase { protected: InputReaderInterface() { } @@ -270,25 +273,27 @@ public: virtual void requestTimeoutAtTime(nsecs_t when) = 0; virtual InputReaderPolicyInterface* getPolicy() = 0; - virtual InputDispatcherInterface* getDispatcher() = 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 dispatcher. Some functions of the input reader, such as early + * 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. * - * IMPORTANT INVARIANT: - * Because the policy and dispatcher can potentially block or cause re-entrance into - * the input reader, the input reader never calls into other components while holding - * an exclusive internal lock whenever re-entrance can happen. + * 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, protected InputReaderContext { +class InputReader : public InputReaderInterface { public: InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, - const sp<InputDispatcherInterface>& dispatcher); + const sp<InputListenerInterface>& listener); virtual ~InputReader(); virtual void dump(String8& dump); @@ -313,74 +318,80 @@ public: virtual void requestRefreshConfiguration(uint32_t changes); protected: - // These methods are protected virtual so they can be overridden and instrumented - // by test cases. - virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes); + // These members are protected so they can be instrumented by test cases. + virtual InputDevice* createDeviceLocked(int32_t deviceId, + const String8& name, 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 InputReaderPolicyInterface* getPolicy(); + virtual InputListenerInterface* getListener(); + virtual EventHubInterface* getEventHub(); + } mContext; + + friend class ContextImpl; private: + Mutex mLock; + sp<EventHubInterface> mEventHub; sp<InputReaderPolicyInterface> mPolicy; - sp<InputDispatcherInterface> mDispatcher; + sp<QueuedInputListener> mQueuedListener; InputReaderConfiguration mConfig; - virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); } - virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } - virtual EventHubInterface* getEventHub() { return mEventHub.get(); } - // The event queue. static const int EVENT_BUFFER_SIZE = 256; RawEvent mEventBuffer[EVENT_BUFFER_SIZE]; - // This reader/writer lock guards the list of input devices. - // The writer lock must be held whenever the list of input devices is modified - // and then promptly released. - // The reader lock must be held whenever the list of input devices is traversed or an - // input device in the list is accessed. - // This lock only protects the registry and prevents inadvertent deletion of device objects - // that are in use. Individual devices are responsible for guarding their own internal state - // as needed for concurrent operation. - RWLock mDeviceRegistryLock; KeyedVector<int32_t, InputDevice*> mDevices; // low-level input event decoding and device management - void processEvents(const RawEvent* rawEvents, size_t count); + void processEventsLocked(const RawEvent* rawEvents, size_t count); - void addDevice(int32_t deviceId); - void removeDevice(int32_t deviceId); - void processEventsForDevice(int32_t deviceId, const RawEvent* rawEvents, size_t count); - void timeoutExpired(nsecs_t when); + void addDeviceLocked(int32_t deviceId); + void removeDeviceLocked(int32_t deviceId); + void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count); + void timeoutExpiredLocked(nsecs_t when); - void handleConfigurationChanged(nsecs_t when); + void handleConfigurationChangedLocked(nsecs_t when); - // state management for all devices - Mutex mStateLock; + int32_t mGlobalMetaState; + void updateGlobalMetaStateLocked(); + int32_t getGlobalMetaStateLocked(); - int32_t mGlobalMetaState; // guarded by mStateLock - virtual void updateGlobalMetaState(); - virtual int32_t getGlobalMetaState(); + void fadePointerLocked(); - virtual void fadePointer(); - - InputConfiguration mInputConfiguration; // guarded by mStateLock - void updateInputConfiguration(); + InputConfiguration mInputConfiguration; + void updateInputConfigurationLocked(); - nsecs_t mDisableVirtualKeysTimeout; // only accessed by reader thread - virtual void disableVirtualKeysUntil(nsecs_t time); - virtual bool shouldDropVirtualKey(nsecs_t now, + nsecs_t mDisableVirtualKeysTimeout; + void disableVirtualKeysUntilLocked(nsecs_t time); + bool shouldDropVirtualKeyLocked(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode); - nsecs_t mNextTimeout; // only accessed by reader thread, not guarded - virtual void requestTimeoutAtTime(nsecs_t when); + nsecs_t mNextTimeout; + void requestTimeoutAtTimeLocked(nsecs_t when); - uint32_t mConfigurationChangesToRefresh; // guarded by mStateLock - void refreshConfiguration(uint32_t changes); + uint32_t mConfigurationChangesToRefresh; + void refreshConfigurationLocked(uint32_t changes); // state queries typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code); - int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code, + int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc); - bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes, + bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags); }; @@ -530,6 +541,93 @@ private: }; +/* 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 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 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 bool isHovering(uint32_t pointerIndex) { + return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id); + } +}; + + /* Keeps track of the state of single-touch protocol. */ class SingleTouchMotionAccumulator { public: @@ -590,8 +688,8 @@ public: int32_t mAbsMTOrientation; int32_t mAbsMTTrackingId; int32_t mAbsMTPressure; - int32_t mAbsMTToolType; int32_t mAbsMTDistance; + int32_t mAbsMTToolType; Slot(); void clearIfInUse(); @@ -632,7 +730,7 @@ public: inline const String8 getDeviceName() { return mDevice->getName(); } inline InputReaderContext* getContext() { return mContext; } inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); } - inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); } + inline InputListenerInterface* getListener() { return mContext->getListener(); } inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } virtual uint32_t getSources() = 0; @@ -657,6 +755,8 @@ protected: InputDevice* mDevice; InputReaderContext* mContext; + status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo); + static void dumpRawAbsoluteAxisInfo(String8& dump, const RawAbsoluteAxisInfo& axis, const char* name); }; @@ -707,27 +807,25 @@ private: uint32_t mSource; int32_t mKeyboardType; + Vector<KeyDown> mKeyDowns; // keys that are down + int32_t mMetaState; + nsecs_t mDownTime; // time of most recent key down + + 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 { int32_t associatedDisplayId; bool orientationAware; } mParameters; - struct LockedState { - Vector<KeyDown> keyDowns; // keys that are down - int32_t metaState; - nsecs_t downTime; // time of most recent key down - - struct LedState { - bool avail; // led is available - bool on; // we think the led is currently on - }; - LedState capsLockLedState; - LedState numLockLedState; - LedState scrollLockLedState; - } mLocked; - - void initializeLocked(); + void initialize(); void configureParameters(); void dumpParameters(String8& dump); @@ -737,12 +835,12 @@ private: void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags); - ssize_t findKeyDownLocked(int32_t scanCode); + ssize_t findKeyDown(int32_t scanCode); - void resetLedStateLocked(); - void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led); - void updateLedStateLocked(bool reset); - void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led, + 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); }; @@ -767,8 +865,6 @@ private: // Amount that trackball needs to move in order to generate a key event. static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6; - Mutex mLock; - // Immutable configuration parameters. struct Parameters { enum Mode { @@ -801,12 +897,10 @@ private: sp<PointerControllerInterface> mPointerController; - struct LockedState { - int32_t buttonState; - nsecs_t downTime; - } mLocked; + int32_t mButtonState; + nsecs_t mDownTime; - void initializeLocked(); + void initialize(); void configureParameters(); void dumpParameters(String8& dump); @@ -835,8 +929,6 @@ public: virtual void timeoutExpired(nsecs_t when); protected: - Mutex mLock; - struct VirtualKey { int32_t keyCode; int32_t scanCode; @@ -853,82 +945,6 @@ protected: } }; - // Raw data for a single pointer. - struct PointerData { - 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 toolType; // AMOTION_EVENT_TOOL_TYPE constant - bool isHovering; - - inline bool operator== (const PointerData& other) const { - return id == other.id - && x == other.x - && y == other.y - && pressure == other.pressure - && touchMajor == other.touchMajor - && touchMinor == other.touchMinor - && toolMajor == other.toolMajor - && toolMinor == other.toolMinor - && orientation == other.orientation - && distance == other.distance - && toolType == other.toolType - && isHovering == other.isHovering; - } - inline bool operator!= (const PointerData& other) const { - return !(*this == other); - } - }; - - // Raw data for a collection of pointers including a pointer id mapping table. - struct TouchData { - uint32_t pointerCount; - PointerData pointers[MAX_POINTERS]; - BitSet32 idBits; - uint32_t idToIndex[MAX_POINTER_ID + 1]; - int32_t buttonState; - - void copyFrom(const TouchData& other) { - pointerCount = other.pointerCount; - idBits = other.idBits; - buttonState = other.buttonState; - - for (uint32_t i = 0; i < pointerCount; i++) { - pointers[i] = other.pointers[i]; - - int id = pointers[i].id; - idToIndex[id] = other.idToIndex[id]; - } - } - - inline void clear() { - pointerCount = 0; - idBits.clear(); - buttonState = 0; - } - - void getCentroid(float* outX, float* outY) { - float x = 0, y = 0; - if (pointerCount != 0) { - for (uint32_t i = 0; i < pointerCount; i++) { - x += pointers[i].x; - y += pointers[i].y; - } - x /= pointerCount; - y /= pointerCount; - } - *outX = x; - *outY = y; - } - }; - // Input sources supported by the device. uint32_t mTouchSource; // sources when reporting touch data uint32_t mPointerSource; // sources when reporting pointer gestures @@ -1038,29 +1054,23 @@ protected: float distanceScale; } mCalibration; - // Raw axis information from the driver. - struct RawAxes { - RawAbsoluteAxisInfo x; - RawAbsoluteAxisInfo y; - RawAbsoluteAxisInfo pressure; - RawAbsoluteAxisInfo touchMajor; - RawAbsoluteAxisInfo touchMinor; - RawAbsoluteAxisInfo toolMajor; - RawAbsoluteAxisInfo toolMinor; - RawAbsoluteAxisInfo orientation; - RawAbsoluteAxisInfo distance; - RawAbsoluteAxisInfo trackingId; - RawAbsoluteAxisInfo slot; - } mRawAxes; - - // Current and previous touch sample data. - TouchData mCurrentTouch; - PointerProperties mCurrentTouchProperties[MAX_POINTERS]; - PointerCoords mCurrentTouchCoords[MAX_POINTERS]; - - TouchData mLastTouch; - PointerProperties mLastTouchProperties[MAX_POINTERS]; - PointerCoords mLastTouchCoords[MAX_POINTERS]; + // 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; + + // True if we sent a HOVER_ENTER event. + bool mSentHoverEnter; // The time the primary pointer last went down. nsecs_t mDownTime; @@ -1068,113 +1078,106 @@ protected: // The pointer controller, or null if the device is not a pointer. sp<PointerControllerInterface> mPointerController; - struct LockedState { - Vector<VirtualKey> virtualKeys; - - // The surface orientation and width and height set by configureSurfaceLocked(). - int32_t surfaceOrientation; - int32_t surfaceWidth, surfaceHeight; + Vector<VirtualKey> mVirtualKeys; - // The associated display orientation and width and height set by configureSurfaceLocked(). - int32_t associatedDisplayOrientation; - int32_t associatedDisplayWidth, associatedDisplayHeight; + virtual void configureParameters(); + virtual void dumpParameters(String8& dump); + virtual void configureRawPointerAxes(); + virtual void dumpRawPointerAxes(String8& dump); + virtual bool configureSurface(); + virtual void dumpSurface(String8& dump); + virtual void configureVirtualKeys(); + virtual void dumpVirtualKeys(String8& dump); + virtual void parseCalibration(); + virtual void resolveCalibration(); + virtual void dumpCalibration(String8& dump); - // Translation and scaling factors, orientation-independent. - float xScale; - float xPrecision; + void syncTouch(nsecs_t when, bool havePointerIds); - float yScale; - float yPrecision; +private: + // The surface orientation and width and height set by configureSurface(). + int32_t mSurfaceOrientation; + int32_t mSurfaceWidth; + int32_t mSurfaceHeight; - float geometricScale; + // The associated display orientation and width and height set by configureSurface(). + int32_t mAssociatedDisplayOrientation; + int32_t mAssociatedDisplayWidth; + int32_t mAssociatedDisplayHeight; - float toolSizeLinearScale; - float toolSizeLinearBias; - float toolSizeAreaScale; - float toolSizeAreaBias; + // Translation and scaling factors, orientation-independent. + float mXScale; + float mXPrecision; - float pressureScale; + float mYScale; + float mYPrecision; - float sizeScale; + float mGeometricScale; - float orientationScale; + float mToolSizeLinearScale; + float mToolSizeLinearBias; + float mToolSizeAreaScale; + float mToolSizeAreaBias; - float distanceScale; + float mPressureScale; - // Oriented motion ranges for input device info. - struct OrientedRanges { - InputDeviceInfo::MotionRange x; - InputDeviceInfo::MotionRange y; + float mSizeScale; - bool havePressure; - InputDeviceInfo::MotionRange pressure; + float mOrientationScale; - bool haveSize; - InputDeviceInfo::MotionRange size; + float mDistanceScale; - bool haveTouchSize; - InputDeviceInfo::MotionRange touchMajor; - InputDeviceInfo::MotionRange touchMinor; + // Oriented motion ranges for input device info. + struct OrientedRanges { + InputDeviceInfo::MotionRange x; + InputDeviceInfo::MotionRange y; - bool haveToolSize; - InputDeviceInfo::MotionRange toolMajor; - InputDeviceInfo::MotionRange toolMinor; + bool havePressure; + InputDeviceInfo::MotionRange pressure; - bool haveOrientation; - InputDeviceInfo::MotionRange orientation; + bool haveSize; + InputDeviceInfo::MotionRange size; - bool haveDistance; - InputDeviceInfo::MotionRange distance; - } orientedRanges; + bool haveTouchSize; + InputDeviceInfo::MotionRange touchMajor; + InputDeviceInfo::MotionRange touchMinor; - // Oriented dimensions and precision. - float orientedSurfaceWidth, orientedSurfaceHeight; - float orientedXPrecision, orientedYPrecision; + bool haveToolSize; + InputDeviceInfo::MotionRange toolMajor; + InputDeviceInfo::MotionRange toolMinor; - struct CurrentVirtualKeyState { - bool down; - nsecs_t downTime; - int32_t keyCode; - int32_t scanCode; - } currentVirtualKey; + bool haveOrientation; + InputDeviceInfo::MotionRange orientation; - // Scale factor for gesture based pointer movements. - float pointerGestureXMovementScale; - float pointerGestureYMovementScale; + bool haveDistance; + InputDeviceInfo::MotionRange distance; + } mOrientedRanges; - // Scale factor for gesture based zooming and other freeform motions. - float pointerGestureXZoomScale; - float pointerGestureYZoomScale; + // Oriented dimensions and precision. + float mOrientedSurfaceWidth; + float mOrientedSurfaceHeight; + float mOrientedXPrecision; + float mOrientedYPrecision; - // The maximum swipe width. - float pointerGestureMaxSwipeWidth; - } mLocked; + struct CurrentVirtualKeyState { + bool down; + bool ignored; + nsecs_t downTime; + int32_t keyCode; + int32_t scanCode; + } mCurrentVirtualKey; - virtual void configureParameters(); - virtual void dumpParameters(String8& dump); - virtual void configureRawAxes(); - virtual void dumpRawAxes(String8& dump); - virtual bool configureSurfaceLocked(); - virtual void dumpSurfaceLocked(String8& dump); - virtual void configureVirtualKeysLocked(); - virtual void dumpVirtualKeysLocked(String8& dump); - virtual void parseCalibration(); - virtual void resolveCalibration(); - virtual void dumpCalibration(String8& dump); + // Scale factor for gesture based pointer movements. + float mPointerGestureXMovementScale; + float mPointerGestureYMovementScale; - enum TouchResult { - // Dispatch the touch normally. - DISPATCH_TOUCH, - // Do not dispatch the touch, but keep tracking the current stroke. - SKIP_TOUCH, - // Do not dispatch the touch, and drop all information associated with the current stoke - // so the next movement will appear as a new down. - DROP_STROKE - }; + // Scale factor for gesture based zooming and other freeform motions. + float mPointerGestureXZoomScale; + float mPointerGestureYZoomScale; - void syncTouch(nsecs_t when, bool havePointerIds); + // The maximum swipe width. + float mPointerGestureMaxSwipeWidth; -private: struct PointerDistanceHeapElement { uint32_t currentPointerIndex : 8; uint32_t lastPointerIndex : 8; @@ -1319,11 +1322,17 @@ private: } } mPointerGesture; - void initializeLocked(); + void initialize(); + + bool consumeRawTouches(nsecs_t when, uint32_t policyFlags); + void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, + int32_t keyEventAction, int32_t keyEventFlags); - TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags); void dispatchTouches(nsecs_t when, uint32_t policyFlags); - void prepareTouches(float* outXPrecision, float* outYPrecision); + void dispatchHoverExit(nsecs_t when, uint32_t policyFlags); + void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags); + void cookPointerData(); + void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout); bool preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout); @@ -1346,12 +1355,10 @@ private: PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const; - void suppressSwipeOntoVirtualKeys(nsecs_t when); - - bool isPointInsideSurfaceLocked(int32_t x, int32_t y); - const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y); + bool isPointInsideSurface(int32_t x, int32_t y); + const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); - void calculatePointerIds(); + void assignPointerIds(); }; @@ -1364,7 +1371,7 @@ public: virtual void process(const RawEvent* rawEvent); protected: - virtual void configureRawAxes(); + virtual void configureRawPointerAxes(); private: CursorButtonAccumulator mCursorButtonAccumulator; @@ -1386,7 +1393,7 @@ public: virtual void process(const RawEvent* rawEvent); protected: - virtual void configureRawAxes(); + virtual void configureRawPointerAxes(); private: CursorButtonAccumulator mCursorButtonAccumulator; diff --git a/services/input/PointerController.cpp b/services/input/PointerController.cpp index 12c7cba..1d1730d 100644 --- a/services/input/PointerController.cpp +++ b/services/input/PointerController.cpp @@ -261,9 +261,7 @@ void PointerController::setSpots(const PointerCoords* spotCoords, // Add or move spots for fingers that are down. for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - + 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; diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 8533743..4a866a8 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -48,13 +48,16 @@ static inline float avg(float x, float y) { class FakePointerController : public PointerControllerInterface { bool mHaveBounds; float mMinX, mMinY, mMaxX, mMaxY; + float mX, mY; + int32_t mButtonState; protected: virtual ~FakePointerController() { } public: FakePointerController() : - mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0) { + mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0), mX(0), mY(0), + mButtonState(0) { } void setBounds(float minX, float minY, float maxX, float maxY) { @@ -65,31 +68,40 @@ public: mMaxY = maxY; } -private: - virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const { - *outMinX = mMinX; - *outMinY = mMinY; - *outMaxX = mMaxX; - *outMaxY = mMaxY; - return mHaveBounds; - } - - virtual void move(float deltaX, float deltaY) { + virtual void setPosition(float x, float y) { + mX = x; + mY = y; } virtual void setButtonState(int32_t buttonState) { + mButtonState = buttonState; } virtual int32_t getButtonState() const { - return 0; + return mButtonState; } - virtual void setPosition(float x, float y) { + virtual void getPosition(float* outX, float* outY) const { + *outX = mX; + *outY = mY; } - virtual void getPosition(float* outX, float* outY) const { - *outX = 0; - *outY = 0; +private: + virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const { + *outMinX = mMinX; + *outMinY = mMinY; + *outMaxX = mMaxX; + *outMaxY = mMaxY; + return mHaveBounds; + } + + virtual void move(float deltaX, float deltaY) { + mX += deltaX; + if (mX < mMinX) mX = mMinX; + if (mX > mMaxX) mX = mMaxX; + mY += deltaY; + if (mY < mMinY) mY = mMinY; + if (mY > mMaxY) mY = mMaxY; } virtual void fade(Transition transition) { @@ -186,221 +198,84 @@ private: }; -// --- FakeInputDispatcher --- - -class FakeInputDispatcher : public InputDispatcherInterface { -public: - struct NotifyConfigurationChangedArgs { - NotifyConfigurationChangedArgs() : eventTime(0) { } - - nsecs_t eventTime; - }; - - struct 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; - }; - - struct 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; - uint32_t pointerCount; - Vector<PointerProperties> pointerProperties; - Vector<PointerCoords> pointerCoords; - float xPrecision; - float yPrecision; - nsecs_t downTime; - }; - - struct NotifySwitchArgs { - nsecs_t when; - int32_t switchCode; - int32_t switchValue; - uint32_t policyFlags; - }; +// --- FakeInputListener --- +class FakeInputListener : public InputListenerInterface { private: - List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgs; - List<NotifyKeyArgs> mNotifyKeyArgs; - List<NotifyMotionArgs> mNotifyMotionArgs; - List<NotifySwitchArgs> mNotifySwitchArgs; + List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgsQueue; + List<NotifyKeyArgs> mNotifyKeyArgsQueue; + List<NotifyMotionArgs> mNotifyMotionArgsQueue; + List<NotifySwitchArgs> mNotifySwitchArgsQueue; protected: - virtual ~FakeInputDispatcher() { } + virtual ~FakeInputListener() { } public: - FakeInputDispatcher() { + FakeInputListener() { } - void assertNotifyConfigurationChangedWasCalled(NotifyConfigurationChangedArgs* outArgs = NULL) { - ASSERT_FALSE(mNotifyConfigurationChangedArgs.empty()) + void assertNotifyConfigurationChangedWasCalled( + NotifyConfigurationChangedArgs* outEventArgs = NULL) { + ASSERT_FALSE(mNotifyConfigurationChangedArgsQueue.empty()) << "Expected notifyConfigurationChanged() to have been called."; - if (outArgs) { - *outArgs = *mNotifyConfigurationChangedArgs.begin(); + if (outEventArgs) { + *outEventArgs = *mNotifyConfigurationChangedArgsQueue.begin(); } - mNotifyConfigurationChangedArgs.erase(mNotifyConfigurationChangedArgs.begin()); + mNotifyConfigurationChangedArgsQueue.erase(mNotifyConfigurationChangedArgsQueue.begin()); } - void assertNotifyKeyWasCalled(NotifyKeyArgs* outArgs = NULL) { - ASSERT_FALSE(mNotifyKeyArgs.empty()) + void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = NULL) { + ASSERT_FALSE(mNotifyKeyArgsQueue.empty()) << "Expected notifyKey() to have been called."; - if (outArgs) { - *outArgs = *mNotifyKeyArgs.begin(); + if (outEventArgs) { + *outEventArgs = *mNotifyKeyArgsQueue.begin(); } - mNotifyKeyArgs.erase(mNotifyKeyArgs.begin()); + mNotifyKeyArgsQueue.erase(mNotifyKeyArgsQueue.begin()); } void assertNotifyKeyWasNotCalled() { - ASSERT_TRUE(mNotifyKeyArgs.empty()) + ASSERT_TRUE(mNotifyKeyArgsQueue.empty()) << "Expected notifyKey() to not have been called."; } - void assertNotifyMotionWasCalled(NotifyMotionArgs* outArgs = NULL) { - ASSERT_FALSE(mNotifyMotionArgs.empty()) + void assertNotifyMotionWasCalled(NotifyMotionArgs* outEventArgs = NULL) { + ASSERT_FALSE(mNotifyMotionArgsQueue.empty()) << "Expected notifyMotion() to have been called."; - if (outArgs) { - *outArgs = *mNotifyMotionArgs.begin(); + if (outEventArgs) { + *outEventArgs = *mNotifyMotionArgsQueue.begin(); } - mNotifyMotionArgs.erase(mNotifyMotionArgs.begin()); + mNotifyMotionArgsQueue.erase(mNotifyMotionArgsQueue.begin()); } void assertNotifyMotionWasNotCalled() { - ASSERT_TRUE(mNotifyMotionArgs.empty()) + ASSERT_TRUE(mNotifyMotionArgsQueue.empty()) << "Expected notifyMotion() to not have been called."; } - void assertNotifySwitchWasCalled(NotifySwitchArgs* outArgs = NULL) { - ASSERT_FALSE(mNotifySwitchArgs.empty()) + void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = NULL) { + ASSERT_FALSE(mNotifySwitchArgsQueue.empty()) << "Expected notifySwitch() to have been called."; - if (outArgs) { - *outArgs = *mNotifySwitchArgs.begin(); + if (outEventArgs) { + *outEventArgs = *mNotifySwitchArgsQueue.begin(); } - mNotifySwitchArgs.erase(mNotifySwitchArgs.begin()); + mNotifySwitchArgsQueue.erase(mNotifySwitchArgsQueue.begin()); } private: - virtual void notifyConfigurationChanged(nsecs_t eventTime) { - NotifyConfigurationChangedArgs args; - args.eventTime = eventTime; - mNotifyConfigurationChangedArgs.push_back(args); - } - - virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, 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 args; - args.eventTime = eventTime; - args.deviceId = deviceId; - args.source = source; - args.policyFlags = policyFlags; - args.action = action; - args.flags = flags; - args.keyCode = keyCode; - args.scanCode = scanCode; - args.metaState = metaState; - args.downTime = downTime; - mNotifyKeyArgs.push_back(args); - } - - virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source, - uint32_t policyFlags, int32_t action, int32_t flags, - int32_t metaState, int32_t buttonState, int32_t edgeFlags, - uint32_t pointerCount, const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords, - float xPrecision, float yPrecision, nsecs_t downTime) { - NotifyMotionArgs args; - args.eventTime = eventTime; - args.deviceId = deviceId; - args.source = source; - args.policyFlags = policyFlags; - args.action = action; - args.flags = flags; - args.metaState = metaState; - args.buttonState = buttonState; - args.edgeFlags = edgeFlags; - args.pointerCount = pointerCount; - args.pointerProperties.clear(); - args.pointerProperties.appendArray(pointerProperties, pointerCount); - args.pointerCoords.clear(); - args.pointerCoords.appendArray(pointerCoords, pointerCount); - args.xPrecision = xPrecision; - args.yPrecision = yPrecision; - args.downTime = downTime; - mNotifyMotionArgs.push_back(args); - } - - virtual void notifySwitch(nsecs_t when, - int32_t switchCode, int32_t switchValue, uint32_t policyFlags) { - NotifySwitchArgs args; - args.when = when; - args.switchCode = switchCode; - args.switchValue = switchValue; - args.policyFlags = policyFlags; - mNotifySwitchArgs.push_back(args); - } - - virtual void dump(String8& dump) { - ADD_FAILURE() << "Should never be called by input reader."; - } - - virtual void dispatchOnce() { - ADD_FAILURE() << "Should never be called by input reader."; - } - - virtual int32_t injectInputEvent(const InputEvent* event, - int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, - uint32_t policyFlags) { - ADD_FAILURE() << "Should never be called by input reader."; - return INPUT_EVENT_INJECTION_FAILED; - } - - virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) { - ADD_FAILURE() << "Should never be called by input reader."; + virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { + mNotifyConfigurationChangedArgsQueue.push_back(*args); } - virtual void setFocusedApplication( - const sp<InputApplicationHandle>& inputApplicationHandle) { - ADD_FAILURE() << "Should never be called by input reader."; + virtual void notifyKey(const NotifyKeyArgs* args) { + mNotifyKeyArgsQueue.push_back(*args); } - virtual void setInputDispatchMode(bool enabled, bool frozen) { - ADD_FAILURE() << "Should never be called by input reader."; + virtual void notifyMotion(const NotifyMotionArgs* args) { + mNotifyMotionArgsQueue.push_back(*args); } - virtual void setInputFilterEnabled(bool enabled) { - ADD_FAILURE() << "Should never be called by input reader."; - } - - virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel, - const sp<InputChannel>& toChannel) { - ADD_FAILURE() << "Should never be called by input reader."; - return 0; - } - - virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, - const sp<InputWindowHandle>& inputWindowHandle, bool monitor) { - ADD_FAILURE() << "Should never be called by input reader."; - return 0; - } - - virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) { - ADD_FAILURE() << "Should never be called by input reader."; - return 0; + virtual void notifySwitch(const NotifySwitchArgs* args) { + mNotifySwitchArgsQueue.push_back(*args); } }; @@ -551,6 +426,10 @@ public: event.value = value; event.flags = flags; mEvents.push_back(event); + + if (type == EV_ABS) { + setAbsoluteAxisValue(deviceId, scanCode, value); + } } void assertQueueIsEmpty() { @@ -765,15 +644,15 @@ private: class FakeInputReaderContext : public InputReaderContext { sp<EventHubInterface> mEventHub; sp<InputReaderPolicyInterface> mPolicy; - sp<InputDispatcherInterface> mDispatcher; + sp<InputListenerInterface> mListener; int32_t mGlobalMetaState; bool mUpdateGlobalMetaStateWasCalled; public: FakeInputReaderContext(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, - const sp<InputDispatcherInterface>& dispatcher) : - mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher), + const sp<InputListenerInterface>& listener) : + mEventHub(eventHub), mPolicy(policy), mListener(listener), mGlobalMetaState(0) { } @@ -806,8 +685,8 @@ private: return mPolicy.get(); } - virtual InputDispatcherInterface* getDispatcher() { - return mDispatcher.get(); + virtual InputListenerInterface* getListener() { + return mListener.get(); } virtual void disableVirtualKeysUntil(nsecs_t time) { @@ -969,8 +848,8 @@ class InstrumentedInputReader : public InputReader { public: InstrumentedInputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, - const sp<InputDispatcherInterface>& dispatcher) : - InputReader(eventHub, policy, dispatcher), + const sp<InputListenerInterface>& listener) : + InputReader(eventHub, policy, listener), mNextDevice(NULL) { } @@ -984,14 +863,19 @@ public: mNextDevice = device; } + InputDevice* newDevice(int32_t deviceId, const String8& name) { + return new InputDevice(&mContext, deviceId, name); + } + protected: - virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes) { + virtual InputDevice* createDeviceLocked(int32_t deviceId, + const String8& name, uint32_t classes) { if (mNextDevice) { InputDevice* device = mNextDevice; mNextDevice = NULL; return device; } - return InputReader::createDevice(deviceId, name, classes); + return InputReader::createDeviceLocked(deviceId, name, classes); } friend class InputReaderTest; @@ -1002,7 +886,7 @@ protected: class InputReaderTest : public testing::Test { protected: - sp<FakeInputDispatcher> mFakeDispatcher; + sp<FakeInputListener> mFakeListener; sp<FakeInputReaderPolicy> mFakePolicy; sp<FakeEventHub> mFakeEventHub; sp<InstrumentedInputReader> mReader; @@ -1010,15 +894,15 @@ protected: virtual void SetUp() { mFakeEventHub = new FakeEventHub(); mFakePolicy = new FakeInputReaderPolicy(); - mFakeDispatcher = new FakeInputDispatcher(); + mFakeListener = new FakeInputListener(); - mReader = new InstrumentedInputReader(mFakeEventHub, mFakePolicy, mFakeDispatcher); + mReader = new InstrumentedInputReader(mFakeEventHub, mFakePolicy, mFakeListener); } virtual void TearDown() { mReader.clear(); - mFakeDispatcher.clear(); + mFakeListener.clear(); mFakePolicy.clear(); mFakeEventHub.clear(); } @@ -1038,7 +922,7 @@ protected: FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId, const String8& name, uint32_t classes, uint32_t sources, const PropertyMap* configuration) { - InputDevice* device = new InputDevice(mReader.get(), deviceId, name); + InputDevice* device = mReader->newDevice(deviceId, name); FakeInputMapper* mapper = new FakeInputMapper(device, sources); device->addMapper(mapper); mReader->setNextDevice(device); @@ -1304,8 +1188,9 @@ TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) { TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) { addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, NULL); - FakeInputDispatcher::NotifyConfigurationChangedArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyConfigurationChangedWasCalled(&args)); + NotifyConfigurationChangedArgs args; + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME, args.eventTime); } @@ -1339,7 +1224,7 @@ protected: sp<FakeEventHub> mFakeEventHub; sp<FakeInputReaderPolicy> mFakePolicy; - sp<FakeInputDispatcher> mFakeDispatcher; + sp<FakeInputListener> mFakeListener; FakeInputReaderContext* mFakeContext; InputDevice* mDevice; @@ -1347,8 +1232,8 @@ protected: virtual void SetUp() { mFakeEventHub = new FakeEventHub(); mFakePolicy = new FakeInputReaderPolicy(); - mFakeDispatcher = new FakeInputDispatcher(); - mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher); + mFakeListener = new FakeInputListener(); + mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener); mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0); mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME)); @@ -1358,7 +1243,7 @@ protected: delete mDevice; delete mFakeContext; - mFakeDispatcher.clear(); + mFakeListener.clear(); mFakePolicy.clear(); mFakeEventHub.clear(); } @@ -1509,15 +1394,15 @@ protected: sp<FakeEventHub> mFakeEventHub; sp<FakeInputReaderPolicy> mFakePolicy; - sp<FakeInputDispatcher> mFakeDispatcher; + sp<FakeInputListener> mFakeListener; FakeInputReaderContext* mFakeContext; InputDevice* mDevice; virtual void SetUp() { mFakeEventHub = new FakeEventHub(); mFakePolicy = new FakeInputReaderPolicy(); - mFakeDispatcher = new FakeInputDispatcher(); - mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher); + mFakeListener = new FakeInputListener(); + mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener); mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME)); mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0); @@ -1526,7 +1411,7 @@ protected: virtual void TearDown() { delete mDevice; delete mFakeContext; - mFakeDispatcher.clear(); + mFakeListener.clear(); mFakePolicy.clear(); mFakeEventHub.clear(); } @@ -1570,7 +1455,7 @@ protected: static void assertPointerCoords(const PointerCoords& coords, float x, float y, float pressure, float size, float touchMajor, float touchMinor, float toolMajor, float toolMinor, - float orientation) { + float orientation, float distance) { ASSERT_NEAR(x, coords.getAxisValue(AMOTION_EVENT_AXIS_X), 1); ASSERT_NEAR(y, coords.getAxisValue(AMOTION_EVENT_AXIS_Y), 1); ASSERT_NEAR(pressure, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), EPSILON); @@ -1580,6 +1465,14 @@ protected: ASSERT_NEAR(toolMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), 1); ASSERT_NEAR(toolMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), 1); ASSERT_NEAR(orientation, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), EPSILON); + ASSERT_NEAR(distance, coords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), EPSILON); + } + + static void assertPosition(const sp<FakePointerController>& controller, float x, float y) { + float actualX, actualY; + controller->getPosition(&actualX, &actualY); + ASSERT_NEAR(x, actualX, 1); + ASSERT_NEAR(y, actualY, 1); } }; @@ -1617,9 +1510,9 @@ TEST_F(SwitchInputMapperTest, Process) { process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 0, 1, 0); - FakeInputDispatcher::NotifySwitchArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifySwitchWasCalled(&args)); - ASSERT_EQ(ARBITRARY_TIME, args.when); + NotifySwitchArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySwitchWasCalled(&args)); + ASSERT_EQ(ARBITRARY_TIME, args.eventTime); ASSERT_EQ(SW_LID, args.switchCode); ASSERT_EQ(1, args.switchValue); ASSERT_EQ(uint32_t(0), args.policyFlags); @@ -1636,16 +1529,16 @@ protected: void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper, int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) { - FakeInputDispatcher::NotifyKeyArgs args; + NotifyKeyArgs args; process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 1, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); ASSERT_EQ(originalScanCode, args.scanCode); ASSERT_EQ(rotatedKeyCode, args.keyCode); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); ASSERT_EQ(originalScanCode, args.scanCode); ASSERT_EQ(rotatedKeyCode, args.keyCode); @@ -1668,8 +1561,8 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { // Key down. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE); - FakeInputDispatcher::NotifyKeyArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + NotifyKeyArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); ASSERT_EQ(ARBITRARY_TIME, args.eventTime); @@ -1684,7 +1577,7 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { // Key up. process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime); @@ -1705,16 +1598,16 @@ TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreNotDown_DoesNotSynthesizeKeyUp) // Key down. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); // Key up. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); // Reset. Since no keys still down, should not synthesize any key ups. mapper->reset(); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); } TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) { @@ -1725,18 +1618,18 @@ TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) { // Metakey down. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); // Key down. process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, KEY_A, AKEYCODE_A, 1, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); // Reset. Since two keys are still down, should synthesize two key ups in reverse order. mapper->reset(); - FakeInputDispatcher::NotifyKeyArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + NotifyKeyArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); @@ -1747,7 +1640,7 @@ TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) { ASSERT_EQ(uint32_t(0), args.policyFlags); ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); @@ -1759,7 +1652,7 @@ TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) { ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime); // And that's it. - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); } TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { @@ -1773,8 +1666,8 @@ TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { // Metakey down. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0); - FakeInputDispatcher::NotifyKeyArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + NotifyKeyArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState()); ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled()); @@ -1782,21 +1675,21 @@ TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { // Key down. process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, KEY_A, AKEYCODE_A, 1, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState()); // Key up. process(mapper, ARBITRARY_TIME + 2, DEVICE_ID, EV_KEY, KEY_A, AKEYCODE_A, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState()); // Metakey up. process(mapper, ARBITRARY_TIME + 3, DEVICE_ID, EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_NONE, args.metaState); ASSERT_EQ(AMETA_NONE, mapper->getMetaState()); ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled()); @@ -1876,13 +1769,13 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) { // Special case: if orientation changes while key is down, we still emit the same keycode // in the key up as we did in the key down. - FakeInputDispatcher::NotifyKeyArgs args; + NotifyKeyArgs args; mFakePolicy->setDisplayInfo(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_270); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 1, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); ASSERT_EQ(KEY_UP, args.scanCode); ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode); @@ -1891,7 +1784,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) { DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_180); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); ASSERT_EQ(KEY_UP, args.scanCode); ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode); @@ -2034,17 +1927,17 @@ const int32_t CursorInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6; void CursorInputMapperTest::testMotionRotation(CursorInputMapper* mapper, int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) { - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, originalX, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, originalY, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], float(rotatedX) / TRACKBALL_MOVEMENT_THRESHOLD, float(rotatedY) / TRACKBALL_MOVEMENT_THRESHOLD, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } TEST_F(CursorInputMapperTest, WhenModeIsPointer_GetSources_ReturnsMouse) { @@ -2120,13 +2013,13 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; // Button press. // Mostly testing non x/y behavior here so we don't need to check again elsewhere. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source); @@ -2140,7 +2033,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat ASSERT_EQ(0, args.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, args.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision); ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision); ASSERT_EQ(ARBITRARY_TIME, args.downTime); @@ -2148,7 +2041,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat // Button release. Should have same down time. process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0); process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source); @@ -2162,7 +2055,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat ASSERT_EQ(0, args.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, args.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision); ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision); ASSERT_EQ(ARBITRARY_TIME, args.downTime); @@ -2173,23 +2066,23 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) { addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; // Motion in X but not Y. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Motion in Y but not X. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - 0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { @@ -2197,23 +2090,23 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; - // Button press without following sync. + // Button press. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - // Button release without following sync. + // Button release. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { @@ -2221,36 +2114,36 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; // Combined X, Y and Button. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, - 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Move X, Y a bit while pressed. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 2, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 1, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, - 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Release Button. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } TEST_F(CursorInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) { @@ -2258,22 +2151,24 @@ TEST_F(CursorInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButto addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; // Button press. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); // Button release. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action); // Reset. Should not synthesize button up since button is not pressed. mapper->reset(); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(CursorInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) { @@ -2281,20 +2176,20 @@ TEST_F(CursorInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) { addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; // Button press. process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0); process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); // Reset. Should synthesize button up. mapper->reset(); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) { @@ -2366,6 +2261,203 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1)); } +TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "pointer"); + addMapperAndConfigure(mapper); + + mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1); + mFakePointerController->setPosition(100, 200); + mFakePointerController->setButtonState(0); + + NotifyMotionArgs motionArgs; + NotifyKeyArgs keyArgs; + + // press BTN_LEFT, release BTN_LEFT + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 0, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, mFakePointerController->getButtonState()); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(0, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(0, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 0, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 0, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY, + motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY, + mFakePointerController->getButtonState()); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(0, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(0, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + // press BTN_BACK, release BTN_BACK + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 0, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(0, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + + // press BTN_SIDE, release BTN_SIDE + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 0, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(0, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + + // press BTN_FORWARD, release BTN_FORWARD + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 0, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(0, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + + // press BTN_EXTRA, release BTN_EXTRA + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 0, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(0, mFakePointerController->getButtonState()); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); +} + +TEST_F(CursorInputMapperTest, Process_WhenModeIsPointer_ShouldMoveThePointerAround) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "pointer"); + addMapperAndConfigure(mapper); + + mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1); + mFakePointerController->setPosition(100, 200); + mFakePointerController->setButtonState(0); + + NotifyMotionArgs args; + + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 10, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 20, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], + 110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); + ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f)); +} + // --- TouchInputMapperTest --- @@ -2383,8 +2475,12 @@ protected: static const int32_t RAW_PRESSURE_MAX; static const int32_t RAW_ORIENTATION_MIN; static const int32_t RAW_ORIENTATION_MAX; + static const int32_t RAW_DISTANCE_MIN; + static const int32_t RAW_DISTANCE_MAX; static const int32_t RAW_ID_MIN; static const int32_t RAW_ID_MAX; + static const int32_t RAW_SLOT_MIN; + static const int32_t RAW_SLOT_MAX; static const float X_PRECISION; static const float Y_PRECISION; @@ -2398,6 +2494,9 @@ protected: ORIENTATION = 1 << 4, MINOR = 1 << 5, ID = 1 << 6, + DISTANCE = 1 << 7, + SLOT = 1 << 8, + TOOL_TYPE = 1 << 9, }; void prepareDisplay(int32_t orientation); @@ -2420,8 +2519,12 @@ const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = RAW_TOUCH_MIN; const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = RAW_TOUCH_MAX; const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7; const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7; +const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0; +const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7; const int32_t TouchInputMapperTest::RAW_ID_MIN = 0; const int32_t TouchInputMapperTest::RAW_ID_MAX = 9; +const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0; +const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9; const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH; const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT; @@ -2470,6 +2573,8 @@ protected: void processUp(SingleTouchInputMapper* mappery); void processPressure(SingleTouchInputMapper* mapper, int32_t pressure); void processToolMajor(SingleTouchInputMapper* mapper, int32_t toolMajor); + void processDistance(SingleTouchInputMapper* mapper, int32_t distance); + void processKey(SingleTouchInputMapper* mapper, int32_t code, int32_t value); void processSync(SingleTouchInputMapper* mapper); }; @@ -2492,6 +2597,10 @@ void SingleTouchInputMapperTest::prepareAxes(int axes) { mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); } + if (axes & DISTANCE) { + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_DISTANCE, + RAW_DISTANCE_MIN, RAW_DISTANCE_MAX, 0, 0); + } } void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) { @@ -2519,6 +2628,16 @@ void SingleTouchInputMapperTest::processToolMajor( process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, 0, toolMajor, 0); } +void SingleTouchInputMapperTest::processDistance( + SingleTouchInputMapper* mapper, int32_t distance) { + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_DISTANCE, 0, distance, 0); +} + +void SingleTouchInputMapperTest::processKey( + SingleTouchInputMapper* mapper, int32_t code, int32_t value) { + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, 0, value, 0); +} + void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) { process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); } @@ -2581,14 +2700,14 @@ TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) { int32_t y = toRawY(VIRTUAL_KEYS[0].centerY); processDown(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME)); // Virtual key is up. processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); ASSERT_EQ(AKEY_STATE_UP, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME)); } @@ -2610,14 +2729,14 @@ TEST_F(SingleTouchInputMapperTest, GetScanCodeState) { int32_t y = toRawY(VIRTUAL_KEYS[0].centerY); processDown(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME)); // Virtual key is up. processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); ASSERT_EQ(AKEY_STATE_UP, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME)); } @@ -2656,13 +2775,13 @@ TEST_F(SingleTouchInputMapperTest, Reset_WhenVirtualKeysAreDown_SendsUp) { int32_t y = toRawY(VIRTUAL_KEYS[0].centerY); processDown(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); // Reset. Since key is down, synthesize key up. mapper->reset(); - FakeInputDispatcher::NotifyKeyArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + NotifyKeyArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); //ASSERT_EQ(ARBITRARY_TIME, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -2689,18 +2808,18 @@ TEST_F(SingleTouchInputMapperTest, Reset_WhenNothingIsPressed_NothingMuchHappens int32_t y = toRawY(VIRTUAL_KEYS[0].centerY); processDown(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); // Release virtual key. processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled()); // Reset. Since no key is down, nothing happens. mapper->reset(); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) { @@ -2714,7 +2833,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNor mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); - FakeInputDispatcher::NotifyKeyArgs args; + NotifyKeyArgs args; // Press virtual key. int32_t x = toRawX(VIRTUAL_KEYS[0].centerX); @@ -2722,7 +2841,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNor processDown(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -2738,7 +2857,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNor processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -2751,7 +2870,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNor ASSERT_EQ(ARBITRARY_TIME, args.downTime); // Should not have sent any motions. - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) { @@ -2765,7 +2884,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); - FakeInputDispatcher::NotifyKeyArgs keyArgs; + NotifyKeyArgs keyArgs; // Press virtual key. int32_t x = toRawX(VIRTUAL_KEYS[0].centerX); @@ -2773,7 +2892,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB processDown(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime); ASSERT_EQ(DEVICE_ID, keyArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source); @@ -2791,7 +2910,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB processMove(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime); ASSERT_EQ(DEVICE_ID, keyArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source); @@ -2804,8 +2923,8 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState); ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime); - FakeInputDispatcher::NotifyMotionArgs motionArgs; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + NotifyMotionArgs motionArgs; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -2819,7 +2938,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -2829,7 +2948,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB processMove(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -2843,7 +2962,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -2852,7 +2971,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -2866,14 +2985,14 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); // Should not have sent any more keys or motions. - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) { @@ -2887,7 +3006,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); - FakeInputDispatcher::NotifyMotionArgs motionArgs; + NotifyMotionArgs motionArgs; // Initially go down out of bounds. int32_t x = -10; @@ -2895,7 +3014,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves processDown(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); // Move into the display area. Should generate a pointer down. x = 50; @@ -2903,7 +3022,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves processMove(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -2917,7 +3036,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -2926,7 +3045,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -2940,14 +3059,14 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); // Should not have sent any more keys or motions. - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { @@ -2961,7 +3080,7 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); - FakeInputDispatcher::NotifyMotionArgs motionArgs; + NotifyMotionArgs motionArgs; // Down. int32_t x = 100; @@ -2969,7 +3088,7 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { processDown(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -2983,7 +3102,7 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -2994,7 +3113,7 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { processMove(mapper, x, y); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3008,7 +3127,7 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -3017,7 +3136,7 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3031,14 +3150,14 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) { ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); // Should not have sent any more keys or motions. - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) { @@ -3049,20 +3168,20 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotate addConfigurationProperty("touch.orientationAware", "0"); addMapperAndConfigure(mapper); - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; // Rotation 90. prepareDisplay(DISPLAY_ORIENTATION_90); processDown(mapper, toRawX(50), toRawY(75)); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled()); } TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) { @@ -3072,59 +3191,59 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) prepareAxes(POSITION); addMapperAndConfigure(mapper); - FakeInputDispatcher::NotifyMotionArgs args; + NotifyMotionArgs args; // Rotation 0. prepareDisplay(DISPLAY_ORIENTATION_0); processDown(mapper, toRawX(50), toRawY(75)); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled()); // Rotation 90. prepareDisplay(DISPLAY_ORIENTATION_90); processDown(mapper, RAW_X_MAX - toRawX(75) + RAW_X_MIN, toRawY(50)); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled()); // Rotation 180. prepareDisplay(DISPLAY_ORIENTATION_180); processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled()); // Rotation 270. prepareDisplay(DISPLAY_ORIENTATION_270); processDown(mapper, toRawX(75), RAW_Y_MAX - toRawY(50) + RAW_Y_MIN); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); processUp(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled()); } TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) { @@ -3132,7 +3251,7 @@ TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareButtons(); - prepareAxes(POSITION | PRESSURE | TOOL); + prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE); addMapperAndConfigure(mapper); // These calculations are based on the input device calibration documentation. @@ -3140,6 +3259,7 @@ TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) { int32_t rawY = 200; int32_t rawPressure = 10; int32_t rawToolMajor = 12; + int32_t rawDistance = 0; float x = toDisplayX(rawX); float y = toDisplayY(rawY); @@ -3147,16 +3267,388 @@ TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) { float size = float(rawToolMajor) / RAW_TOOL_MAX; float tool = min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * size; float touch = min(tool * pressure, tool); + float distance = float(rawDistance); processDown(mapper, rawX, rawY); processPressure(mapper, rawPressure); processToolMajor(mapper, rawToolMajor); + processDistance(mapper, rawDistance); processSync(mapper); - FakeInputDispatcher::NotifyMotionArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - x, y, pressure, size, touch, touch, tool, tool, 0)); + x, y, pressure, size, touch, touch, tool, tool, 0, distance)); +} + +TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) { + SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); + prepareAxes(POSITION); + addMapperAndConfigure(mapper); + + NotifyMotionArgs motionArgs; + NotifyKeyArgs keyArgs; + + processDown(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_EQ(0, motionArgs.buttonState); + + // press BTN_LEFT, release BTN_LEFT + processKey(mapper, BTN_LEFT, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState); + + processKey(mapper, BTN_LEFT, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE + processKey(mapper, BTN_RIGHT, 1); + processKey(mapper, BTN_MIDDLE, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY, + motionArgs.buttonState); + + processKey(mapper, BTN_RIGHT, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_MIDDLE, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + // press BTN_BACK, release BTN_BACK + processKey(mapper, BTN_BACK, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_BACK, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + + // press BTN_SIDE, release BTN_SIDE + processKey(mapper, BTN_SIDE, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_SIDE, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + + // press BTN_FORWARD, release BTN_FORWARD + processKey(mapper, BTN_FORWARD, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_FORWARD, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + + // press BTN_EXTRA, release BTN_EXTRA + processKey(mapper, BTN_EXTRA, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_EXTRA, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + + // press BTN_STYLUS, release BTN_STYLUS + processKey(mapper, BTN_STYLUS, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY, motionArgs.buttonState); + + processKey(mapper, BTN_STYLUS, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + // press BTN_STYLUS2, release BTN_STYLUS2 + processKey(mapper, BTN_STYLUS2, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState); + + processKey(mapper, BTN_STYLUS2, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + // release touch + processUp(mapper); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_EQ(0, motionArgs.buttonState); +} + +TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) { + SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); + prepareAxes(POSITION); + addMapperAndConfigure(mapper); + + NotifyMotionArgs motionArgs; + + // default tool type is finger + processDown(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + + // eraser + processKey(mapper, BTN_TOOL_RUBBER, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType); + + // stylus + processKey(mapper, BTN_TOOL_RUBBER, 0); + processKey(mapper, BTN_TOOL_PEN, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType); + + // finger + processKey(mapper, BTN_TOOL_PEN, 0); + processKey(mapper, BTN_TOOL_FINGER, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + + // stylus trumps finger + processKey(mapper, BTN_TOOL_PEN, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType); + + // eraser trumps stylus + processKey(mapper, BTN_TOOL_RUBBER, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType); + + // back to default tool type + processKey(mapper, BTN_TOOL_RUBBER, 0); + processKey(mapper, BTN_TOOL_PEN, 0); + processKey(mapper, BTN_TOOL_FINGER, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); +} + +TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) { + SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); + prepareAxes(POSITION); + mFakeEventHub->addKey(DEVICE_ID, BTN_TOOL_FINGER, AKEYCODE_UNKNOWN, 0); + addMapperAndConfigure(mapper); + + NotifyMotionArgs motionArgs; + + // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0 + processKey(mapper, BTN_TOOL_FINGER, 1); + processMove(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0)); + + // move a little + processMove(mapper, 150, 250); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); + + // down when BTN_TOUCH is pressed, pressure defaults to 1 + processKey(mapper, BTN_TOUCH, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0)); + + // up when BTN_TOUCH is released, hover restored + processKey(mapper, BTN_TOUCH, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); + + // exit hover when pointer goes away + processKey(mapper, BTN_TOOL_FINGER, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); +} + +TEST_F(SingleTouchInputMapperTest, Process_WhenAbsDistanceIsPresent_HoversIfItsValueIsGreaterThanZero) { + SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); + prepareAxes(POSITION | DISTANCE); + addMapperAndConfigure(mapper); + + NotifyMotionArgs motionArgs; + + // initially hovering because distance is 1, pressure defaults to 0 + processDown(mapper, 100, 200); + processDistance(mapper, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 1)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 1)); + + // move a little + processMove(mapper, 150, 250); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); + + // down when distance goes to 0, pressure defaults to 1 + processDistance(mapper, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0)); + + // up when distance goes to 1, hover restored + processDistance(mapper, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); + + // exit hover when pointer goes away + processUp(mapper); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); } @@ -3173,7 +3665,11 @@ protected: void processToolMinor(MultiTouchInputMapper* mapper, int32_t toolMinor); void processOrientation(MultiTouchInputMapper* mapper, int32_t orientation); void processPressure(MultiTouchInputMapper* mapper, int32_t pressure); + void processDistance(MultiTouchInputMapper* mapper, int32_t distance); void processId(MultiTouchInputMapper* mapper, int32_t id); + void processSlot(MultiTouchInputMapper* mapper, int32_t slot); + void processToolType(MultiTouchInputMapper* mapper, int32_t toolType); + void processKey(MultiTouchInputMapper* mapper, int32_t code, int32_t value); void processMTSync(MultiTouchInputMapper* mapper); void processSync(MultiTouchInputMapper* mapper); }; @@ -3209,10 +3705,23 @@ void MultiTouchInputMapperTest::prepareAxes(int axes) { mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0); } + if (axes & DISTANCE) { + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_DISTANCE, + RAW_DISTANCE_MIN, RAW_DISTANCE_MAX, 0, 0); + } if (axes & ID) { mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0, 0); } + if (axes & SLOT) { + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_SLOT, + RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0); + mFakeEventHub->setAbsoluteAxisValue(DEVICE_ID, ABS_MT_SLOT, 0); + } + if (axes & TOOL_TYPE) { + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOOL_TYPE, + 0, MT_TOOL_MAX, 0, 0); + } } void MultiTouchInputMapperTest::processPosition( @@ -3251,11 +3760,31 @@ void MultiTouchInputMapperTest::processPressure( process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, 0, pressure, 0); } +void MultiTouchInputMapperTest::processDistance( + MultiTouchInputMapper* mapper, int32_t distance) { + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_DISTANCE, 0, distance, 0); +} + void MultiTouchInputMapperTest::processId( MultiTouchInputMapper* mapper, int32_t id) { process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, 0, id, 0); } +void MultiTouchInputMapperTest::processSlot( + MultiTouchInputMapper* mapper, int32_t slot) { + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_SLOT, 0, slot, 0); +} + +void MultiTouchInputMapperTest::processToolType( + MultiTouchInputMapper* mapper, int32_t toolType) { + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOOL_TYPE, 0, toolType, 0); +} + +void MultiTouchInputMapperTest::processKey( + MultiTouchInputMapper* mapper, int32_t code, int32_t value) { + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, 0, value, 0); +} + void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) { process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0, 0, 0); } @@ -3275,7 +3804,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); - FakeInputDispatcher::NotifyMotionArgs motionArgs; + NotifyMotionArgs motionArgs; // Two fingers down at once. int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500; @@ -3285,7 +3814,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3299,12 +3828,12 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3321,9 +3850,9 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -3336,7 +3865,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3352,9 +3881,9 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -3365,7 +3894,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3382,14 +3911,14 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3403,7 +3932,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(1, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -3414,7 +3943,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3428,7 +3957,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(1, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -3441,7 +3970,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3458,9 +3987,9 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -3471,7 +4000,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3488,14 +4017,14 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3509,7 +4038,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); @@ -3518,7 +4047,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime); ASSERT_EQ(DEVICE_ID, motionArgs.deviceId); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source); @@ -3532,14 +4061,14 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON); ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON); ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime); // Should not have sent any more keys or motions. - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) { @@ -3552,7 +4081,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); - FakeInputDispatcher::NotifyMotionArgs motionArgs; + NotifyMotionArgs motionArgs; // Two fingers down at once. int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500; @@ -3564,15 +4093,15 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); ASSERT_EQ(size_t(1), motionArgs.pointerCount); ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), motionArgs.action); ASSERT_EQ(size_t(2), motionArgs.pointerCount); @@ -3581,9 +4110,9 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); // Move. x1 += 10; y1 += 15; x2 += 5; y2 -= 10; @@ -3595,7 +4124,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); ASSERT_EQ(size_t(2), motionArgs.pointerCount); ASSERT_EQ(0, motionArgs.pointerProperties[0].id); @@ -3603,9 +4132,9 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); // First finger up. x2 += 15; y2 -= 20; @@ -3614,7 +4143,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), motionArgs.action); ASSERT_EQ(size_t(2), motionArgs.pointerCount); @@ -3623,17 +4152,17 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); ASSERT_EQ(size_t(1), motionArgs.pointerCount); ASSERT_EQ(1, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); // Move. x2 += 20; y2 -= 25; @@ -3642,13 +4171,13 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); ASSERT_EQ(size_t(1), motionArgs.pointerCount); ASSERT_EQ(1, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); // New finger down. int32_t x3 = 700, y3 = 300; @@ -3660,7 +4189,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), motionArgs.action); ASSERT_EQ(size_t(2), motionArgs.pointerCount); @@ -3669,9 +4198,9 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); // Second finger up. x3 += 30; y3 -= 20; @@ -3680,7 +4209,7 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), motionArgs.action); ASSERT_EQ(size_t(2), motionArgs.pointerCount); @@ -3689,40 +4218,211 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId ASSERT_EQ(1, motionArgs.pointerProperties[1].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], - toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); ASSERT_EQ(size_t(1), motionArgs.pointerCount); ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); // Last finger up. processMTSync(mapper); processSync(mapper); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); ASSERT_EQ(size_t(1), motionArgs.pointerCount); ASSERT_EQ(0, motionArgs.pointerProperties[0].id); ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], - toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0)); + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); // Should not have sent any more keys or motions. - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled()); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); +} + +TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) { + MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION | ID | SLOT); + prepareVirtualKeys(); + addMapperAndConfigure(mapper); + + mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); + + NotifyMotionArgs motionArgs; + + // Two fingers down at once. + int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500; + processPosition(mapper, x1, y1); + processId(mapper, 1); + processSlot(mapper, 1); + processPosition(mapper, x2, y2); + processId(mapper, 2); + processSync(mapper); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_EQ(size_t(1), motionArgs.pointerCount); + ASSERT_EQ(0, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), + motionArgs.action); + ASSERT_EQ(size_t(2), motionArgs.pointerCount); + ASSERT_EQ(0, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_EQ(1, motionArgs.pointerProperties[1].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); + + // Move. + x1 += 10; y1 += 15; x2 += 5; y2 -= 10; + processSlot(mapper, 0); + processPosition(mapper, x1, y1); + processSlot(mapper, 1); + processPosition(mapper, x2, y2); + processSync(mapper); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(size_t(2), motionArgs.pointerCount); + ASSERT_EQ(0, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_EQ(1, motionArgs.pointerProperties[1].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); + + // First finger up. + x2 += 15; y2 -= 20; + processSlot(mapper, 0); + processId(mapper, -1); + processSlot(mapper, 1); + processPosition(mapper, x2, y2); + processSync(mapper); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), + motionArgs.action); + ASSERT_EQ(size_t(2), motionArgs.pointerCount); + ASSERT_EQ(0, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_EQ(1, motionArgs.pointerProperties[1].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0)); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(size_t(1), motionArgs.pointerCount); + ASSERT_EQ(1, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); + + // Move. + x2 += 20; y2 -= 25; + processPosition(mapper, x2, y2); + processSync(mapper); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(size_t(1), motionArgs.pointerCount); + ASSERT_EQ(1, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); + + // New finger down. + int32_t x3 = 700, y3 = 300; + processPosition(mapper, x2, y2); + processSlot(mapper, 0); + processId(mapper, 3); + processPosition(mapper, x3, y3); + processSync(mapper); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), + motionArgs.action); + ASSERT_EQ(size_t(2), motionArgs.pointerCount); + ASSERT_EQ(0, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_EQ(1, motionArgs.pointerProperties[1].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); + + // Second finger up. + x3 += 30; y3 -= 20; + processSlot(mapper, 1); + processId(mapper, -1); + processSlot(mapper, 0); + processPosition(mapper, x3, y3); + processSync(mapper); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), + motionArgs.action); + ASSERT_EQ(size_t(2), motionArgs.pointerCount); + ASSERT_EQ(0, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_EQ(1, motionArgs.pointerProperties[1].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], + toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(size_t(1), motionArgs.pointerCount); + ASSERT_EQ(0, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); + + // Last finger up. + processId(mapper, -1); + processSync(mapper); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_EQ(size_t(1), motionArgs.pointerCount); + ASSERT_EQ(0, motionArgs.pointerProperties[0].id); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0)); + + // Should not have sent any more keys or motions. + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) { MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice); addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); - prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR); + prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE); addMapperAndConfigure(mapper); // These calculations are based on the input device calibration documentation. @@ -3733,6 +4433,7 @@ TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) { int32_t rawToolMajor = 9; int32_t rawToolMinor = 8; int32_t rawPressure = 11; + int32_t rawDistance = 0; int32_t rawOrientation = 3; int32_t id = 5; @@ -3745,6 +4446,7 @@ TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) { float touchMajor = min(toolMajor * pressure, toolMajor); float touchMinor = min(toolMinor * pressure, toolMinor); float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2; + float distance = float(rawDistance); processPosition(mapper, rawX, rawY); processTouchMajor(mapper, rawTouchMajor); @@ -3753,15 +4455,16 @@ TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) { processToolMinor(mapper, rawToolMinor); processPressure(mapper, rawPressure); processOrientation(mapper, rawOrientation); + processDistance(mapper, rawDistance); processId(mapper, id); processMTSync(mapper); processSync(mapper); - FakeInputDispatcher::NotifyMotionArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(0, args.pointerProperties[0].id); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation)); + x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation, distance)); } TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) { @@ -3800,10 +4503,10 @@ TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) processMTSync(mapper); processSync(mapper); - FakeInputDispatcher::NotifyMotionArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, 0)); + x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0)); } TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_SummedLinearCalibration) { @@ -3850,18 +4553,18 @@ TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_SummedLinear processMTSync(mapper); processSync(mapper); - FakeInputDispatcher::NotifyMotionArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), args.action); ASSERT_EQ(size_t(2), args.pointerCount); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - x, y, pressure, size, touch, touch, tool, tool, 0)); + x, y, pressure, size, touch, touch, tool, tool, 0, 0)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1], - x2, y2, pressure, size, touch, touch, tool, tool, 0)); + x2, y2, pressure, size, touch, touch, tool, tool, 0, 0)); } TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_AreaCalibration) { @@ -3899,10 +4602,395 @@ TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_AreaCalibrat processMTSync(mapper); processSync(mapper); - FakeInputDispatcher::NotifyMotionArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], - x, y, pressure, size, touch, touch, tool, tool, 0)); + x, y, pressure, size, touch, touch, tool, tool, 0, 0)); +} + +TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) { + MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION | ID | SLOT); + addMapperAndConfigure(mapper); + + NotifyMotionArgs motionArgs; + NotifyKeyArgs keyArgs; + + processId(mapper, 1); + processPosition(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_EQ(0, motionArgs.buttonState); + + // press BTN_LEFT, release BTN_LEFT + processKey(mapper, BTN_LEFT, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState); + + processKey(mapper, BTN_LEFT, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE + processKey(mapper, BTN_RIGHT, 1); + processKey(mapper, BTN_MIDDLE, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY, + motionArgs.buttonState); + + processKey(mapper, BTN_RIGHT, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_MIDDLE, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + // press BTN_BACK, release BTN_BACK + processKey(mapper, BTN_BACK, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_BACK, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + + // press BTN_SIDE, release BTN_SIDE + processKey(mapper, BTN_SIDE, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_SIDE, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); + + // press BTN_FORWARD, release BTN_FORWARD + processKey(mapper, BTN_FORWARD, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_FORWARD, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + + // press BTN_EXTRA, release BTN_EXTRA + processKey(mapper, BTN_EXTRA, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + processKey(mapper, BTN_EXTRA, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); + ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); + + // press BTN_STYLUS, release BTN_STYLUS + processKey(mapper, BTN_STYLUS, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY, motionArgs.buttonState); + + processKey(mapper, BTN_STYLUS, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + // press BTN_STYLUS2, release BTN_STYLUS2 + processKey(mapper, BTN_STYLUS2, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState); + + processKey(mapper, BTN_STYLUS2, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(0, motionArgs.buttonState); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + + // release touch + processId(mapper, -1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_EQ(0, motionArgs.buttonState); } +TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) { + MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION | ID | SLOT | TOOL_TYPE); + addMapperAndConfigure(mapper); + + NotifyMotionArgs motionArgs; + + // default tool type is finger + processId(mapper, 1); + processPosition(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + + // eraser + processKey(mapper, BTN_TOOL_RUBBER, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType); + + // stylus + processKey(mapper, BTN_TOOL_RUBBER, 0); + processKey(mapper, BTN_TOOL_PEN, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType); + + // finger + processKey(mapper, BTN_TOOL_PEN, 0); + processKey(mapper, BTN_TOOL_FINGER, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + + // stylus trumps finger + processKey(mapper, BTN_TOOL_PEN, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType); + + // eraser trumps stylus + processKey(mapper, BTN_TOOL_RUBBER, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType); + + // MT tool type trumps BTN tool types: MT_TOOL_FINGER + processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); + + // MT tool type trumps BTN tool types: MT_TOOL_PEN + processToolType(mapper, MT_TOOL_PEN); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType); + + // back to default tool type + processToolType(mapper, -1); // use a deliberately undefined tool type, for testing + processKey(mapper, BTN_TOOL_RUBBER, 0); + processKey(mapper, BTN_TOOL_PEN, 0); + processKey(mapper, BTN_TOOL_FINGER, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); + ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType); +} + +TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) { + MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION | ID | SLOT); + mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, AKEYCODE_UNKNOWN, 0); + addMapperAndConfigure(mapper); + + NotifyMotionArgs motionArgs; + + // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0 + processId(mapper, 1); + processPosition(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0)); + + // move a little + processPosition(mapper, 150, 250); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); + + // down when BTN_TOUCH is pressed, pressure defaults to 1 + processKey(mapper, BTN_TOUCH, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0)); + + // up when BTN_TOUCH is released, hover restored + processKey(mapper, BTN_TOUCH, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); + + // exit hover when pointer goes away + processId(mapper, -1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); +} + +TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTDistanceIsPresent_HoversIfItsValueIsGreaterThanZero) { + MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice); + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION | ID | SLOT | DISTANCE); + addMapperAndConfigure(mapper); + + NotifyMotionArgs motionArgs; + + // initially hovering because distance is 1, pressure defaults to 0 + processId(mapper, 1); + processPosition(mapper, 100, 200); + processDistance(mapper, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 1)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 1)); + + // move a little + processPosition(mapper, 150, 250); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); + + // down when distance goes to 0, pressure defaults to 1 + processDistance(mapper, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0)); + + // up when distance goes to 1, hover restored + processDistance(mapper, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); + + // exit hover when pointer goes away + processId(mapper, -1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], + toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 1)); +} + + } // namespace android diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index bdd8938..2e3d6dd 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -129,6 +129,7 @@ import javax.crypto.spec.SecretKeySpec; class BackupManagerService extends IBackupManager.Stub { private static final String TAG = "BackupManagerService"; private static final boolean DEBUG = true; + private static final boolean MORE_DEBUG = false; // Name and current contents version of the full-backup manifest file static final String BACKUP_MANIFEST_FILENAME = "_manifest"; @@ -851,10 +852,10 @@ class BackupManagerService extends IBackupManager.Stub { info = mPackageManager.getPackageInfo(pkg, 0); mEverStoredApps.add(pkg); temp.writeUTF(pkg); - if (DEBUG) Slog.v(TAG, " + " + pkg); + if (MORE_DEBUG) Slog.v(TAG, " + " + pkg); } catch (NameNotFoundException e) { // nope, this package was uninstalled; don't include it - if (DEBUG) Slog.v(TAG, " - " + pkg); + if (MORE_DEBUG) Slog.v(TAG, " - " + pkg); } } } catch (EOFException e) { @@ -1246,7 +1247,7 @@ class BackupManagerService extends IBackupManager.Stub { private void addPackageParticipantsLockedInner(String packageName, List<PackageInfo> targetPkgs) { - if (DEBUG) { + if (MORE_DEBUG) { Slog.v(TAG, "Adding " + targetPkgs.size() + " backup participants:"); for (PackageInfo p : targetPkgs) { Slog.v(TAG, " " + p + " agent=" + p.applicationInfo.backupAgentName @@ -1296,7 +1297,7 @@ class BackupManagerService extends IBackupManager.Stub { private void removePackageParticipantsLockedInner(String packageName, List<String> allPackageNames) { - if (DEBUG) { + if (MORE_DEBUG) { Slog.v(TAG, "removePackageParticipantsLockedInner (" + packageName + ") removing " + allPackageNames.size() + " entries"); for (String p : allPackageNames) { @@ -1320,7 +1321,7 @@ class BackupManagerService extends IBackupManager.Stub { // We can't just remove(app) because the instances are different. for (ApplicationInfo entry: set) { if (entry.packageName.equals(pkg)) { - if (DEBUG) Slog.v(TAG, " removing participant " + pkg); + if (MORE_DEBUG) Slog.v(TAG, " removing participant " + pkg); set.remove(entry); removeEverBackedUp(pkg); break; @@ -1403,7 +1404,8 @@ class BackupManagerService extends IBackupManager.Stub { // Remove our awareness of having ever backed up the given package void removeEverBackedUp(String packageName) { - if (DEBUG) Slog.v(TAG, "Removing backed-up knowledge of " + packageName + ", new set:"); + if (DEBUG) Slog.v(TAG, "Removing backed-up knowledge of " + packageName); + if (MORE_DEBUG) Slog.v(TAG, "New set:"); synchronized (mEverStoredApps) { // Rewrite the file and rename to overwrite. If we reboot in the middle, @@ -1416,7 +1418,7 @@ class BackupManagerService extends IBackupManager.Stub { mEverStoredApps.remove(packageName); for (String s : mEverStoredApps) { known.writeUTF(s); - if (DEBUG) Slog.v(TAG, " " + s); + if (MORE_DEBUG) Slog.v(TAG, " " + s); } known.close(); known = null; @@ -1460,7 +1462,7 @@ class BackupManagerService extends IBackupManager.Stub { if (DEBUG) Slog.v(TAG, "Ancestral packages: " + mAncestralPackages.size()); for (String pkgName : mAncestralPackages) { af.writeUTF(pkgName); - if (DEBUG) Slog.v(TAG, " " + pkgName); + if (MORE_DEBUG) Slog.v(TAG, " " + pkgName); } } af.close(); @@ -1523,7 +1525,7 @@ class BackupManagerService extends IBackupManager.Stub { try { PackageInfo info = mPackageManager.getPackageInfo(packageName, 0); if ((info.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) { - if (DEBUG) Slog.i(TAG, "allowClearUserData=false so not wiping " + if (MORE_DEBUG) Slog.i(TAG, "allowClearUserData=false so not wiping " + packageName); return; } @@ -1593,13 +1595,13 @@ class BackupManagerService extends IBackupManager.Stub { } } mBackupHandler.removeMessages(MSG_TIMEOUT); - if (DEBUG) Slog.v(TAG, "operation " + Integer.toHexString(token) + if (MORE_DEBUG) Slog.v(TAG, "operation " + Integer.toHexString(token) + " complete: finalState=" + finalState); return finalState == OP_ACKNOWLEDGED; } void prepareOperationTimeout(int token, long interval) { - if (DEBUG) Slog.v(TAG, "starting timeout: token=" + Integer.toHexString(token) + if (MORE_DEBUG) Slog.v(TAG, "starting timeout: token=" + Integer.toHexString(token) + " interval=" + interval); synchronized (mCurrentOpLock) { mCurrentOperations.put(token, OP_PENDING); @@ -1937,7 +1939,7 @@ class BackupManagerService extends IBackupManager.Stub { BackupDataOutput output = new BackupDataOutput( mPipe.getFileDescriptor()); - if (DEBUG) Slog.d(TAG, "Writing manifest for " + mPackage.packageName); + if (MORE_DEBUG) Slog.d(TAG, "Writing manifest for " + mPackage.packageName); writeAppManifest(mPackage, mManifestFile, mSendApk); FullBackup.backupToTar(mPackage.packageName, null, null, mFilesDir.getAbsolutePath(), @@ -1948,7 +1950,7 @@ class BackupManagerService extends IBackupManager.Stub { writeApkToBackup(mPackage, output); } - if (DEBUG) Slog.d(TAG, "Calling doFullBackup()"); + if (DEBUG) Slog.d(TAG, "Calling doFullBackup() on " + mPackage.packageName); prepareOperationTimeout(mToken, TIMEOUT_FULL_BACKUP_INTERVAL); mAgent.doFullBackup(mPipe, mToken, mBackupManagerBinder); } catch (IOException e) { @@ -2285,7 +2287,7 @@ class BackupManagerService extends IBackupManager.Stub { // check for .obb and save those too final File obbDir = Environment.getExternalStorageAppObbDirectory(pkg.packageName); if (obbDir != null) { - if (DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath()); + if (MORE_DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath()); File[] obbFiles = obbDir.listFiles(); if (obbFiles != null) { final String obbDirName = obbDir.getAbsolutePath(); @@ -2374,10 +2376,10 @@ class BackupManagerService extends IBackupManager.Stub { // The agent was running with a stub Application object, so shut it down. if (app.uid != Process.SYSTEM_UID && app.uid != Process.PHONE_UID) { - if (DEBUG) Slog.d(TAG, "Backup complete, killing host process"); + if (MORE_DEBUG) Slog.d(TAG, "Backup complete, killing host process"); mActivityManager.killApplicationProcess(app.processName, app.uid); } else { - if (DEBUG) Slog.d(TAG, "Not killing after restore: " + app.processName); + if (MORE_DEBUG) Slog.d(TAG, "Not killing after restore: " + app.processName); } } catch (RemoteException e) { Slog.d(TAG, "Lost app trying to shut down"); @@ -2600,7 +2602,7 @@ class BackupManagerService extends IBackupManager.Stub { didRestore = restoreOneFile(in, buffer); } while (didRestore); - if (DEBUG) Slog.v(TAG, "Done consuming input tarfile, total bytes=" + mBytes); + if (MORE_DEBUG) Slog.v(TAG, "Done consuming input tarfile, total bytes=" + mBytes); } catch (IOException e) { Slog.e(TAG, "Unable to read restore input"); } finally { @@ -2624,7 +2626,7 @@ class BackupManagerService extends IBackupManager.Stub { } sendEndRestore(); mWakelock.release(); - if (DEBUG) Slog.d(TAG, "Full restore pass complete."); + Slog.d(TAG, "Full restore pass complete."); } } @@ -2722,7 +2724,7 @@ class BackupManagerService extends IBackupManager.Stub { try { info = readTarHeaders(instream); if (info != null) { - if (DEBUG) { + if (MORE_DEBUG) { dumpFileMetadata(info); } @@ -2910,7 +2912,6 @@ class BackupManagerService extends IBackupManager.Stub { boolean pipeOkay = true; FileOutputStream pipe = new FileOutputStream( mPipes[1].getFileDescriptor()); - if (DEBUG) Slog.d(TAG, "Piping data to agent"); while (toCopy > 0) { int toRead = (toCopy > buffer.length) ? buffer.length : (int)toCopy; @@ -3629,7 +3630,7 @@ class BackupManagerService extends IBackupManager.Stub { // Allow unsigned apps, but not signed on one device and unsigned on the other // !!! TODO: is this the right policy? Signature[] deviceSigs = target.signatures; - if (DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + if (MORE_DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs); if ((storedSigs == null || storedSigs.length == 0) && (deviceSigs == null || deviceSigs.length == 0)) { @@ -4189,7 +4190,7 @@ class BackupManagerService extends IBackupManager.Stub { // in the set; we want to avoid touching the disk redundantly. writeToJournalLocked(packageName); - if (DEBUG) { + if (MORE_DEBUG) { int numKeys = mPendingBackups.size(); Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:"); for (BackupRequest b : mPendingBackups.values()) { @@ -4387,7 +4388,7 @@ class BackupManagerService extends IBackupManager.Stub { } Binder.restoreCallingIdentity(oldId); } - if (DEBUG) Slog.d(TAG, "Full backup done; returning to caller"); + if (MORE_DEBUG) Slog.d(TAG, "Full backup done; returning to caller"); } public void fullRestore(ParcelFileDescriptor fd) { @@ -4446,7 +4447,7 @@ class BackupManagerService extends IBackupManager.Stub { } void startConfirmationTimeout(int token, FullParams params) { - if (DEBUG) Slog.d(TAG, "Posting conf timeout msg after " + if (MORE_DEBUG) Slog.d(TAG, "Posting conf timeout msg after " + TIMEOUT_FULL_CONFIRMATION + " millis"); Message msg = mBackupHandler.obtainMessage(MSG_FULL_CONFIRMATION_TIMEOUT, token, 0, params); @@ -4625,7 +4626,7 @@ class BackupManagerService extends IBackupManager.Stub { public String getCurrentTransport() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "getCurrentTransport"); - if (DEBUG) Slog.v(TAG, "... getCurrentTransport() returning " + mCurrentTransport); + if (MORE_DEBUG) Slog.v(TAG, "... getCurrentTransport() returning " + mCurrentTransport); return mCurrentTransport; } @@ -4682,7 +4683,7 @@ class BackupManagerService extends IBackupManager.Stub { if (transport != null) { try { final Intent intent = transport.configurationIntent(); - if (DEBUG) Slog.d(TAG, "getConfigurationIntent() returning config intent " + if (MORE_DEBUG) Slog.d(TAG, "getConfigurationIntent() returning config intent " + intent); return intent; } catch (RemoteException e) { @@ -4708,7 +4709,7 @@ class BackupManagerService extends IBackupManager.Stub { if (transport != null) { try { final String text = transport.currentDestinationString(); - if (DEBUG) Slog.d(TAG, "getDestinationString() returning " + text); + if (MORE_DEBUG) Slog.d(TAG, "getDestinationString() returning " + text); return text; } catch (RemoteException e) { /* fall through to return null */ @@ -4853,7 +4854,7 @@ class BackupManagerService extends IBackupManager.Stub { // completed the given outstanding asynchronous backup/restore operation. public void opComplete(int token) { synchronized (mCurrentOpLock) { - if (DEBUG) Slog.v(TAG, "opComplete: " + Integer.toHexString(token)); + if (MORE_DEBUG) Slog.v(TAG, "opComplete: " + Integer.toHexString(token)); mCurrentOperations.put(token, OP_ACKNOWLEDGED); mCurrentOpLock.notifyAll(); } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 39d2b1c..a59b6c0 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -21,6 +21,8 @@ import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.provider.Settings.Secure.NETSTATS_ENABLED; +import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; +import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.content.Context; import android.content.pm.PackageManager; @@ -54,7 +56,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.Inet4Address; import java.net.InetAddress; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -89,8 +90,10 @@ class NetworkManagementService extends INetworkManagementService.Stub { private static final String KEY_IFACE = "iface"; private static final String KEY_TAG_HEX = "acct_tag_hex"; private static final String KEY_UID = "uid_tag_int"; - private static final String KEY_RX = "rx_bytes"; - private static final String KEY_TX = "tx_bytes"; + private static final String KEY_RX_BYTES = "rx_bytes"; + private static final String KEY_RX_PACKETS = "rx_packets"; + private static final String KEY_TX_BYTES = "tx_bytes"; + private static final String KEY_TX_PACKETS = "tx_packets"; class NetdResponseCode { /* Keep in sync with system/netd/ResponseCode.h */ @@ -203,8 +206,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { Slog.d(TAG, "not enabling bandwidth control"); } - SystemProperties.set(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED, - mBandwidthControlEnabled ? "1" : "0"); + SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); } public void registerObserver(INetworkManagementEventObserver obs) { @@ -1249,6 +1251,9 @@ class NetworkManagementService extends INetworkManagementService.Stub { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24); final NetworkStats.Entry entry = new NetworkStats.Entry(); + // TODO: remove knownLines check once 5087722 verified + final HashSet<String> knownLines = Sets.newHashSet(); + final ArrayList<String> keys = Lists.newArrayList(); final ArrayList<String> values = Lists.newArrayList(); final HashMap<String, String> parsed = Maps.newHashMap(); @@ -1266,14 +1271,18 @@ class NetworkManagementService extends INetworkManagementService.Stub { splitLine(line, values); parseLine(keys, values, parsed); + if (!knownLines.add(line)) { + throw new IllegalStateException("encountered duplicate proc entry"); + } + try { - // TODO: add rxPackets/txPackets once kernel exports entry.iface = parsed.get(KEY_IFACE); - entry.tag = NetworkManagementSocketTagger.kernelToTag( - parsed.get(KEY_TAG_HEX)); - entry.uid = Integer.parseInt(parsed.get(KEY_UID)); - entry.rxBytes = Long.parseLong(parsed.get(KEY_RX)); - entry.txBytes = Long.parseLong(parsed.get(KEY_TX)); + entry.tag = kernelToTag(parsed.get(KEY_TAG_HEX)); + entry.uid = getParsedInt(parsed, KEY_UID); + entry.rxBytes = getParsedLong(parsed, KEY_RX_BYTES); + entry.rxPackets = getParsedLong(parsed, KEY_RX_PACKETS); + entry.txBytes = getParsedLong(parsed, KEY_TX_BYTES); + entry.txPackets = getParsedLong(parsed, KEY_TX_PACKETS); if (limitUid == UID_ALL || limitUid == entry.uid) { stats.addValues(entry); @@ -1291,6 +1300,16 @@ class NetworkManagementService extends INetworkManagementService.Stub { return stats; } + private static int getParsedInt(HashMap<String, String> parsed, String key) { + final String value = parsed.get(key); + return value != null ? Integer.parseInt(value) : 0; + } + + private static long getParsedLong(HashMap<String, String> parsed, String key) { + final String value = parsed.get(key); + return value != null ? Long.parseLong(value) : 0; + } + /** * Build {@link NetworkStats} with detailed UID statistics. * diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java index 837778e..e97df84 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -80,7 +80,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { // Set the current spell checker if there is one or more spell checkers // available. In this case, "sci" is the first one in the available spell // checkers. - setCurrentSpellCheckerLocked(sci); + setCurrentSpellCheckerLocked(sci.getId()); } } } @@ -95,12 +95,14 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (sci == null) return; final String packageName = sci.getPackageName(); final int change = isPackageDisappearing(packageName); - if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) { - // Package disappearing - setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName)); - } else if (isPackageModified(packageName)) { - // Package modified - setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName)); + if (// Package disappearing + change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE + // Package modified + || isPackageModified(packageName)) { + sci = findAvailSpellCheckerLocked(null, packageName); + if (sci != null) { + setCurrentSpellCheckerLocked(sci.getId()); + } } } } @@ -177,20 +179,20 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } @Override - public void getSpellCheckerService(SpellCheckerInfo info, String locale, + public void getSpellCheckerService(String sciId, String locale, ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) { if (!mSystemReady) { return; } - if (info == null || tsListener == null || scListener == null) { + if (TextUtils.isEmpty(sciId) || tsListener == null || scListener == null) { Slog.e(TAG, "getSpellCheckerService: Invalid input."); return; } - final String sciId = info.getId(); synchronized(mSpellCheckerMap) { if (!mSpellCheckerMap.containsKey(sciId)) { return; } + final SpellCheckerInfo sci = mSpellCheckerMap.get(sciId); final int uid = Binder.getCallingUid(); if (mSpellCheckerBindGroups.containsKey(sciId)) { final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId); @@ -234,7 +236,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } final long ident = Binder.clearCallingIdentity(); try { - startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener, uid); + startSpellCheckerServiceInnerLocked(sci, locale, tsListener, scListener, uid); } finally { Binder.restoreCallingIdentity(ident); } @@ -290,7 +292,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } @Override - public void setCurrentSpellChecker(SpellCheckerInfo sci) { + public void setCurrentSpellChecker(String sciId) { synchronized(mSpellCheckerMap) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.WRITE_SECURE_SETTINGS) @@ -299,19 +301,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { "Requires permission " + android.Manifest.permission.WRITE_SECURE_SETTINGS); } - setCurrentSpellCheckerLocked(sci); + setCurrentSpellCheckerLocked(sciId); } } - private void setCurrentSpellCheckerLocked(SpellCheckerInfo sci) { + private void setCurrentSpellCheckerLocked(String sciId) { if (DBG) { - Slog.w(TAG, "setCurrentSpellChecker: " + sci.getId()); + Slog.w(TAG, "setCurrentSpellChecker: " + sciId); } - if (sci == null || !mSpellCheckerMap.containsKey(sci.getId())) return; + if (TextUtils.isEmpty(sciId) || !mSpellCheckerMap.containsKey(sciId)) return; final long ident = Binder.clearCallingIdentity(); try { Settings.Secure.putString(mContext.getContentResolver(), - Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId()); + Settings.Secure.SPELL_CHECKER_SERVICE, sciId); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index c129b97..2460fd6 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -68,7 +68,6 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import com.android.internal.content.PackageMonitor; -import com.android.internal.service.wallpaper.ImageWallpaper; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.JournaledFile; @@ -150,8 +149,8 @@ class WallpaperManagerService extends IWallpaperManager.Stub { * Name of the component used to display bitmap wallpapers from either the gallery or * built-in wallpapers. */ - ComponentName mImageWallpaperComponent = new ComponentName("android", - ImageWallpaper.class.getName()); + ComponentName mImageWallpaperComponent = new ComponentName("com.android.systemui", + "com.android.systemui.ImageWallpaper"); WallpaperConnection mWallpaperConnection; long mLastDiedTime; diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 6cc01f4..24188ca 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -17,6 +17,8 @@ package com.android.server.net; import static android.Manifest.permission.CONNECTIVITY_INTERNAL; +import static android.Manifest.permission.ACCESS_NETWORK_STATE; +import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING; import static android.Manifest.permission.DUMP; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.content.Intent.ACTION_SHUTDOWN; @@ -56,6 +58,7 @@ import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; +import android.os.Binder; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; @@ -65,6 +68,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; import android.telephony.TelephonyManager; +import android.util.Log; import android.util.LongSparseArray; import android.util.NtpTrustedTime; import android.util.Slog; @@ -150,9 +154,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Set of currently active ifaces. */ private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap(); - /** Set of historical stats for known networks. */ + /** Set of historical network layer stats for known networks. */ private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap(); - /** Set of historical stats for known UIDs. */ + /** Set of historical network layer stats for known UIDs. */ private HashMap<NetworkIdentitySet, LongSparseArray<NetworkStatsHistory>> mUidStats = Maps.newHashMap(); @@ -164,6 +168,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStats mLastUidSnapshot; + /** Data layer operation counters for splicing into other structures. */ + private NetworkStats mOperations = new NetworkStats(0L, 10); + private NetworkStats mLastOperationsSnapshot; + private final HandlerThread mHandlerThread; private final Handler mHandler; @@ -381,9 +389,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { entry.uid = uid; entry.tag = tag; entry.rxBytes = historyEntry.rxBytes; + entry.rxPackets = historyEntry.rxPackets; entry.txBytes = historyEntry.txBytes; + entry.txPackets = historyEntry.txPackets; + entry.operations = historyEntry.operations; - if (entry.rxBytes > 0 || entry.txBytes > 0) { + if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0 + || entry.txPackets > 0 || entry.operations > 0) { stats.combineValues(entry); } } @@ -396,6 +408,41 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override + public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException { + if (Binder.getCallingUid() != uid) { + mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); + } + + // TODO: switch to data layer stats once kernel exports + // for now, read network layer stats and flatten across all ifaces + final NetworkStats networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid); + final NetworkStats dataLayer = new NetworkStats( + networkLayer.getElapsedRealtime(), networkLayer.size()); + + NetworkStats.Entry entry = null; + for (int i = 0; i < networkLayer.size(); i++) { + entry = networkLayer.getValues(i, entry); + entry.iface = IFACE_ALL; + dataLayer.combineValues(entry); + } + + // splice in operation counts + dataLayer.spliceOperationsFrom(mOperations); + return dataLayer; + } + + @Override + public void incrementOperationCount(int uid, int tag, int operationCount) { + if (Binder.getCallingUid() != uid) { + mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + } + + synchronized (mStatsLock) { + mOperations.combineValues(IFACE_ALL, uid, tag, 0L, 0L, 0L, 0L, operationCount); + } + } + + @Override public void forceUpdate() { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); @@ -533,7 +580,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats uidSnapshot; try { networkSnapshot = mNetworkManager.getNetworkStatsSummary(); - uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null; + uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsUidDetail(UID_ALL) : null; } catch (IllegalStateException e) { Slog.w(TAG, "problem reading network stats: " + e); return; @@ -592,7 +639,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident); - history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes); + history.recordData(timeStart, currentTime, entry); } // trim any history beyond max @@ -615,9 +662,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { ensureUidStatsLoadedLocked(); final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot); + final NetworkStats operationsDelta = computeStatsDelta( + mLastOperationsSnapshot, mOperations); final long timeStart = currentTime - delta.getElapsedRealtime(); NetworkStats.Entry entry = null; + NetworkStats.Entry operationsEntry = null; for (int i = 0; i < delta.size(); i++) { entry = delta.getValues(i, entry); final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface); @@ -625,9 +675,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { continue; } + // splice in operation counts since last poll + final int j = operationsDelta.findIndex(IFACE_ALL, entry.uid, entry.tag); + if (j != -1) { + operationsEntry = operationsDelta.getValues(j, operationsEntry); + entry.operations = operationsEntry.operations; + } + final NetworkStatsHistory history = findOrCreateUidStatsLocked( ident, entry.uid, entry.tag); - history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes); + history.recordData(timeStart, currentTime, entry); } // trim any history beyond max @@ -648,6 +705,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } mLastUidSnapshot = uidSnapshot; + mLastOperationsSnapshot = mOperations; + mOperations = new NetworkStats(0L, 10); } /** @@ -980,7 +1039,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int tag = unpackTag(packed); final NetworkStatsHistory history = uidStats.valueAt(i); pw.print(" UID="); pw.print(uid); - pw.print(" tag="); pw.println(tag); + pw.print(" tag=0x"); pw.println(Integer.toHexString(tag)); history.dump(" ", pw, fullHistory); } } @@ -1028,7 +1087,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (before != null) { return current.subtractClamped(before); } else { - return current; + // this is first snapshot; to prevent from double-counting we only + // observe traffic occuring between known snapshots. + return new NetworkStats(0L, 10); } } @@ -1114,5 +1175,4 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return DAY_IN_MILLIS; } } - } diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index f67c82e..b178e49 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -22,7 +22,7 @@ ifeq ($(TARGET_BOARD_PLATFORM), omap3) LOCAL_CFLAGS += -DNO_RGBX_8888 endif ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) - LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY + LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE endif diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 63062cc..886bb2a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -105,6 +105,7 @@ void Layer::onFrameQueued() { // in the purgatory list void Layer::onRemoved() { + mSurfaceTexture->abandon(); } sp<ISurface> Layer::createSurface() diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp index 91e010f..5973e76 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.cpp +++ b/services/surfaceflinger/SurfaceTextureLayer.cpp @@ -86,6 +86,32 @@ status_t SurfaceTextureLayer::dequeueBuffer(int *buf, return res; } +status_t SurfaceTextureLayer::connect(int api) { + status_t err = SurfaceTexture::connect(api); + if (err == NO_ERROR) { + switch(api) { + case NATIVE_WINDOW_API_MEDIA: + case NATIVE_WINDOW_API_CAMERA: + // Camera preview and videos are rate-limited on the producer + // side. If enabled for this build, we use async mode to always + // show the most recent frame at the cost of requiring an + // additional buffer. +#ifndef NEVER_DEFAULT_TO_ASYNC_MODE + err = setSynchronousMode(false); + break; +#endif + // fall through to set synchronous mode when not defaulting to + // async mode. + deafult: + err = setSynchronousMode(true); + break; + } + if (err != NO_ERROR) { + disconnect(api); + } + } + return err; +} // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h index 29a9cbe..5d328b7 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.h +++ b/services/surfaceflinger/SurfaceTextureLayer.h @@ -50,6 +50,8 @@ protected: virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage); + + virtual status_t connect(int api); }; // --------------------------------------------------------------------------- diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 1620405..60be35a 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -26,10 +26,12 @@ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" /> <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" /> + <uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" /> <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> - <uses-permission android:name="android.permission.WAKE_LOCK" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java index 56ef995..f628977 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java @@ -50,10 +50,9 @@ public class NetworkManagementServiceTest extends AndroidTestCase { public void setUp() throws Exception { super.setUp(); - final File canonicalFilesDir = getContext().getFilesDir().getCanonicalFile(); - mTestProc = new File(canonicalFilesDir, "proc"); + mTestProc = new File(getContext().getFilesDir(), "proc"); if (mTestProc.exists()) { - Files.deleteRecursively(mTestProc); + IoUtils.deleteContents(mTestProc); } mService = NetworkManagementService.createForTest(mContext, mTestProc, true); @@ -64,7 +63,7 @@ public class NetworkManagementServiceTest extends AndroidTestCase { mService = null; if (mTestProc.exists()) { - Files.deleteRecursively(mTestProc); + IoUtils.deleteContents(mTestProc); } super.tearDown(); diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java index aab09ca..91fef22 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -197,9 +197,6 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce(); expectTime(System.currentTimeMillis()); - // default behavior is background data enabled - expect(mConnManager.getBackgroundDataSetting()).andReturn(true); - replay(); mService.systemReady(); verifyAndReset(); @@ -471,7 +468,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { // pretend that 512 bytes total have happened stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L, 11); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10)) .andReturn(stats).atLeastOnce(); @@ -547,7 +544,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0); state = new NetworkState[] { buildWifi() }; { @@ -574,7 +571,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L, 11); { expectTime(currentTime); @@ -595,7 +592,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L, 22); { expectTime(currentTime); diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index bd80af9..cf69fd5 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -160,22 +160,25 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 1L, 2048L, 2L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); + assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); verifyAndReset(); // and bump forward again, with counters going higher. this is @@ -185,13 +188,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 4L, 8192L, 8L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4096L, 8192L); + assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); verifyAndReset(); } @@ -211,26 +214,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 8L, 2048L, 16L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 2) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 2) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 128L, 1L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 20); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); - assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L); - assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L); + assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 512L, 4L, 256L, 2L, 20); + assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 10); verifyAndReset(); // graceful shutdown system, which should trigger persist of stats, and @@ -241,7 +250,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // we persisted them to file. expectDefaultSettings(); replay(); - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); assertStatsFilesExist(true); @@ -254,9 +263,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mService.systemReady(); // after systemReady(), we should have historical stats loaded again - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); - assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L); - assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L); + assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 512L, 4L, 256L, 2L, 20); + assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 10); verifyAndReset(); } @@ -278,20 +287,23 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += 2 * HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 4L, 512L, 4L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history history = mService.getHistoryForNetwork(sTemplateWifi); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); assertEquals(2, history.size()); verifyAndReset(); @@ -301,14 +313,14 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectTime(TEST_START + elapsedRealtime); expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify identical stats, but spread across 4 buckets now history = mService.getHistoryForNetwork(sTemplateWifi); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); assertEquals(4, history.size()); verifyAndReset(); @@ -328,25 +340,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic on first network elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 16L, 512L, 4L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 3) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 3) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 12L, 512L, 4L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 4L, 0L, 0L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 15); + mService.incrementOperationCount(UID_RED, 0xF00D, 10); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateImsi1, 2048L, 512L); - assertNetworkTotal(sTemplateWifi, 0L, 0L); - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L); - assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L); + assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 15); + assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 5); verifyAndReset(); // now switch networks; this also tests that we're okay with interfaces @@ -356,7 +375,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkState(buildMobile3gState(IMSI_2)); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); @@ -369,22 +388,24 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1L, 1024L, 8L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 1024L, 8L)); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify original history still intact - assertNetworkTotal(sTemplateImsi1, 2048L, 512L); - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L); - assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L); + assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 15); + assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 5); // and verify new history also recorded under different template, which // verifies that we didn't cross the streams. - assertNetworkTotal(sTemplateImsi2, 128L, 1024L); - assertNetworkTotal(sTemplateWifi, 0L, 0L); - assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1024L); + assertNetworkTotal(sTemplateImsi2, 128L, 1L, 1024L, 8L, 0); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1L, 1024L, 8L, 10); verifyAndReset(); } @@ -402,25 +423,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 258L, 544L, 34L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 16L, 1L, 16L, 1L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 258L, 512L, 32L) .addValues(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 1L, 16L, 1L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 10); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 15); + mService.incrementOperationCount(UID_GREEN, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4128L, 544L); - assertUidTotal(sTemplateWifi, UID_RED, 16L, 16L); - assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 512L); - assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L); + assertNetworkTotal(sTemplateWifi, 4128L, 258L, 544L, 34L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 16L, 1L, 16L, 1L, 10); + assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 15); + assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 5); verifyAndReset(); // now pretend two UIDs are uninstalled, which should migrate stats to @@ -435,11 +463,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // existing uid and total should remain unchanged; but removed UID // should be gone completely. - assertNetworkTotal(sTemplateWifi, 4128L, 544L); - assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L); - assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L); - assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L); - assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 528L); + assertNetworkTotal(sTemplateWifi, 4128L, 258L, 544L, 34L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 5); + assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 259L, 528L, 33L, 25); verifyAndReset(); } @@ -457,20 +485,26 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 8L, 1024L, 8L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 10); + mService.incrementOperationCount(UID_RED, 0xF00D, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 1024L); + assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 10); verifyAndReset(); // now switch over to 4g network @@ -479,7 +513,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkState(buildMobile4gState()); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); @@ -491,14 +525,16 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify that ALL_MOBILE template combines both - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 1280L); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 15); verifyAndReset(); @@ -537,32 +573,41 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic for two apps elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 10L, 1L, 10L, 1L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 5); + mService.incrementOperationCount(UID_RED, 0xF00D, 1); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertUidTotal(sTemplateWifi, UID_RED, 50L, 50L); - assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 512L); + assertUidTotal(sTemplateWifi, UID_RED, 50L, 5L, 50L, 5L, 5); + assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 8L, 512L, 4L, 10); verifyAndReset(); - + // now create more traffic in next hour, but only for one app elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L)); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 15); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); @@ -570,28 +615,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { NetworkStats stats = mService.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(3, stats.size()); - assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L); - assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L); - assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L); + assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L, 5); + assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L, 1); + assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L, 15); // now verify that recent history only contains one uid final long currentTime = TEST_START + elapsedRealtime; stats = mService.getSummaryForAllUid( sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true); assertEquals(1, stats.size()); - assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L); + assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L, 5); verifyAndReset(); } - private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long txBytes) { + private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets, + long txBytes, long txPackets, int operations) { final NetworkStatsHistory history = mService.getHistoryForNetwork(template); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, + txPackets, operations); } - private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long txBytes) { + private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets, + long txBytes, long txPackets, int operations) { final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, + txPackets, operations); } private void expectSystemReady() throws Exception { @@ -611,8 +660,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mNetManager.getNetworkStatsSummary()).andReturn(summary).atLeastOnce(); } - private void expectNetworkStatsDetail(NetworkStats detail) throws Exception { - expect(mNetManager.getNetworkStatsDetail()).andReturn(detail).atLeastOnce(); + private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { + expect(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL))).andReturn(detail).atLeastOnce(); } private void expectDefaultSettings() throws Exception { @@ -639,6 +688,17 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes(); } + private void performBootstrapPoll(long testStart, long elapsedRealtime) throws Exception { + expectTime(testStart + elapsedRealtime); + expectDefaultSettings(); + expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); + + replay(); + mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); + verifyAndReset(); + } + private void assertStatsFilesExist(boolean exist) { final File networkFile = new File(mStatsDir, "netstats.bin"); final File uidFile = new File(mStatsDir, "netstats_uid.bin"); @@ -652,23 +712,26 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } private static void assertValues(NetworkStats stats, int i, String iface, int uid, int tag, - long rxBytes, long rxPackets, long txBytes, long txPackets) { + long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) { final NetworkStats.Entry entry = stats.getValues(i, null); - assertEquals(iface, entry.iface); - assertEquals(uid, entry.uid); - assertEquals(tag, entry.tag); - assertEquals(rxBytes, entry.rxBytes); - // TODO: enable testing packet counts once stored in history -// assertEquals(rxPackets, entry.rxPackets); - assertEquals(txBytes, entry.txBytes); -// assertEquals(txPackets, entry.txPackets); + assertEquals("unexpected iface", iface, entry.iface); + assertEquals("unexpected uid", uid, entry.uid); + assertEquals("unexpected tag", tag, entry.tag); + assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); + assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); + assertEquals("unexpected txBytes", txBytes, entry.txBytes); + assertEquals("unexpected txPackets", txPackets, entry.txPackets); + assertEquals("unexpected operations", operations, entry.operations); } - private static void assertValues( - NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) { + private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes, + long rxPackets, long txBytes, long txPackets, int operations) { final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); + assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); assertEquals("unexpected txBytes", txBytes, entry.txBytes); + assertEquals("unexpected txPackets", txPackets, entry.txPackets); + assertEquals("unexpected operations", operations, entry.operations); } private static NetworkState buildWifiState() { diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java index 50c18f0..c0870c7 100644 --- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java @@ -289,7 +289,7 @@ public class ThrottleServiceTest extends AndroidTestCase { public void expectGetInterfaceCounter(long rx, long tx) throws Exception { // TODO: provide elapsedRealtime mock to match TimeAuthority final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); - stats.addValues(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, 0L, tx, 0L); + stats.addValues(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, 0L, tx, 0L, 0); expect(mMockNMService.getNetworkStatsSummary()).andReturn(stats).atLeastOnce(); } |