summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/WindowManager.java5
-rw-r--r--include/ui/EventHub.h4
-rw-r--r--include/ui/InputReader.h21
-rw-r--r--include/ui/PointerController.h63
-rw-r--r--include/utils/PropertyMap.h6
-rw-r--r--libs/ui/EventHub.cpp4
-rw-r--r--libs/ui/InputDispatcher.cpp8
-rw-r--r--libs/ui/InputReader.cpp183
-rw-r--r--libs/ui/tests/InputReader_test.cpp228
-rw-r--r--libs/utils/PropertyMap.cpp6
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java5
-rw-r--r--services/java/com/android/server/InputManager.java9
-rw-r--r--services/jni/com_android_server_InputManager.cpp453
13 files changed, 846 insertions, 149 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e8792ff..c435c43 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -381,6 +381,11 @@ public interface WindowManager extends ViewManager {
*/
public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;
+ /**
+ * Window type: (mouse) pointer
+ * @hide
+ */
+ public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18;
/**
* End of types of system windows.
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;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 2e89a21..281ac2e 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -112,6 +112,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.animation.Animation;
@@ -176,6 +177,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// things in here CAN NOT take focus, but are shown on top of everything else.
static final int SYSTEM_OVERLAY_LAYER = 18;
static final int SECURE_SYSTEM_OVERLAY_LAYER = 19;
+ // the (mouse) pointer layer
+ static final int POINTER_LAYER = 20;
static final int APPLICATION_MEDIA_SUBLAYER = -2;
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -950,6 +953,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return WALLPAPER_LAYER;
case TYPE_DRAG:
return DRAG_LAYER;
+ case TYPE_POINTER:
+ return POINTER_LAYER;
}
Log.e(TAG, "Unknown window type: " + type);
return APPLICATION_LAYER;
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 4c499cd..b5becb5 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -32,6 +32,7 @@ import android.view.InputDevice;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.Surface;
+import android.view.WindowManager;
import java.io.BufferedReader;
import java.io.File;
@@ -475,5 +476,13 @@ public class InputManager {
}
return result;
}
+
+ @SuppressWarnings("unused")
+ public int getPointerLayer() {
+ return mWindowManagerService.mPolicy.windowTypeToLayerLw(
+ WindowManager.LayoutParams.TYPE_DRAG)
+ * WindowManagerService.TYPE_LAYER_MULTIPLIER
+ + WindowManagerService.TYPE_LAYER_OFFSET;
+ }
}
}
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 9156249..c757ada 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -24,6 +24,10 @@
// Log debug messages about InputDispatcherPolicy
#define DEBUG_INPUT_DISPATCHER_POLICY 0
+// Log debug messages about PointerController
+#define DEBUG_POINTER_CONTROLLER 1
+
+
#include "JNIHelp.h"
#include "jni.h"
#include <limits.h>
@@ -34,6 +38,10 @@
#include <ui/InputTransport.h>
#include <utils/Log.h>
#include <utils/threads.h>
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+
#include "../../core/jni/android_view_KeyEvent.h"
#include "../../core/jni/android_view_MotionEvent.h"
#include "../../core/jni/android_view_InputChannel.h"
@@ -58,6 +66,7 @@ static struct {
jmethodID filterJumpyTouchEvents;
jmethodID getExcludedDeviceNames;
jmethodID getMaxEventsPerSecond;
+ jmethodID getPointerLayer;
} gCallbacksClassInfo;
static struct {
@@ -135,6 +144,52 @@ static inline nsecs_t now() {
// ----------------------------------------------------------------------------
+class PointerController : public PointerControllerInterface {
+protected:
+ virtual ~PointerController();
+
+public:
+ PointerController(int32_t pointerLayer);
+
+ virtual bool getBounds(float* outMinX, float* outMinY,
+ float* outMaxX, float* outMaxY) const;
+ virtual void move(float deltaX, float deltaY);
+ virtual void setButtonState(uint32_t buttonState);
+ virtual uint32_t getButtonState() const;
+ virtual void setPosition(float x, float y);
+ virtual void getPosition(float* outX, float* outY) const;
+
+ void setDisplaySize(int32_t width, int32_t height);
+ void setDisplayOrientation(int32_t orientation);
+
+private:
+ mutable Mutex mLock;
+
+ int32_t mPointerLayer;
+ sp<SurfaceComposerClient> mSurfaceComposerClient;
+ sp<SurfaceControl> mSurfaceControl;
+
+ struct Locked {
+ int32_t displayWidth;
+ int32_t displayHeight;
+ int32_t displayOrientation;
+
+ float pointerX;
+ float pointerY;
+ uint32_t buttonState;
+
+ bool wantVisible;
+ bool visible;
+ bool drawn;
+ } mLocked;
+
+ bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
+ void setPositionLocked(float x, float y);
+ void updateLocked();
+};
+
+// ----------------------------------------------------------------------------
+
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface {
@@ -166,6 +221,7 @@ public:
virtual bool filterTouchEvents();
virtual bool filterJumpyTouchEvents();
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
+ virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
/* --- InputDispatcherPolicyInterface implementation --- */
@@ -215,19 +271,23 @@ private:
// Cached throttling policy.
int32_t mMaxEventsPerSecond;
- // Cached display state. (lock mDisplayLock)
- Mutex mDisplayLock;
- int32_t mDisplayWidth, mDisplayHeight;
- int32_t mDisplayOrientation;
+ Mutex mLock;
+ struct Locked {
+ // Display size information.
+ int32_t displayWidth, displayHeight; // -1 when initialized
+ int32_t displayOrientation;
+
+ // Pointer controller singleton, created and destroyed as needed.
+ wp<PointerController> pointerController;
+
+ // Weak references to all currently registered input channels by connection pointer.
+ KeyedVector<InputChannel*, jweak> inputChannelObjWeakTable;
+ } mLocked;
// Power manager interactions.
bool isScreenOn();
bool isScreenBright();
- // Weak references to all currently registered input channels by connection pointer.
- Mutex mInputChannelRegistryLock;
- KeyedVector<InputChannel*, jweak> mInputChannelObjWeakTable;
-
jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
@@ -243,12 +303,18 @@ private:
NativeInputManager::NativeInputManager(jobject callbacksObj) :
mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
- mMaxEventsPerSecond(-1),
- mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0) {
+ mMaxEventsPerSecond(-1) {
JNIEnv* env = jniEnv();
mCallbacksObj = env->NewGlobalRef(callbacksObj);
+ {
+ AutoMutex _l(mLock);
+ mLocked.displayWidth = -1;
+ mLocked.displayHeight = -1;
+ mLocked.displayOrientation = ROTATION_0;
+ }
+
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
@@ -279,18 +345,32 @@ bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const c
void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
if (displayId == 0) {
- AutoMutex _l(mDisplayLock);
+ AutoMutex _l(mLock);
- mDisplayWidth = width;
- mDisplayHeight = height;
+ if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+ mLocked.displayWidth = width;
+ mLocked.displayHeight = height;
+
+ sp<PointerController> controller = mLocked.pointerController.promote();
+ if (controller != NULL) {
+ controller->setDisplaySize(width, height);
+ }
+ }
}
}
void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
if (displayId == 0) {
- AutoMutex _l(mDisplayLock);
+ AutoMutex _l(mLock);
+
+ if (mLocked.displayOrientation != orientation) {
+ mLocked.displayOrientation = orientation;
- mDisplayOrientation = orientation;
+ sp<PointerController> controller = mLocked.pointerController.promote();
+ if (controller != NULL) {
+ controller->setDisplayOrientation(orientation);
+ }
+ }
}
}
@@ -305,9 +385,9 @@ status_t NativeInputManager::registerInputChannel(JNIEnv* env,
status_t status;
{
- AutoMutex _l(mInputChannelRegistryLock);
+ AutoMutex _l(mLock);
- ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
+ ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
if (index >= 0) {
LOGE("Input channel object '%s' has already been registered",
inputChannel->getName().string());
@@ -315,7 +395,7 @@ status_t NativeInputManager::registerInputChannel(JNIEnv* env,
goto DeleteWeakRef;
}
- mInputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
+ mLocked.inputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
}
status = mInputManager->getDispatcher()->registerInputChannel(inputChannel, monitor);
@@ -326,8 +406,8 @@ status_t NativeInputManager::registerInputChannel(JNIEnv* env,
// Failed!
{
- AutoMutex _l(mInputChannelRegistryLock);
- mInputChannelObjWeakTable.removeItem(inputChannel.get());
+ AutoMutex _l(mLock);
+ mLocked.inputChannelObjWeakTable.removeItem(inputChannel.get());
}
DeleteWeakRef:
@@ -339,17 +419,17 @@ status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
const sp<InputChannel>& inputChannel) {
jweak inputChannelObjWeak;
{
- AutoMutex _l(mInputChannelRegistryLock);
+ AutoMutex _l(mLock);
- ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
+ ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
if (index < 0) {
LOGE("Input channel object '%s' is not currently registered",
inputChannel->getName().string());
return INVALID_OPERATION;
}
- inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
- mInputChannelObjWeakTable.removeItemsAt(index);
+ inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
+ mLocked.inputChannelObjWeakTable.removeItemsAt(index);
}
env->DeleteWeakGlobalRef(inputChannelObjWeak);
@@ -365,14 +445,14 @@ jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
}
{
- AutoMutex _l(mInputChannelRegistryLock);
+ AutoMutex _l(mLock);
- ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannelPtr);
+ ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannelPtr);
if (index < 0) {
return NULL;
}
- jweak inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
+ jweak inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
return env->NewLocalRef(inputChannelObjWeak);
}
}
@@ -381,17 +461,17 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId,
int32_t* width, int32_t* height, int32_t* orientation) {
bool result = false;
if (displayId == 0) {
- AutoMutex _l(mDisplayLock);
+ AutoMutex _l(mLock);
- if (mDisplayWidth > 0) {
+ if (mLocked.displayWidth > 0 && mLocked.displayHeight > 0) {
if (width) {
- *width = mDisplayWidth;
+ *width = mLocked.displayWidth;
}
if (height) {
- *height = mDisplayHeight;
+ *height = mLocked.displayHeight;
}
if (orientation) {
- *orientation = mDisplayOrientation;
+ *orientation = mLocked.displayOrientation;
}
result = true;
}
@@ -451,6 +531,24 @@ void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDevi
}
}
+sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32_t deviceId) {
+ AutoMutex _l(mLock);
+
+ sp<PointerController> controller = mLocked.pointerController.promote();
+ if (controller == NULL) {
+ JNIEnv* env = jniEnv();
+ jint layer = env->CallIntMethod(mCallbacksObj, gCallbacksClassInfo.getPointerLayer);
+ checkAndClearExceptionFromCallback(env, "getPointerLayer");
+
+ controller = new PointerController(layer);
+ mLocked.pointerController = controller;
+
+ controller->setDisplaySize(mLocked.displayWidth, mLocked.displayHeight);
+ controller->setDisplayOrientation(mLocked.displayOrientation);
+ }
+ return controller;
+}
+
void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
int32_t switchValue, uint32_t policyFlags) {
#if DEBUG_INPUT_DISPATCHER_POLICY
@@ -886,6 +984,294 @@ bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
return result;
}
+// --- PointerController ---
+
+PointerController::PointerController(int32_t pointerLayer) :
+ mPointerLayer(pointerLayer) {
+ AutoMutex _l(mLock);
+
+ mLocked.displayWidth = -1;
+ mLocked.displayHeight = -1;
+ mLocked.displayOrientation = InputReaderPolicyInterface::ROTATION_0;
+
+ mLocked.pointerX = 0;
+ mLocked.pointerY = 0;
+ mLocked.buttonState = 0;
+
+ mLocked.wantVisible = false;
+ mLocked.visible = false;
+ mLocked.drawn = false;
+}
+
+PointerController::~PointerController() {
+ mSurfaceControl.clear();
+ mSurfaceComposerClient.clear();
+}
+
+bool PointerController::getBounds(float* outMinX, float* outMinY,
+ float* outMaxX, float* outMaxY) const {
+ AutoMutex _l(mLock);
+
+ return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
+}
+
+bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
+ float* outMaxX, float* outMaxY) const {
+ if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) {
+ return false;
+ }
+
+ *outMinX = 0;
+ *outMinY = 0;
+ switch (mLocked.displayOrientation) {
+ case InputReaderPolicyInterface::ROTATION_90:
+ case InputReaderPolicyInterface::ROTATION_270:
+ *outMaxX = mLocked.displayHeight;
+ *outMaxY = mLocked.displayWidth;
+ break;
+ default:
+ *outMaxX = mLocked.displayWidth;
+ *outMaxY = mLocked.displayHeight;
+ break;
+ }
+ return true;
+}
+
+void PointerController::move(float deltaX, float deltaY) {
+#if DEBUG_POINTER_CONTROLLER
+ LOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
+#endif
+ if (deltaX == 0.0f && deltaY == 0.0f) {
+ return;
+ }
+
+ AutoMutex _l(mLock);
+
+ setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
+}
+
+void PointerController::setButtonState(uint32_t buttonState) {
+ AutoMutex _l(mLock);
+
+ if (mLocked.buttonState != buttonState) {
+ mLocked.buttonState = buttonState;
+ mLocked.wantVisible = true;
+ updateLocked();
+ }
+}
+
+uint32_t PointerController::getButtonState() const {
+ AutoMutex _l(mLock);
+
+ return mLocked.buttonState;
+}
+
+void PointerController::setPosition(float x, float y) {
+ AutoMutex _l(mLock);
+
+ setPositionLocked(x, y);
+}
+
+void PointerController::setPositionLocked(float x, float y) {
+ float minX, minY, maxX, maxY;
+ if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
+ if (x <= minX) {
+ mLocked.pointerX = minX;
+ } else if (x >= maxX) {
+ mLocked.pointerX = maxX;
+ } else {
+ mLocked.pointerX = x;
+ }
+ if (y <= minY) {
+ mLocked.pointerY = minY;
+ } else if (y >= maxY) {
+ mLocked.pointerY = maxY;
+ } else {
+ mLocked.pointerY = y;
+ }
+ mLocked.wantVisible = true;
+ updateLocked();
+ }
+}
+
+void PointerController::getPosition(float* outX, float* outY) const {
+ AutoMutex _l(mLock);
+
+ *outX = mLocked.pointerX;
+ *outY = mLocked.pointerY;
+}
+
+void PointerController::updateLocked() {
+#if DEBUG_POINTER_CONTROLLER
+ LOGD("Pointer at (%f, %f).", mLocked.pointerX, mLocked.pointerY);
+#endif
+
+ if (!mLocked.wantVisible && !mLocked.visible) {
+ return;
+ }
+
+ if (mSurfaceComposerClient == NULL) {
+ mSurfaceComposerClient = new SurfaceComposerClient();
+ }
+
+ if (mSurfaceControl == NULL) {
+ mSurfaceControl = mSurfaceComposerClient->createSurface(getpid(),
+ String8("Pointer"), 0, 16, 16, PIXEL_FORMAT_RGBA_8888);
+ if (mSurfaceControl == NULL) {
+ LOGE("Error creating pointer surface.");
+ return;
+ }
+ }
+
+ status_t status = mSurfaceComposerClient->openTransaction();
+ if (status) {
+ LOGE("Error opening surface transaction to update pointer surface.");
+ return;
+ }
+
+ if (mLocked.wantVisible) {
+ if (!mLocked.drawn) {
+ mLocked.drawn = true;
+
+ sp<Surface> surface = mSurfaceControl->getSurface();
+ Surface::SurfaceInfo surfaceInfo;
+ status = surface->lock(&surfaceInfo);
+ if (status) {
+ LOGE("Error %d locking pointer surface before drawing.", status);
+ goto CloseTransaction;
+ }
+
+ // TODO: Load pointers from assets and allow them to be set.
+ char* bitmap = (char*)surfaceInfo.bits;
+ ssize_t bpr = surfaceInfo.s * 4;
+ for (int y = 0; y < surfaceInfo.h; y++) {
+ for (int x = 0; x < surfaceInfo.w; x++) {
+ bitmap[y * bpr + x * 4] = 128;
+ bitmap[y * bpr + x * 4 + 1] = 255;
+ bitmap[y * bpr + x * 4 + 2] = 128;
+ bitmap[y * bpr + x * 4 + 3] = 255;
+ }
+ }
+
+ status = surface->unlockAndPost();
+ if (status) {
+ LOGE("Error %d unlocking pointer surface after drawing.", status);
+ goto CloseTransaction;
+ }
+ }
+
+ status = mSurfaceControl->setPosition(mLocked.pointerX, mLocked.pointerY);
+ if (status) {
+ LOGE("Error %d moving pointer surface.", status);
+ goto CloseTransaction;
+ }
+
+ if (!mLocked.visible) {
+ mLocked.visible = true;
+
+ mSurfaceControl->setLayer(mPointerLayer);
+
+ LOGD("XXX Show");
+ status = mSurfaceControl->show(mPointerLayer);
+ if (status) {
+ LOGE("Error %d showing pointer surface.", status);
+ goto CloseTransaction;
+ }
+ }
+ } else {
+ if (mLocked.visible) {
+ mLocked.visible = false;
+
+ if (mSurfaceControl != NULL) {
+ status = mSurfaceControl->hide();
+ if (status) {
+ LOGE("Error %d hiding pointer surface.", status);
+ goto CloseTransaction;
+ }
+ }
+ }
+ }
+
+CloseTransaction:
+ status = mSurfaceComposerClient->closeTransaction();
+ if (status) {
+ LOGE("Error closing surface transaction to update pointer surface.");
+ }
+}
+
+void PointerController::setDisplaySize(int32_t width, int32_t height) {
+ AutoMutex _l(mLock);
+
+ if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+ mLocked.displayWidth = width;
+ mLocked.displayHeight = height;
+
+ float minX, minY, maxX, maxY;
+ if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
+ mLocked.pointerX = (minX + maxX) * 0.5f;
+ mLocked.pointerY = (minY + maxY) * 0.5f;
+ } else {
+ mLocked.pointerX = 0;
+ mLocked.pointerY = 0;
+ }
+
+ updateLocked();
+ }
+}
+
+void PointerController::setDisplayOrientation(int32_t orientation) {
+ AutoMutex _l(mLock);
+
+ if (mLocked.displayOrientation != orientation) {
+ float absoluteX, absoluteY;
+
+ // Map from oriented display coordinates to absolute display coordinates.
+ switch (mLocked.displayOrientation) {
+ case InputReaderPolicyInterface::ROTATION_90:
+ absoluteX = mLocked.displayWidth - mLocked.pointerY;
+ absoluteY = mLocked.pointerX;
+ break;
+ case InputReaderPolicyInterface::ROTATION_180:
+ absoluteX = mLocked.displayWidth - mLocked.pointerX;
+ absoluteY = mLocked.displayHeight - mLocked.pointerY;
+ break;
+ case InputReaderPolicyInterface::ROTATION_270:
+ absoluteX = mLocked.pointerY;
+ absoluteY = mLocked.displayHeight - mLocked.pointerX;
+ break;
+ default:
+ absoluteX = mLocked.pointerX;
+ absoluteY = mLocked.pointerY;
+ break;
+ }
+
+ // Map from absolute display coordinates to oriented display coordinates.
+ switch (orientation) {
+ case InputReaderPolicyInterface::ROTATION_90:
+ mLocked.pointerX = absoluteY;
+ mLocked.pointerY = mLocked.displayWidth - absoluteX;
+ break;
+ case InputReaderPolicyInterface::ROTATION_180:
+ mLocked.pointerX = mLocked.displayWidth - absoluteX;
+ mLocked.pointerY = mLocked.displayHeight - absoluteY;
+ break;
+ case InputReaderPolicyInterface::ROTATION_270:
+ mLocked.pointerX = mLocked.displayHeight - absoluteY;
+ mLocked.pointerY = absoluteX;
+ break;
+ default:
+ mLocked.pointerX = absoluteX;
+ mLocked.pointerY = absoluteY;
+ break;
+ }
+
+ mLocked.displayOrientation = orientation;
+
+ updateLocked();
+ }
+}
+
+
// ----------------------------------------------------------------------------
static sp<NativeInputManager> gNativeInputManager;
@@ -1326,6 +1712,9 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
"getMaxEventsPerSecond", "()I");
+ GET_METHOD_ID(gCallbacksClassInfo.getPointerLayer, gCallbacksClassInfo.clazz,
+ "getPointerLayer", "()I");
+
// InputWindow
FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");