diff options
author | Jeff Brown <jeffbrown@google.com> | 2010-12-29 13:22:08 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-12-29 13:22:08 -0800 |
commit | 288757f99692de553cda0eb30486767912f07518 (patch) | |
tree | 3c79927171ef7c58e4f933a84d34dc9eb4034808 | |
parent | f95a66052d4491f2469b40d6089ca0a98fb5a88c (diff) | |
parent | 4c501a42173bfc0c7c9ee32312db392c59b67e13 (diff) | |
download | frameworks_native-288757f99692de553cda0eb30486767912f07518.zip frameworks_native-288757f99692de553cda0eb30486767912f07518.tar.gz frameworks_native-288757f99692de553cda0eb30486767912f07518.tar.bz2 |
Merge "Add initial support for cursor-based pointing devices."
-rw-r--r-- | include/ui/EventHub.h | 4 | ||||
-rw-r--r-- | include/ui/InputReader.h | 21 | ||||
-rw-r--r-- | include/ui/PointerController.h | 63 | ||||
-rw-r--r-- | include/utils/PropertyMap.h | 6 | ||||
-rw-r--r-- | libs/ui/EventHub.cpp | 4 | ||||
-rw-r--r-- | libs/ui/InputDispatcher.cpp | 8 | ||||
-rw-r--r-- | libs/ui/InputReader.cpp | 183 | ||||
-rw-r--r-- | libs/ui/tests/InputReader_test.cpp | 228 | ||||
-rw-r--r-- | libs/utils/PropertyMap.cpp | 6 |
9 files changed, 406 insertions, 117 deletions
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h index 6c6c297..8f922a5 100644 --- a/include/ui/EventHub.h +++ b/include/ui/EventHub.h @@ -109,8 +109,8 @@ enum { /* The input device is a touchscreen (either single-touch or multi-touch). */ INPUT_DEVICE_CLASS_TOUCHSCREEN = 0x00000004, - /* The input device is a trackball. */ - INPUT_DEVICE_CLASS_TRACKBALL = 0x00000008, + /* The input device is a cursor device such as a trackball or mouse. */ + INPUT_DEVICE_CLASS_CURSOR = 0x00000008, /* The input device is a multi-touch touchscreen. */ INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010, diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h index b466ff1..00a06be 100644 --- a/include/ui/InputReader.h +++ b/include/ui/InputReader.h @@ -20,6 +20,7 @@ #include <ui/EventHub.h> #include <ui/Input.h> #include <ui/InputDispatcher.h> +#include <ui/PointerController.h> #include <utils/KeyedVector.h> #include <utils/threads.h> #include <utils/Timers.h> @@ -77,6 +78,9 @@ public: /* Gets the excluded device names for the platform. */ virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0; + + /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */ + virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0; }; @@ -421,10 +425,10 @@ private: }; -class TrackballInputMapper : public InputMapper { +class CursorInputMapper : public InputMapper { public: - TrackballInputMapper(InputDevice* device); - virtual ~TrackballInputMapper(); + CursorInputMapper(InputDevice* device); + virtual ~CursorInputMapper(); virtual uint32_t getSources(); virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); @@ -443,6 +447,12 @@ private: // Immutable configuration parameters. struct Parameters { + enum Mode { + MODE_POINTER, + MODE_NAVIGATION, + }; + + Mode mode; int32_t associatedDisplayId; bool orientationAware; } mParameters; @@ -465,10 +475,12 @@ private: } } mAccumulator; + int32_t mSources; float mXScale; float mYScale; float mXPrecision; float mYPrecision; + sp<PointerControllerInterface> mPointerController; struct LockedState { bool down; @@ -572,6 +584,9 @@ protected: } }; + // Input sources supported by the device. + int32_t mSources; + // Immutable configuration parameters. struct Parameters { enum DeviceType { diff --git a/include/ui/PointerController.h b/include/ui/PointerController.h new file mode 100644 index 0000000..4db24e5 --- /dev/null +++ b/include/ui/PointerController.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _UI_POINTER_CONTROLLER_H +#define _UI_POINTER_CONTROLLER_H + +#include <utils/RefBase.h> + +namespace android { + +enum { + POINTER_BUTTON_1 = 1 << 0, +}; + +/** + * Interface for tracking a single (mouse) pointer. + * + * The pointer controller is responsible for providing synchronization and for tracking + * display orientation changes if needed. + */ +class PointerControllerInterface : public virtual RefBase { +protected: + PointerControllerInterface() { } + virtual ~PointerControllerInterface() { } + +public: + /* Gets the bounds of the region that the pointer can traverse. + * Returns true if the bounds are available. */ + virtual bool getBounds(float* outMinX, float* outMinY, + float* outMaxX, float* outMaxY) const = 0; + + /* Move the pointer. */ + virtual void move(float deltaX, float deltaY) = 0; + + /* Sets a mask that indicates which buttons are pressed. */ + virtual void setButtonState(uint32_t buttonState) = 0; + + /* Gets a mask that indicates which buttons are pressed. */ + virtual uint32_t getButtonState() const = 0; + + /* Sets the absolute location of the pointer. */ + virtual void setPosition(float x, float y) = 0; + + /* Gets the absolute location of the pointer. */ + virtual void getPosition(float* outX, float* outY) const = 0; +}; + +} // namespace android + +#endif // _UI_POINTER_CONTROLLER_H diff --git a/include/utils/PropertyMap.h b/include/utils/PropertyMap.h index a54f819..a9e674f 100644 --- a/include/utils/PropertyMap.h +++ b/include/utils/PropertyMap.h @@ -71,6 +71,12 @@ public: bool tryGetProperty(const String8& key, int32_t& outValue) const; bool tryGetProperty(const String8& key, float& outValue) const; + /* Adds all values from the specified property map. */ + void addAll(const PropertyMap* map); + + /* Gets the underlying property map. */ + inline const KeyedVector<String8, String8>& getProperties() const { return mProperties; } + /* Loads a property map from a file. */ static status_t load(const String8& filename, PropertyMap** outMap); diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp index 8f4bac6..4e9fad0 100644 --- a/libs/ui/EventHub.cpp +++ b/libs/ui/EventHub.cpp @@ -755,14 +755,14 @@ int EventHub::openDevice(const char *devicePath) { } } - // See if this is a trackball (or mouse). + // See if this is a cursor device such as a trackball or mouse. if (test_bit(BTN_MOUSE, key_bitmask)) { uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)]; memset(rel_bitmask, 0, sizeof(rel_bitmask)); LOGV("Getting relative controllers..."); if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) { if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) { - device->classes |= INPUT_DEVICE_CLASS_TRACKBALL; + device->classes |= INPUT_DEVICE_CLASS_CURSOR; } } } diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index ed0cb8e..0548e61 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -1443,11 +1443,11 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, #if DEBUG_DISPATCH_CYCLE LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, " "xOffset=%f, yOffset=%f, " - "windowType=%d, pointerIds=0x%x, " + "pointerIds=0x%x, " "resumeWithAppendedMotionSample=%s", connection->getInputChannelName(), inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset, - inputTarget->windowType, inputTarget->pointerIds.value, + inputTarget->pointerIds.value, toString(resumeWithAppendedMotionSample)); #endif @@ -1826,8 +1826,8 @@ void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime, void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection) { #if DEBUG_DISPATCH_CYCLE - LOGD("channel '%s' ~ abortBrokenDispatchCycle - broken=%s", - connection->getInputChannelName(), toString(broken)); + LOGD("channel '%s' ~ abortBrokenDispatchCycle", + connection->getInputChannelName()); #endif // Clear the outbound queue. diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp index 51ed09f..a11a010 100644 --- a/libs/ui/InputReader.cpp +++ b/libs/ui/InputReader.cpp @@ -239,9 +239,9 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType)); } - // Trackball-like devices. - if (classes & INPUT_DEVICE_CLASS_TRACKBALL) { - device->addMapper(new TrackballInputMapper(device)); + // Cursor-like devices. + if (classes & INPUT_DEVICE_CLASS_CURSOR) { + device->addMapper(new CursorInputMapper(device)); } // Touchscreen-like devices. @@ -914,7 +914,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, if (policyFlags & POLICY_FLAG_FUNCTION) { newMetaState |= AMETA_FUNCTION_ON; } - getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags, + getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime); } @@ -983,36 +983,40 @@ void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& } -// --- TrackballInputMapper --- +// --- CursorInputMapper --- -TrackballInputMapper::TrackballInputMapper(InputDevice* device) : +CursorInputMapper::CursorInputMapper(InputDevice* device) : InputMapper(device) { - mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; - mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; - mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; - mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; - initializeLocked(); } -TrackballInputMapper::~TrackballInputMapper() { +CursorInputMapper::~CursorInputMapper() { } -uint32_t TrackballInputMapper::getSources() { - return AINPUT_SOURCE_TRACKBALL; +uint32_t CursorInputMapper::getSources() { + return mSources; } -void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) { +void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { InputMapper::populateDeviceInfo(info); - info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale); - info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale); + if (mParameters.mode == Parameters::MODE_POINTER) { + float minX, minY, maxX, maxY; + if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) { + info->addMotionRange(AINPUT_MOTION_RANGE_X, minX, maxX, 0.0f, 0.0f); + info->addMotionRange(AINPUT_MOTION_RANGE_Y, minY, maxY, 0.0f, 0.0f); + } + } else { + info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale); + info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale); + } + info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f); } -void TrackballInputMapper::dump(String8& dump) { +void CursorInputMapper::dump(String8& dump) { { // acquire lock AutoMutex _l(mLock); - dump.append(INDENT2 "Trackball Input Mapper:\n"); + dump.append(INDENT2 "Cursor Input Mapper:\n"); dumpParameters(dump); dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision); dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision); @@ -1021,37 +1025,79 @@ void TrackballInputMapper::dump(String8& dump) { } // release lock } -void TrackballInputMapper::configure() { +void CursorInputMapper::configure() { InputMapper::configure(); // Configure basic parameters. configureParameters(); + + // Configure device mode. + switch (mParameters.mode) { + case Parameters::MODE_POINTER: + mSources = AINPUT_SOURCE_MOUSE; + mXPrecision = 1.0f; + mYPrecision = 1.0f; + mXScale = 1.0f; + mYScale = 1.0f; + mPointerController = getPolicy()->obtainPointerController(getDeviceId()); + break; + case Parameters::MODE_NAVIGATION: + mSources = AINPUT_SOURCE_TRACKBALL; + mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; + mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; + mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; + mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; + break; + } } -void TrackballInputMapper::configureParameters() { +void CursorInputMapper::configureParameters() { + mParameters.mode = Parameters::MODE_POINTER; + String8 cursorModeString; + if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) { + if (cursorModeString == "navigation") { + mParameters.mode = Parameters::MODE_NAVIGATION; + } else if (cursorModeString != "pointer" && cursorModeString != "default") { + LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string()); + } + } + mParameters.orientationAware = false; - getDevice()->getConfiguration().tryGetProperty(String8("trackball.orientationAware"), + getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"), mParameters.orientationAware); - mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1; + mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER + || mParameters.orientationAware ? 0 : -1; } -void TrackballInputMapper::dumpParameters(String8& dump) { +void CursorInputMapper::dumpParameters(String8& dump) { dump.append(INDENT3 "Parameters:\n"); dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n", mParameters.associatedDisplayId); + + switch (mParameters.mode) { + case Parameters::MODE_POINTER: + dump.append(INDENT4 "Mode: pointer\n"); + break; + case Parameters::MODE_NAVIGATION: + dump.append(INDENT4 "Mode: navigation\n"); + break; + default: + assert(false); + } + dump.appendFormat(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware)); } -void TrackballInputMapper::initializeLocked() { +void CursorInputMapper::initializeLocked() { mAccumulator.clear(); mLocked.down = false; mLocked.downTime = 0; } -void TrackballInputMapper::reset() { +void CursorInputMapper::reset() { for (;;) { { // acquire lock AutoMutex _l(mLock); @@ -1062,7 +1108,7 @@ void TrackballInputMapper::reset() { } } // release lock - // Synthesize trackball button up event on reset. + // Synthesize button up event on reset. nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE; mAccumulator.btnMouse = false; @@ -1072,7 +1118,7 @@ void TrackballInputMapper::reset() { InputMapper::reset(); } -void TrackballInputMapper::process(const RawEvent* rawEvent) { +void CursorInputMapper::process(const RawEvent* rawEvent) { switch (rawEvent->type) { case EV_KEY: switch (rawEvent->scanCode) { @@ -1109,7 +1155,7 @@ void TrackballInputMapper::process(const RawEvent* rawEvent) { } } -void TrackballInputMapper::sync(nsecs_t when) { +void CursorInputMapper::sync(nsecs_t when) { uint32_t fields = mAccumulator.fields; if (fields == 0) { return; // no new state changes, so nothing to do @@ -1133,8 +1179,8 @@ void TrackballInputMapper::sync(nsecs_t when) { } downTime = mLocked.downTime; - float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f; - float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f; + float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f; + float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f; if (downChanged) { motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; @@ -1142,18 +1188,8 @@ void TrackballInputMapper::sync(nsecs_t when) { motionEventAction = AMOTION_EVENT_ACTION_MOVE; } - pointerCoords.x = x; - pointerCoords.y = y; - pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f; - pointerCoords.size = 0; - pointerCoords.touchMajor = 0; - pointerCoords.touchMinor = 0; - pointerCoords.toolMajor = 0; - pointerCoords.toolMinor = 0; - pointerCoords.orientation = 0; - if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0 - && (x != 0.0f || y != 0.0f)) { + && (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; @@ -1165,35 +1201,54 @@ void TrackballInputMapper::sync(nsecs_t when) { float temp; switch (orientation) { case InputReaderPolicyInterface::ROTATION_90: - temp = pointerCoords.x; - pointerCoords.x = pointerCoords.y; - pointerCoords.y = - temp; + temp = deltaX; + deltaX = deltaY; + deltaY = -temp; break; case InputReaderPolicyInterface::ROTATION_180: - pointerCoords.x = - pointerCoords.x; - pointerCoords.y = - pointerCoords.y; + deltaX = -deltaX; + deltaY = -deltaY; break; case InputReaderPolicyInterface::ROTATION_270: - temp = pointerCoords.x; - pointerCoords.x = - pointerCoords.y; - pointerCoords.y = temp; + temp = deltaX; + deltaX = -deltaY; + deltaY = temp; break; } } + + if (mPointerController != NULL) { + mPointerController->move(deltaX, deltaY); + if (downChanged) { + mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0); + } + mPointerController->getPosition(&pointerCoords.x, &pointerCoords.y); + } else { + pointerCoords.x = deltaX; + pointerCoords.y = deltaY; + } + + pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f; + pointerCoords.size = 0; + pointerCoords.touchMajor = 0; + pointerCoords.touchMinor = 0; + pointerCoords.toolMajor = 0; + pointerCoords.toolMinor = 0; + pointerCoords.orientation = 0; } // release lock int32_t metaState = mContext->getGlobalMetaState(); int32_t pointerId = 0; - getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, 0, + getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0, motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime); mAccumulator.clear(); } -int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { +int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) { return getEventHub()->getScanCodeState(getDeviceId(), scanCode); } else { @@ -1217,15 +1272,7 @@ TouchInputMapper::~TouchInputMapper() { } uint32_t TouchInputMapper::getSources() { - switch (mParameters.deviceType) { - case Parameters::DEVICE_TYPE_TOUCH_SCREEN: - return AINPUT_SOURCE_TOUCHSCREEN; - case Parameters::DEVICE_TYPE_TOUCH_PAD: - return AINPUT_SOURCE_TOUCHPAD; - default: - assert(false); - return AINPUT_SOURCE_UNKNOWN; - } + return mSources; } void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { @@ -1326,6 +1373,18 @@ void TouchInputMapper::configure() { // Configure basic parameters. configureParameters(); + // Configure sources. + switch (mParameters.deviceType) { + case Parameters::DEVICE_TYPE_TOUCH_SCREEN: + mSources = AINPUT_SOURCE_TOUCHSCREEN; + break; + case Parameters::DEVICE_TYPE_TOUCH_PAD: + mSources = AINPUT_SOURCE_TOUCHPAD; + break; + default: + assert(false); + } + // Configure absolute axis information. configureRawAxes(); @@ -2560,7 +2619,7 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, yPrecision = mLocked.orientedYPrecision; } // release lock - getDispatcher()->notifyMotion(when, getDeviceId(), getSources(), policyFlags, + getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags, motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags, pointerCount, pointerIds, pointerCoords, xPrecision, yPrecision, mDownTime); diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp index 97cbc25..50d3383 100644 --- a/libs/ui/tests/InputReader_test.cpp +++ b/libs/ui/tests/InputReader_test.cpp @@ -30,6 +30,56 @@ static inline float avg(float x, float y) { } +// --- FakePointerController --- + +class FakePointerController : public PointerControllerInterface { + bool mHaveBounds; + float mMinX, mMinY, mMaxX, mMaxY; + +protected: + virtual ~FakePointerController() { } + +public: + FakePointerController() { + } + + void setBounds(float minX, float minY, float maxX, float maxY) { + mHaveBounds = true; + mMinX = minX; + mMinY = minY; + mMaxX = maxX; + mMaxY = maxY; + } + +private: + virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const { + *outMinX = mMinX; + *outMaxX = mMinX; + *outMinY = mMinY; + *outMaxY = mMaxY; + return mHaveBounds; + } + + virtual void move(float deltaX, float deltaY) { + } + + virtual void setButtonState(uint32_t buttonState) { + } + + virtual uint32_t getButtonState() const { + return 0; + } + + virtual void setPosition(float x, float y) { + } + + virtual void getPosition(float* outX, float* outY) const { + *outX = 0; + *outY = 0; + } +}; + + // --- FakeInputReaderPolicy --- class FakeInputReaderPolicy : public InputReaderPolicyInterface { @@ -43,6 +93,7 @@ class FakeInputReaderPolicy : public InputReaderPolicyInterface { bool mFilterTouchEvents; bool mFilterJumpyTouchEvents; Vector<String8> mExcludedDeviceNames; + KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers; protected: virtual ~FakeInputReaderPolicy() { } @@ -78,6 +129,10 @@ public: mExcludedDeviceNames.push(deviceName); } + void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) { + mPointerControllers.add(deviceId, controller); + } + private: virtual bool getDisplayInfo(int32_t displayId, int32_t* width, int32_t* height, int32_t* orientation) { @@ -109,6 +164,10 @@ private: virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) { outExcludedDeviceNames.appendVector(mExcludedDeviceNames); } + + virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) { + return mPointerControllers.valueFor(deviceId); + } }; @@ -381,6 +440,11 @@ public: device->configuration.addProperty(key, value); } + void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration) { + Device* device = getDevice(deviceId); + device->configuration.addAll(configuration); + } + void addAxis(int32_t deviceId, int axis, int32_t minValue, int32_t maxValue, int flat, int fuzz) { Device* device = getDevice(deviceId); @@ -851,8 +915,12 @@ protected: mFakeEventHub.clear(); } - void addDevice(int32_t deviceId, const String8& name, uint32_t classes) { + void addDevice(int32_t deviceId, const String8& name, uint32_t classes, + const PropertyMap* configuration) { mFakeEventHub->addDevice(deviceId, name, classes); + if (configuration) { + mFakeEventHub->addConfigurationMap(deviceId, configuration); + } mFakeEventHub->finishDeviceScan(); mReader->loopOnce(); mReader->loopOnce(); @@ -860,12 +928,13 @@ protected: } FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId, - const String8& name, uint32_t classes, uint32_t sources) { + const String8& name, uint32_t classes, uint32_t sources, + const PropertyMap* configuration) { InputDevice* device = new InputDevice(mReader.get(), deviceId, name); FakeInputMapper* mapper = new FakeInputMapper(device, sources); device->addMapper(mapper); mReader->setNextDevice(device); - addDevice(deviceId, name, classes); + addDevice(deviceId, name, classes, configuration); return mapper; } }; @@ -881,7 +950,7 @@ TEST_F(InputReaderTest, GetInputConfiguration_WhenNoDevices_ReturnsDefaults) { TEST_F(InputReaderTest, GetInputConfiguration_WhenAlphabeticKeyboardPresent_ReturnsQwertyKeyboard) { ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("keyboard"), - INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY)); + INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY, NULL)); InputConfiguration config; mReader->getInputConfiguration(&config); @@ -893,7 +962,7 @@ TEST_F(InputReaderTest, GetInputConfiguration_WhenAlphabeticKeyboardPresent_Retu TEST_F(InputReaderTest, GetInputConfiguration_WhenTouchScreenPresent_ReturnsFingerTouchScreen) { ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("touchscreen"), - INPUT_DEVICE_CLASS_TOUCHSCREEN)); + INPUT_DEVICE_CLASS_TOUCHSCREEN, NULL)); InputConfiguration config; mReader->getInputConfiguration(&config); @@ -903,9 +972,25 @@ TEST_F(InputReaderTest, GetInputConfiguration_WhenTouchScreenPresent_ReturnsFing ASSERT_EQ(InputConfiguration::TOUCHSCREEN_FINGER, config.touchScreen); } +TEST_F(InputReaderTest, GetInputConfiguration_WhenMousePresent_ReturnsNoNavigation) { + PropertyMap configuration; + configuration.addProperty(String8("cursor.mode"), String8("pointer")); + ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("mouse"), + INPUT_DEVICE_CLASS_CURSOR, &configuration)); + + InputConfiguration config; + mReader->getInputConfiguration(&config); + + ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard); + ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation); + ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen); +} + TEST_F(InputReaderTest, GetInputConfiguration_WhenTrackballPresent_ReturnsTrackballNavigation) { + PropertyMap configuration; + configuration.addProperty(String8("cursor.mode"), String8("navigation")); ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("trackball"), - INPUT_DEVICE_CLASS_TRACKBALL)); + INPUT_DEVICE_CLASS_CURSOR, &configuration)); InputConfiguration config; mReader->getInputConfiguration(&config); @@ -917,7 +1002,7 @@ TEST_F(InputReaderTest, GetInputConfiguration_WhenTrackballPresent_ReturnsTrackb TEST_F(InputReaderTest, GetInputConfiguration_WhenDPadPresent_ReturnsDPadNavigation) { ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("dpad"), - INPUT_DEVICE_CLASS_DPAD)); + INPUT_DEVICE_CLASS_DPAD, NULL)); InputConfiguration config; mReader->getInputConfiguration(&config); @@ -929,7 +1014,7 @@ TEST_F(InputReaderTest, GetInputConfiguration_WhenDPadPresent_ReturnsDPadNavigat TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsValid) { ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"), - INPUT_DEVICE_CLASS_KEYBOARD)); + INPUT_DEVICE_CLASS_KEYBOARD, NULL)); InputDeviceInfo info; status_t result = mReader->getInputDeviceInfo(1, &info); @@ -950,7 +1035,7 @@ TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsInvalid) { } TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsIgnored) { - addDevice(1, String8("ignored"), 0); // no classes so device will be ignored + addDevice(1, String8("ignored"), 0, NULL); // no classes so device will be ignored InputDeviceInfo info; status_t result = mReader->getInputDeviceInfo(1, &info); @@ -960,9 +1045,9 @@ TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsIgnored) { TEST_F(InputReaderTest, GetInputDeviceIds) { ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"), - INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY)); - ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("trackball"), - INPUT_DEVICE_CLASS_TRACKBALL)); + INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY, NULL)); + ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("mouse"), + INPUT_DEVICE_CLASS_CURSOR, NULL)); Vector<int32_t> ids; mReader->getInputDeviceIds(ids); @@ -975,7 +1060,7 @@ TEST_F(InputReaderTest, GetInputDeviceIds) { TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) { FakeInputMapper* mapper = NULL; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN); ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0, @@ -1002,7 +1087,7 @@ TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) { TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) { FakeInputMapper* mapper = NULL; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN); ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0, @@ -1029,7 +1114,7 @@ TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) { TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) { FakeInputMapper* mapper = NULL; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN); ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0, @@ -1056,7 +1141,7 @@ TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) { TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) { FakeInputMapper* mapper = NULL; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); mapper->addSupportedKeyCode(AKEYCODE_A); mapper->addSupportedKeyCode(AKEYCODE_B); @@ -1089,7 +1174,7 @@ TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) { } TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) { - addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD); + addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, NULL); FakeInputDispatcher::NotifyConfigurationChangedArgs args; ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyConfigurationChangedWasCalled(&args)); @@ -1099,7 +1184,7 @@ TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChange TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { FakeInputMapper* mapper = NULL; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, AKEYCODE_A, 1, POLICY_FLAG_WAKE); mReader->loopOnce(); @@ -1792,19 +1877,28 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) } -// --- TrackballInputMapperTest --- +// --- CursorInputMapperTest --- -class TrackballInputMapperTest : public InputMapperTest { +class CursorInputMapperTest : public InputMapperTest { protected: static const int32_t TRACKBALL_MOVEMENT_THRESHOLD; - void testMotionRotation(TrackballInputMapper* mapper, + sp<FakePointerController> mFakePointerController; + + virtual void SetUp() { + InputMapperTest::SetUp(); + + mFakePointerController = new FakePointerController(); + mFakePolicy->setPointerController(DEVICE_ID, mFakePointerController); + } + + void testMotionRotation(CursorInputMapper* mapper, int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY); }; -const int32_t TrackballInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6; +const int32_t CursorInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6; -void TrackballInputMapperTest::testMotionRotation(TrackballInputMapper* mapper, +void CursorInputMapperTest::testMotionRotation(CursorInputMapper* mapper, int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) { FakeInputDispatcher::NotifyMotionArgs args; @@ -1819,15 +1913,53 @@ void TrackballInputMapperTest::testMotionRotation(TrackballInputMapper* mapper, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } -TEST_F(TrackballInputMapperTest, GetSources) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, WhenModeIsPointer_GetSources_ReturnsMouse) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "pointer"); + addMapperAndConfigure(mapper); + + ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources()); +} + +TEST_F(CursorInputMapperTest, WhenModeIsNavigation_GetSources_ReturnsTrackball) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper->getSources()); } -TEST_F(TrackballInputMapperTest, PopulateDeviceInfo) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeFromPointerController) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "pointer"); + addMapperAndConfigure(mapper); + + InputDeviceInfo info; + mapper->populateDeviceInfo(&info); + + // Initially there may not be a valid motion range. + ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X)); + ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y)); + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE, + 0.0f, 1.0f, 0.0f, 1.0f)); + + // When the bounds are set, then there should be a valid motion range. + mFakePointerController->setBounds(1, 2, 800, 480); + + InputDeviceInfo info2; + mapper->populateDeviceInfo(&info2); + + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_X, + 1, 800, 0.0f, 1.0f)); + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_Y, + 2, 480, 0.0f, 1.0f)); + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_PRESSURE, + 0.0f, 1.0f, 0.0f, 1.0f)); +} + +TEST_F(CursorInputMapperTest, WhenModeIsNavigation_PopulateDeviceInfo_ReturnsScaledRange) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); InputDeviceInfo info; @@ -1839,8 +1971,9 @@ TEST_F(TrackballInputMapperTest, PopulateDeviceInfo) { -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD)); } -TEST_F(TrackballInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON); @@ -1887,8 +2020,9 @@ TEST_F(TrackballInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaS ASSERT_EQ(ARBITRARY_TIME, args.downTime); } -TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentXYUpdates) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); FakeInputDispatcher::NotifyMotionArgs args; @@ -1911,8 +2045,9 @@ TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentXYUpdates) { 0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } -TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); FakeInputDispatcher::NotifyMotionArgs args; @@ -1932,8 +2067,9 @@ TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } -TEST_F(TrackballInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); FakeInputDispatcher::NotifyMotionArgs args; @@ -1967,8 +2103,9 @@ TEST_F(TrackballInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } -TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); FakeInputDispatcher::NotifyMotionArgs args; @@ -1987,8 +2124,9 @@ TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeBu ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled()); } -TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); FakeInputDispatcher::NotifyMotionArgs args; @@ -2006,8 +2144,9 @@ TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } -TEST_F(TrackballInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); +TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); mFakePolicy->setDisplayInfo(DISPLAY_ID, @@ -2023,9 +2162,10 @@ TEST_F(TrackballInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotate ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1)); } -TEST_F(TrackballInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) { - TrackballInputMapper* mapper = new TrackballInputMapper(mDevice); - addConfigurationProperty("trackball.orientationAware", "1"); +TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) { + CursorInputMapper* mapper = new CursorInputMapper(mDevice); + addConfigurationProperty("cursor.mode", "navigation"); + addConfigurationProperty("cursor.orientationAware", "1"); addMapperAndConfigure(mapper); mFakePolicy->setDisplayInfo(DISPLAY_ID, diff --git a/libs/utils/PropertyMap.cpp b/libs/utils/PropertyMap.cpp index fd7edec..d472d45 100644 --- a/libs/utils/PropertyMap.cpp +++ b/libs/utils/PropertyMap.cpp @@ -109,6 +109,12 @@ bool PropertyMap::tryGetProperty(const String8& key, float& outValue) const { return true; } +void PropertyMap::addAll(const PropertyMap* map) { + for (size_t i = 0; i < map->mProperties.size(); i++) { + mProperties.add(map->mProperties.keyAt(i), map->mProperties.valueAt(i)); + } +} + status_t PropertyMap::load(const String8& filename, PropertyMap** outMap) { *outMap = NULL; |