Merge "Add unit tests for native input and fix bugs identified." into gingerbread
This commit is contained in:
commit
f35c873501
@ -170,11 +170,10 @@ public:
|
||||
* and parameters maintained by the input reader.
|
||||
*/
|
||||
class InputReaderContext {
|
||||
protected:
|
||||
public:
|
||||
InputReaderContext() { }
|
||||
virtual ~InputReaderContext() { }
|
||||
|
||||
public:
|
||||
virtual void updateGlobalMetaState() = 0;
|
||||
virtual int32_t getGlobalMetaState() = 0;
|
||||
|
||||
@ -193,7 +192,7 @@ public:
|
||||
* the input reader, the input reader never calls into other components while holding
|
||||
* an exclusive internal lock whenever re-entrance can happen.
|
||||
*/
|
||||
class InputReader : public InputReaderInterface, private InputReaderContext {
|
||||
class InputReader : public InputReaderInterface, protected InputReaderContext {
|
||||
public:
|
||||
InputReader(const sp<EventHubInterface>& eventHub,
|
||||
const sp<InputReaderPolicyInterface>& policy,
|
||||
@ -219,6 +218,11 @@ public:
|
||||
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
|
||||
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:
|
||||
sp<EventHubInterface> mEventHub;
|
||||
sp<InputReaderPolicyInterface> mPolicy;
|
||||
@ -244,12 +248,11 @@ private:
|
||||
|
||||
void addDevice(int32_t deviceId);
|
||||
void removeDevice(int32_t deviceId);
|
||||
InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
|
||||
void configureExcludedDevices();
|
||||
|
||||
void consumeEvent(const RawEvent* rawEvent);
|
||||
|
||||
void handleConfigurationChanged();
|
||||
void handleConfigurationChanged(nsecs_t when);
|
||||
|
||||
// state management for all devices
|
||||
Mutex mStateLock;
|
||||
@ -533,6 +536,21 @@ protected:
|
||||
int32_t toolMajor;
|
||||
int32_t toolMinor;
|
||||
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.
|
||||
|
@ -370,6 +370,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
||||
outEvent->deviceId = device->id;
|
||||
}
|
||||
outEvent->type = DEVICE_REMOVED;
|
||||
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
delete device;
|
||||
mNeedToSendFinishedDeviceScan = true;
|
||||
return true;
|
||||
@ -386,6 +387,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
||||
outEvent->deviceId = device->id;
|
||||
}
|
||||
outEvent->type = DEVICE_ADDED;
|
||||
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
mNeedToSendFinishedDeviceScan = true;
|
||||
return true;
|
||||
}
|
||||
@ -393,6 +395,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
||||
if (mNeedToSendFinishedDeviceScan) {
|
||||
mNeedToSendFinishedDeviceScan = false;
|
||||
outEvent->type = FINISHED_DEVICE_SCAN;
|
||||
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -124,12 +124,19 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount,
|
||||
pointerCount, MAX_POINTERS);
|
||||
return false;
|
||||
}
|
||||
BitSet32 pointerIdBits;
|
||||
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",
|
||||
pointerIds[i], MAX_POINTER_ID);
|
||||
id, MAX_POINTER_ID);
|
||||
return false;
|
||||
}
|
||||
if (pointerIdBits.hasBit(id)) {
|
||||
LOGE("Motion event has duplicate pointer id %d", id);
|
||||
return false;
|
||||
}
|
||||
pointerIdBits.markBit(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ void InputReader::process(const RawEvent* rawEvent) {
|
||||
break;
|
||||
|
||||
case EventHubInterface::FINISHED_DEVICE_SCAN:
|
||||
handleConfigurationChanged();
|
||||
handleConfigurationChanged(rawEvent->when);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -372,7 +372,7 @@ void InputReader::consumeEvent(const RawEvent* rawEvent) {
|
||||
} // 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.
|
||||
updateGlobalMetaState();
|
||||
|
||||
@ -380,7 +380,6 @@ void InputReader::handleConfigurationChanged() {
|
||||
updateInputConfiguration();
|
||||
|
||||
// Enqueue configuration changed.
|
||||
nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
mDispatcher->notifyConfigurationChanged(when);
|
||||
}
|
||||
|
||||
@ -2094,7 +2093,7 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
|
||||
mLocked.currentVirtualKey.down = false;
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
|
||||
mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
|
||||
mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
|
||||
#endif
|
||||
keyEventAction = AKEY_EVENT_ACTION_UP;
|
||||
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
|
||||
@ -2119,13 +2118,22 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
|
||||
mLocked.currentVirtualKey.down = false;
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
|
||||
mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
|
||||
mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
|
||||
#endif
|
||||
keyEventAction = AKEY_EVENT_ACTION_UP;
|
||||
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
|
||||
| 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 {
|
||||
if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
|
||||
// Pointer just went down. Handle off-screen touches, if needed.
|
||||
@ -2143,7 +2151,8 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
|
||||
mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
|
||||
mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
|
||||
mLocked.currentVirtualKey.keyCode,
|
||||
mLocked.currentVirtualKey.scanCode);
|
||||
#endif
|
||||
keyEventAction = AKEY_EVENT_ACTION_DOWN;
|
||||
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
|
||||
@ -2190,14 +2199,35 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
|
||||
dispatchTouch(when, policyFlags, & mCurrentTouch,
|
||||
currentIdBits, -1, currentPointerCount, motionEventAction);
|
||||
} else {
|
||||
// There may be pointers going up and pointers going down at the same time when pointer
|
||||
// ids are reported by the device driver.
|
||||
// There may be pointers going up and pointers going down and pointers moving
|
||||
// all at the same time.
|
||||
BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
|
||||
BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
|
||||
BitSet32 activeIdBits(lastIdBits.value);
|
||||
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();
|
||||
upIdBits.clearBit(upId);
|
||||
BitSet32 oldActiveIdBits = activeIdBits;
|
||||
@ -2210,12 +2240,21 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
|
||||
motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
|
||||
}
|
||||
|
||||
dispatchTouch(when, policyFlags, & mLastTouch,
|
||||
dispatchTouch(when, policyFlags, &interimTouch,
|
||||
oldActiveIdBits, upId, pointerCount, motionEventAction);
|
||||
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();
|
||||
downIdBits.clearBit(downId);
|
||||
BitSet32 oldActiveIdBits = activeIdBits;
|
||||
@ -2230,7 +2269,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
|
||||
}
|
||||
|
||||
pointerCount += 1;
|
||||
dispatchTouch(when, policyFlags, & mCurrentTouch,
|
||||
dispatchTouch(when, policyFlags, &mCurrentTouch,
|
||||
activeIdBits, downId, pointerCount, motionEventAction);
|
||||
}
|
||||
}
|
||||
@ -3339,8 +3378,8 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
|
||||
|
||||
if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
|
||||
if (inPointer.absMTPressure <= 0) {
|
||||
// Some devices send sync packets with X / Y but with a 0 presure to indicate
|
||||
// a pointer up. Drop this finger.
|
||||
// Some devices send sync packets with X / Y but with a 0 pressure to indicate
|
||||
// a pointer going up. Drop this finger.
|
||||
continue;
|
||||
}
|
||||
outPointer.pressure = inPointer.absMTPressure;
|
||||
|
@ -7,6 +7,7 @@ ifneq ($(TARGET_SIMULATOR),true)
|
||||
# Build the unit tests.
|
||||
test_src_files := \
|
||||
InputChannel_test.cpp \
|
||||
InputReader_test.cpp \
|
||||
InputDispatcher_test.cpp \
|
||||
InputPublisherAndConsumer_test.cpp
|
||||
|
||||
|
@ -4,15 +4,223 @@
|
||||
|
||||
#include <ui/InputDispatcher.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
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:
|
||||
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
|
||||
|
3368
libs/ui/tests/InputReader_test.cpp
Normal file
3368
libs/ui/tests/InputReader_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user