am 2ef36763: am 860c2df4: Merge "Add unit tests for native input and fix bugs identified." into gingerbread
Merge commit '2ef36763700eff5679d6012e7f078c57f1a4c465' * commit '2ef36763700eff5679d6012e7f078c57f1a4c465': Add unit tests for native input and fix bugs identified.
This commit is contained in:
commit
bc9f053156
|
@ -170,11 +170,10 @@ public:
|
||||||
* and parameters maintained by the input reader.
|
* and parameters maintained by the input reader.
|
||||||
*/
|
*/
|
||||||
class InputReaderContext {
|
class InputReaderContext {
|
||||||
protected:
|
public:
|
||||||
InputReaderContext() { }
|
InputReaderContext() { }
|
||||||
virtual ~InputReaderContext() { }
|
virtual ~InputReaderContext() { }
|
||||||
|
|
||||||
public:
|
|
||||||
virtual void updateGlobalMetaState() = 0;
|
virtual void updateGlobalMetaState() = 0;
|
||||||
virtual int32_t getGlobalMetaState() = 0;
|
virtual int32_t getGlobalMetaState() = 0;
|
||||||
|
|
||||||
|
@ -193,7 +192,7 @@ public:
|
||||||
* the input reader, the input reader never calls into other components while holding
|
* the input reader, the input reader never calls into other components while holding
|
||||||
* an exclusive internal lock whenever re-entrance can happen.
|
* an exclusive internal lock whenever re-entrance can happen.
|
||||||
*/
|
*/
|
||||||
class InputReader : public InputReaderInterface, private InputReaderContext {
|
class InputReader : public InputReaderInterface, protected InputReaderContext {
|
||||||
public:
|
public:
|
||||||
InputReader(const sp<EventHubInterface>& eventHub,
|
InputReader(const sp<EventHubInterface>& eventHub,
|
||||||
const sp<InputReaderPolicyInterface>& policy,
|
const sp<InputReaderPolicyInterface>& policy,
|
||||||
|
@ -219,6 +218,11 @@ public:
|
||||||
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
|
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
|
||||||
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
|
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// These methods are protected virtual so they can be overridden and instrumented
|
||||||
|
// by test cases.
|
||||||
|
virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sp<EventHubInterface> mEventHub;
|
sp<EventHubInterface> mEventHub;
|
||||||
sp<InputReaderPolicyInterface> mPolicy;
|
sp<InputReaderPolicyInterface> mPolicy;
|
||||||
|
@ -244,12 +248,11 @@ private:
|
||||||
|
|
||||||
void addDevice(int32_t deviceId);
|
void addDevice(int32_t deviceId);
|
||||||
void removeDevice(int32_t deviceId);
|
void removeDevice(int32_t deviceId);
|
||||||
InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
|
|
||||||
void configureExcludedDevices();
|
void configureExcludedDevices();
|
||||||
|
|
||||||
void consumeEvent(const RawEvent* rawEvent);
|
void consumeEvent(const RawEvent* rawEvent);
|
||||||
|
|
||||||
void handleConfigurationChanged();
|
void handleConfigurationChanged(nsecs_t when);
|
||||||
|
|
||||||
// state management for all devices
|
// state management for all devices
|
||||||
Mutex mStateLock;
|
Mutex mStateLock;
|
||||||
|
@ -546,6 +549,21 @@ protected:
|
||||||
int32_t toolMajor;
|
int32_t toolMajor;
|
||||||
int32_t toolMinor;
|
int32_t toolMinor;
|
||||||
int32_t orientation;
|
int32_t orientation;
|
||||||
|
|
||||||
|
inline bool operator== (const PointerData& other) const {
|
||||||
|
return id == other.id
|
||||||
|
&& x == other.x
|
||||||
|
&& y == other.y
|
||||||
|
&& pressure == other.pressure
|
||||||
|
&& touchMajor == other.touchMajor
|
||||||
|
&& touchMinor == other.touchMinor
|
||||||
|
&& toolMajor == other.toolMajor
|
||||||
|
&& toolMinor == other.toolMinor
|
||||||
|
&& orientation == other.orientation;
|
||||||
|
}
|
||||||
|
inline bool operator!= (const PointerData& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Raw data for a collection of pointers including a pointer id mapping table.
|
// Raw data for a collection of pointers including a pointer id mapping table.
|
||||||
|
|
|
@ -403,6 +403,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
||||||
outEvent->deviceId = device->id;
|
outEvent->deviceId = device->id;
|
||||||
}
|
}
|
||||||
outEvent->type = DEVICE_REMOVED;
|
outEvent->type = DEVICE_REMOVED;
|
||||||
|
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
delete device;
|
delete device;
|
||||||
mNeedToSendFinishedDeviceScan = true;
|
mNeedToSendFinishedDeviceScan = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -419,6 +420,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
||||||
outEvent->deviceId = device->id;
|
outEvent->deviceId = device->id;
|
||||||
}
|
}
|
||||||
outEvent->type = DEVICE_ADDED;
|
outEvent->type = DEVICE_ADDED;
|
||||||
|
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
mNeedToSendFinishedDeviceScan = true;
|
mNeedToSendFinishedDeviceScan = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -426,6 +428,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
||||||
if (mNeedToSendFinishedDeviceScan) {
|
if (mNeedToSendFinishedDeviceScan) {
|
||||||
mNeedToSendFinishedDeviceScan = false;
|
mNeedToSendFinishedDeviceScan = false;
|
||||||
outEvent->type = FINISHED_DEVICE_SCAN;
|
outEvent->type = FINISHED_DEVICE_SCAN;
|
||||||
|
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,12 +124,19 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount,
|
||||||
pointerCount, MAX_POINTERS);
|
pointerCount, MAX_POINTERS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
BitSet32 pointerIdBits;
|
||||||
for (size_t i = 0; i < pointerCount; i++) {
|
for (size_t i = 0; i < pointerCount; i++) {
|
||||||
if (pointerIds[i] < 0 || pointerIds[i] > MAX_POINTER_ID) {
|
int32_t id = pointerIds[i];
|
||||||
|
if (id < 0 || id > MAX_POINTER_ID) {
|
||||||
LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
|
LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
|
||||||
pointerIds[i], MAX_POINTER_ID);
|
id, MAX_POINTER_ID);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (pointerIdBits.hasBit(id)) {
|
||||||
|
LOGE("Motion event has duplicate pointer id %d", id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pointerIdBits.markBit(id);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,7 +266,7 @@ void InputReader::process(const RawEvent* rawEvent) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventHubInterface::FINISHED_DEVICE_SCAN:
|
case EventHubInterface::FINISHED_DEVICE_SCAN:
|
||||||
handleConfigurationChanged();
|
handleConfigurationChanged(rawEvent->when);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -404,7 +404,7 @@ void InputReader::consumeEvent(const RawEvent* rawEvent) {
|
||||||
} // release device registry reader lock
|
} // release device registry reader lock
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputReader::handleConfigurationChanged() {
|
void InputReader::handleConfigurationChanged(nsecs_t when) {
|
||||||
// Reset global meta state because it depends on the list of all configured devices.
|
// Reset global meta state because it depends on the list of all configured devices.
|
||||||
updateGlobalMetaState();
|
updateGlobalMetaState();
|
||||||
|
|
||||||
|
@ -412,7 +412,6 @@ void InputReader::handleConfigurationChanged() {
|
||||||
updateInputConfiguration();
|
updateInputConfiguration();
|
||||||
|
|
||||||
// Enqueue configuration changed.
|
// Enqueue configuration changed.
|
||||||
nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
|
|
||||||
mDispatcher->notifyConfigurationChanged(when);
|
mDispatcher->notifyConfigurationChanged(when);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2189,7 +2188,7 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
|
||||||
mLocked.currentVirtualKey.down = false;
|
mLocked.currentVirtualKey.down = false;
|
||||||
#if DEBUG_VIRTUAL_KEYS
|
#if DEBUG_VIRTUAL_KEYS
|
||||||
LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
|
LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
|
||||||
mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
|
mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
|
||||||
#endif
|
#endif
|
||||||
keyEventAction = AKEY_EVENT_ACTION_UP;
|
keyEventAction = AKEY_EVENT_ACTION_UP;
|
||||||
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
|
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
|
||||||
|
@ -2214,13 +2213,22 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
|
||||||
mLocked.currentVirtualKey.down = false;
|
mLocked.currentVirtualKey.down = false;
|
||||||
#if DEBUG_VIRTUAL_KEYS
|
#if DEBUG_VIRTUAL_KEYS
|
||||||
LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
|
LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
|
||||||
mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
|
mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
|
||||||
#endif
|
#endif
|
||||||
keyEventAction = AKEY_EVENT_ACTION_UP;
|
keyEventAction = AKEY_EVENT_ACTION_UP;
|
||||||
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
|
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
|
||||||
| AKEY_EVENT_FLAG_CANCELED;
|
| AKEY_EVENT_FLAG_CANCELED;
|
||||||
touchResult = DROP_STROKE;
|
|
||||||
goto DispatchVirtualKey;
|
// Check whether the pointer moved inside the display area where we should
|
||||||
|
// start a new stroke.
|
||||||
|
int32_t x = mCurrentTouch.pointers[0].x;
|
||||||
|
int32_t y = mCurrentTouch.pointers[0].y;
|
||||||
|
if (isPointInsideSurfaceLocked(x, y)) {
|
||||||
|
mLastTouch.clear();
|
||||||
|
touchResult = DISPATCH_TOUCH;
|
||||||
|
} else {
|
||||||
|
touchResult = DROP_STROKE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
|
if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
|
||||||
// Pointer just went down. Handle off-screen touches, if needed.
|
// Pointer just went down. Handle off-screen touches, if needed.
|
||||||
|
@ -2238,7 +2246,8 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
|
||||||
mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
|
mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
|
||||||
#if DEBUG_VIRTUAL_KEYS
|
#if DEBUG_VIRTUAL_KEYS
|
||||||
LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
|
LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
|
||||||
mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
|
mLocked.currentVirtualKey.keyCode,
|
||||||
|
mLocked.currentVirtualKey.scanCode);
|
||||||
#endif
|
#endif
|
||||||
keyEventAction = AKEY_EVENT_ACTION_DOWN;
|
keyEventAction = AKEY_EVENT_ACTION_DOWN;
|
||||||
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
|
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
|
||||||
|
@ -2285,14 +2294,35 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
|
||||||
dispatchTouch(when, policyFlags, & mCurrentTouch,
|
dispatchTouch(when, policyFlags, & mCurrentTouch,
|
||||||
currentIdBits, -1, currentPointerCount, motionEventAction);
|
currentIdBits, -1, currentPointerCount, motionEventAction);
|
||||||
} else {
|
} else {
|
||||||
// There may be pointers going up and pointers going down at the same time when pointer
|
// There may be pointers going up and pointers going down and pointers moving
|
||||||
// ids are reported by the device driver.
|
// all at the same time.
|
||||||
BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
|
BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
|
||||||
BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
|
BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
|
||||||
BitSet32 activeIdBits(lastIdBits.value);
|
BitSet32 activeIdBits(lastIdBits.value);
|
||||||
uint32_t pointerCount = lastPointerCount;
|
uint32_t pointerCount = lastPointerCount;
|
||||||
|
|
||||||
while (! upIdBits.isEmpty()) {
|
// Produce an intermediate representation of the touch data that consists of the
|
||||||
|
// old location of pointers that have just gone up and the new location of pointers that
|
||||||
|
// have just moved but omits the location of pointers that have just gone down.
|
||||||
|
TouchData interimTouch;
|
||||||
|
interimTouch.copyFrom(mLastTouch);
|
||||||
|
|
||||||
|
BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
|
||||||
|
bool moveNeeded = false;
|
||||||
|
while (!moveIdBits.isEmpty()) {
|
||||||
|
uint32_t moveId = moveIdBits.firstMarkedBit();
|
||||||
|
moveIdBits.clearBit(moveId);
|
||||||
|
|
||||||
|
int32_t oldIndex = mLastTouch.idToIndex[moveId];
|
||||||
|
int32_t newIndex = mCurrentTouch.idToIndex[moveId];
|
||||||
|
if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
|
||||||
|
interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
|
||||||
|
moveNeeded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch pointer up events using the interim pointer locations.
|
||||||
|
while (!upIdBits.isEmpty()) {
|
||||||
uint32_t upId = upIdBits.firstMarkedBit();
|
uint32_t upId = upIdBits.firstMarkedBit();
|
||||||
upIdBits.clearBit(upId);
|
upIdBits.clearBit(upId);
|
||||||
BitSet32 oldActiveIdBits = activeIdBits;
|
BitSet32 oldActiveIdBits = activeIdBits;
|
||||||
|
@ -2305,12 +2335,21 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
|
||||||
motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
|
motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchTouch(when, policyFlags, & mLastTouch,
|
dispatchTouch(when, policyFlags, &interimTouch,
|
||||||
oldActiveIdBits, upId, pointerCount, motionEventAction);
|
oldActiveIdBits, upId, pointerCount, motionEventAction);
|
||||||
pointerCount -= 1;
|
pointerCount -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (! downIdBits.isEmpty()) {
|
// Dispatch move events if any of the remaining pointers moved from their old locations.
|
||||||
|
// Although applications receive new locations as part of individual pointer up
|
||||||
|
// events, they do not generally handle them except when presented in a move event.
|
||||||
|
if (moveNeeded) {
|
||||||
|
dispatchTouch(when, policyFlags, &mCurrentTouch,
|
||||||
|
activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch pointer down events using the new pointer locations.
|
||||||
|
while (!downIdBits.isEmpty()) {
|
||||||
uint32_t downId = downIdBits.firstMarkedBit();
|
uint32_t downId = downIdBits.firstMarkedBit();
|
||||||
downIdBits.clearBit(downId);
|
downIdBits.clearBit(downId);
|
||||||
BitSet32 oldActiveIdBits = activeIdBits;
|
BitSet32 oldActiveIdBits = activeIdBits;
|
||||||
|
@ -2325,7 +2364,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pointerCount += 1;
|
pointerCount += 1;
|
||||||
dispatchTouch(when, policyFlags, & mCurrentTouch,
|
dispatchTouch(when, policyFlags, &mCurrentTouch,
|
||||||
activeIdBits, downId, pointerCount, motionEventAction);
|
activeIdBits, downId, pointerCount, motionEventAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3434,8 +3473,8 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
|
||||||
|
|
||||||
if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
|
if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
|
||||||
if (inPointer.absMTPressure <= 0) {
|
if (inPointer.absMTPressure <= 0) {
|
||||||
// Some devices send sync packets with X / Y but with a 0 presure to indicate
|
// Some devices send sync packets with X / Y but with a 0 pressure to indicate
|
||||||
// a pointer up. Drop this finger.
|
// a pointer going up. Drop this finger.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
outPointer.pressure = inPointer.absMTPressure;
|
outPointer.pressure = inPointer.absMTPressure;
|
||||||
|
|
|
@ -7,6 +7,7 @@ ifneq ($(TARGET_SIMULATOR),true)
|
||||||
# Build the unit tests.
|
# Build the unit tests.
|
||||||
test_src_files := \
|
test_src_files := \
|
||||||
InputChannel_test.cpp \
|
InputChannel_test.cpp \
|
||||||
|
InputReader_test.cpp \
|
||||||
InputDispatcher_test.cpp \
|
InputDispatcher_test.cpp \
|
||||||
InputPublisherAndConsumer_test.cpp
|
InputPublisherAndConsumer_test.cpp
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,223 @@
|
||||||
|
|
||||||
#include <ui/InputDispatcher.h>
|
#include <ui/InputDispatcher.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
class InputDispatcherTest : public testing::Test {
|
// An arbitrary time value.
|
||||||
|
static const nsecs_t ARBITRARY_TIME = 1234;
|
||||||
|
|
||||||
|
// An arbitrary device id.
|
||||||
|
static const int32_t DEVICE_ID = 1;
|
||||||
|
|
||||||
|
// An arbitrary injector pid / uid pair that has permission to inject events.
|
||||||
|
static const int32_t INJECTOR_PID = 999;
|
||||||
|
static const int32_t INJECTOR_UID = 1001;
|
||||||
|
|
||||||
|
|
||||||
|
// --- FakeInputDispatcherPolicy ---
|
||||||
|
|
||||||
|
class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
|
||||||
|
protected:
|
||||||
|
virtual ~FakeInputDispatcherPolicy() {
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
FakeInputDispatcherPolicy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void notifyConfigurationChanged(nsecs_t when) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
|
||||||
|
const sp<InputChannel>& inputChannel) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nsecs_t getKeyRepeatTimeout() {
|
||||||
|
return 500 * 1000000LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nsecs_t getKeyRepeatDelay() {
|
||||||
|
return 50 * 1000000LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int32_t getMaxEventsPerSecond() {
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId,
|
||||||
|
int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode,
|
||||||
|
uint32_t& policyFlags) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
||||||
|
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void notifySwitch(nsecs_t when,
|
||||||
|
int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool checkInjectEventsPermissionNonReentrant(
|
||||||
|
int32_t injectorPid, int32_t injectorUid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(InputDispatcherTest, Dummy) {
|
|
||||||
// TODO
|
// --- InputDispatcherTest ---
|
||||||
|
|
||||||
|
class InputDispatcherTest : public testing::Test {
|
||||||
|
protected:
|
||||||
|
sp<FakeInputDispatcherPolicy> mFakePolicy;
|
||||||
|
sp<InputDispatcher> mDispatcher;
|
||||||
|
|
||||||
|
virtual void SetUp() {
|
||||||
|
mFakePolicy = new FakeInputDispatcherPolicy();
|
||||||
|
mDispatcher = new InputDispatcher(mFakePolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() {
|
||||||
|
mFakePolicy.clear();
|
||||||
|
mDispatcher.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
|
||||||
|
KeyEvent event;
|
||||||
|
|
||||||
|
// Rejects undefined key actions.
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
|
||||||
|
/*action*/ -1, 0,
|
||||||
|
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject key events with undefined action.";
|
||||||
|
|
||||||
|
// Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
|
||||||
|
AKEY_EVENT_ACTION_MULTIPLE, 0,
|
||||||
|
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject key events with ACTION_MULTIPLE.";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
||||||
|
MotionEvent event;
|
||||||
|
int32_t pointerIds[MAX_POINTERS + 1];
|
||||||
|
PointerCoords pointerCoords[MAX_POINTERS + 1];
|
||||||
|
for (int i = 0; i <= MAX_POINTERS; i++) {
|
||||||
|
pointerIds[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rejects undefined motion actions.
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
/*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 1, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with undefined action.";
|
||||||
|
|
||||||
|
// Rejects pointer down with invalid index.
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
|
||||||
|
0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 1, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with pointer down index too large.";
|
||||||
|
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
|
||||||
|
0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 1, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with pointer down index too small.";
|
||||||
|
|
||||||
|
// Rejects pointer up with invalid index.
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
|
||||||
|
0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 1, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with pointer up index too large.";
|
||||||
|
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
|
||||||
|
0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 1, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with pointer up index too small.";
|
||||||
|
|
||||||
|
// Rejects motion events with invalid number of pointers.
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 0, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with 0 pointers.";
|
||||||
|
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with more than MAX_POINTERS pointers.";
|
||||||
|
|
||||||
|
// Rejects motion events with invalid pointer ids.
|
||||||
|
pointerIds[0] = -1;
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 1, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with pointer ids less than 0.";
|
||||||
|
|
||||||
|
pointerIds[0] = MAX_POINTER_ID + 1;
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 1, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
|
||||||
|
|
||||||
|
// Rejects motion events with duplicate pointer ids.
|
||||||
|
pointerIds[0] = 1;
|
||||||
|
pointerIds[1] = 1;
|
||||||
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
|
||||||
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
|
||||||
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
|
/*pointerCount*/ 2, pointerIds, pointerCoords);
|
||||||
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
||||||
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
|
||||||
|
<< "Should reject motion events with duplicate pointer ids.";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue