diff options
Diffstat (limited to 'libs/ui')
-rw-r--r-- | libs/ui/Input.cpp | 56 | ||||
-rw-r--r-- | libs/ui/KeyLayoutMap.cpp | 70 | ||||
-rw-r--r-- | libs/ui/Keyboard.cpp | 24 | ||||
-rw-r--r-- | libs/ui/tests/InputEvent_test.cpp | 425 |
4 files changed, 430 insertions, 145 deletions
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp index e3107d5..a80320e 100644 --- a/libs/ui/Input.cpp +++ b/libs/ui/Input.cpp @@ -250,11 +250,59 @@ void KeyEvent::initialize(const KeyEvent& from) { // --- PointerCoords --- +float PointerCoords::getAxisValue(int32_t axis) const { + if (axis < 0 || axis > 63) { + return 0; + } + + uint64_t axisBit = 1LL << axis; + if (!(bits & axisBit)) { + return 0; + } + uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); + return values[index]; +} + +status_t PointerCoords::setAxisValue(int32_t axis, float value) { + if (axis < 0 || axis > 63) { + return NAME_NOT_FOUND; + } + + uint64_t axisBit = 1LL << axis; + uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); + if (!(bits & axisBit)) { + uint32_t count = __builtin_popcountll(bits); + if (count >= MAX_AXES) { + tooManyAxes(axis); + return NO_MEMORY; + } + bits |= axisBit; + for (uint32_t i = count; i > index; i--) { + values[i] = values[i - 1]; + } + } + values[index] = value; + return OK; +} + +float* PointerCoords::editAxisValue(int32_t axis) { + if (axis < 0 || axis > 63) { + return NULL; + } + + uint64_t axisBit = 1LL << axis; + if (!(bits & axisBit)) { + return NULL; + } + uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); + return &values[index]; +} + #ifdef HAVE_ANDROID_OS status_t PointerCoords::readFromParcel(Parcel* parcel) { - bits = parcel->readInt32(); + bits = parcel->readInt64(); - uint32_t count = __builtin_popcount(bits); + uint32_t count = __builtin_popcountll(bits); if (count > MAX_AXES) { return BAD_VALUE; } @@ -266,9 +314,9 @@ status_t PointerCoords::readFromParcel(Parcel* parcel) { } status_t PointerCoords::writeToParcel(Parcel* parcel) const { - parcel->writeInt32(bits); + parcel->writeInt64(bits); - uint32_t count = __builtin_popcount(bits); + uint32_t count = __builtin_popcountll(bits); for (uint32_t i = 0; i < count; i++) { parcel->writeInt32(values[i]); } diff --git a/libs/ui/KeyLayoutMap.cpp b/libs/ui/KeyLayoutMap.cpp index 56bc26f..2ed0e66 100644 --- a/libs/ui/KeyLayoutMap.cpp +++ b/libs/ui/KeyLayoutMap.cpp @@ -82,11 +82,11 @@ status_t KeyLayoutMap::load(const String8& filename, KeyLayoutMap** outMap) { return status; } -status_t KeyLayoutMap::map(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const { +status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const { ssize_t index = mKeys.indexOfKey(scanCode); if (index < 0) { #if DEBUG_MAPPING - LOGD("map: scanCode=%d ~ Failed.", scanCode); + LOGD("mapKey: scanCode=%d ~ Failed.", scanCode); #endif *keyCode = AKEYCODE_UNKNOWN; *flags = 0; @@ -98,12 +98,12 @@ status_t KeyLayoutMap::map(int32_t scanCode, int32_t* keyCode, uint32_t* flags) *flags = k.flags; #if DEBUG_MAPPING - LOGD("map: scanCode=%d ~ Result keyCode=%d, flags=0x%08x.", scanCode, *keyCode, *flags); + LOGD("mapKey: scanCode=%d ~ Result keyCode=%d, flags=0x%08x.", scanCode, *keyCode, *flags); #endif return NO_ERROR; } -status_t KeyLayoutMap::findScanCodes(int32_t keyCode, Vector<int32_t>* outScanCodes) const { +status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const { const size_t N = mKeys.size(); for (size_t i=0; i<N; i++) { if (mKeys.valueAt(i).keyCode == keyCode) { @@ -113,6 +113,25 @@ status_t KeyLayoutMap::findScanCodes(int32_t keyCode, Vector<int32_t>* outScanCo return NO_ERROR; } +status_t KeyLayoutMap::mapAxis(int32_t scanCode, int32_t* axis) const { + ssize_t index = mAxes.indexOfKey(scanCode); + if (index < 0) { +#if DEBUG_MAPPING + LOGD("mapAxis: scanCode=%d ~ Failed.", scanCode); +#endif + *axis = -1; + return NAME_NOT_FOUND; + } + + *axis = mAxes.valueAt(index); + +#if DEBUG_MAPPING + LOGD("mapAxis: scanCode=%d ~ Result axis=%d.", scanCode, *axis); +#endif + return NO_ERROR; +} + + // --- KeyLayoutMap::Parser --- KeyLayoutMap::Parser::Parser(KeyLayoutMap* map, Tokenizer* tokenizer) : @@ -137,6 +156,10 @@ status_t KeyLayoutMap::Parser::parse() { mTokenizer->skipDelimiters(WHITESPACE); status_t status = parseKey(); if (status) return status; + } else if (keywordToken == "axis") { + mTokenizer->skipDelimiters(WHITESPACE); + status_t status = parseAxis(); + if (status) return status; } else { LOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), keywordToken.string()); @@ -162,12 +185,12 @@ status_t KeyLayoutMap::Parser::parseKey() { char* end; int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0)); if (*end) { - LOGE("%s: Expected scan code number, got '%s'.", mTokenizer->getLocation().string(), + LOGE("%s: Expected key scan code number, got '%s'.", mTokenizer->getLocation().string(), scanCodeToken.string()); return BAD_VALUE; } if (mMap->mKeys.indexOfKey(scanCode) >= 0) { - LOGE("%s: Duplicate entry for scan code '%s'.", mTokenizer->getLocation().string(), + LOGE("%s: Duplicate entry for key scan code '%s'.", mTokenizer->getLocation().string(), scanCodeToken.string()); return BAD_VALUE; } @@ -189,12 +212,12 @@ status_t KeyLayoutMap::Parser::parseKey() { String8 flagToken = mTokenizer->nextToken(WHITESPACE); uint32_t flag = getKeyFlagByLabel(flagToken.string()); if (!flag) { - LOGE("%s: Expected flag label, got '%s'.", mTokenizer->getLocation().string(), + LOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(), flagToken.string()); return BAD_VALUE; } if (flags & flag) { - LOGE("%s: Duplicate flag '%s'.", mTokenizer->getLocation().string(), + LOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(), flagToken.string()); return BAD_VALUE; } @@ -211,4 +234,35 @@ status_t KeyLayoutMap::Parser::parseKey() { return NO_ERROR; } +status_t KeyLayoutMap::Parser::parseAxis() { + String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE); + char* end; + int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0)); + if (*end) { + LOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(), + scanCodeToken.string()); + return BAD_VALUE; + } + if (mMap->mAxes.indexOfKey(scanCode) >= 0) { + LOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(), + scanCodeToken.string()); + return BAD_VALUE; + } + + mTokenizer->skipDelimiters(WHITESPACE); + String8 axisToken = mTokenizer->nextToken(WHITESPACE); + int32_t axis = getAxisByLabel(axisToken.string()); + if (axis < 0) { + LOGE("%s: Expected axis label, got '%s'.", mTokenizer->getLocation().string(), + axisToken.string()); + return BAD_VALUE; + } + +#if DEBUG_PARSER + LOGD("Parsed axis: scanCode=%d, axis=%d.", scanCode, axis); +#endif + mMap->mAxes.add(scanCode, axis); + return NO_ERROR; +} + }; diff --git a/libs/ui/Keyboard.cpp b/libs/ui/Keyboard.cpp index 6faa600..8b6300a 100644 --- a/libs/ui/Keyboard.cpp +++ b/libs/ui/Keyboard.cpp @@ -217,7 +217,7 @@ status_t getKeyCharacterMapFile(int32_t deviceId, String8& outKeyCharacterMapFil return NAME_NOT_FOUND; } -static int lookupLabel(const char* literal, const KeycodeLabel *list) { +static int lookupValueByLabel(const char* literal, const KeycodeLabel *list) { while (list->literal) { if (strcmp(literal, list->literal) == 0) { return list->value; @@ -227,12 +227,30 @@ static int lookupLabel(const char* literal, const KeycodeLabel *list) { return list->value; } +static const char* lookupLabelByValue(int value, const KeycodeLabel *list) { + while (list->literal) { + if (list->value == value) { + return list->literal; + } + list++; + } + return NULL; +} + int32_t getKeyCodeByLabel(const char* label) { - return int32_t(lookupLabel(label, KEYCODES)); + return int32_t(lookupValueByLabel(label, KEYCODES)); } uint32_t getKeyFlagByLabel(const char* label) { - return uint32_t(lookupLabel(label, FLAGS)); + return uint32_t(lookupValueByLabel(label, FLAGS)); +} + +int32_t getAxisByLabel(const char* label) { + return int32_t(lookupValueByLabel(label, AXES)); +} + +const char* getAxisLabel(int32_t axisId) { + return lookupLabelByValue(axisId, AXES); } static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) { diff --git a/libs/ui/tests/InputEvent_test.cpp b/libs/ui/tests/InputEvent_test.cpp index 7b15c38..b77489e 100644 --- a/libs/ui/tests/InputEvent_test.cpp +++ b/libs/ui/tests/InputEvent_test.cpp @@ -18,6 +18,9 @@ #include <gtest/gtest.h> #include <binder/Parcel.h> +#include <math.h> +#include <SkMatrix.h> + namespace android { class BaseTest : public testing::Test { @@ -35,7 +38,7 @@ TEST_F(PointerCoordsTest, ClearSetsBitsToZero) { PointerCoords coords; coords.clear(); - ASSERT_EQ(0U, coords.bits); + ASSERT_EQ(0ULL, coords.bits); } TEST_F(PointerCoordsTest, AxisValues) { @@ -54,7 +57,7 @@ TEST_F(PointerCoordsTest, AxisValues) { // Set first axis. ASSERT_EQ(OK, coords.setAxisValue(1, 5)); - ASSERT_EQ(0x00000002U, coords.bits); + ASSERT_EQ(0x00000002ULL, coords.bits); ASSERT_EQ(5, coords.values[0]); ASSERT_EQ(0, coords.getAxisValue(0)) @@ -64,7 +67,7 @@ TEST_F(PointerCoordsTest, AxisValues) { // Set an axis with a higher id than all others. (appending value at the end) ASSERT_EQ(OK, coords.setAxisValue(3, 2)); - ASSERT_EQ(0x0000000aU, coords.bits); + ASSERT_EQ(0x0000000aULL, coords.bits); ASSERT_EQ(5, coords.values[0]); ASSERT_EQ(2, coords.values[1]); @@ -79,7 +82,7 @@ TEST_F(PointerCoordsTest, AxisValues) { // Set an axis with an id lower than all others. (prepending value at beginning) ASSERT_EQ(OK, coords.setAxisValue(0, 4)); - ASSERT_EQ(0x0000000bU, coords.bits); + ASSERT_EQ(0x0000000bULL, coords.bits); ASSERT_EQ(4, coords.values[0]); ASSERT_EQ(5, coords.values[1]); ASSERT_EQ(2, coords.values[2]); @@ -104,7 +107,7 @@ TEST_F(PointerCoordsTest, AxisValues) { // Set an axis with an id between the others. (inserting value in the middle) ASSERT_EQ(OK, coords.setAxisValue(2, 1)); - ASSERT_EQ(0x0000000fU, coords.bits); + ASSERT_EQ(0x0000000fULL, coords.bits); ASSERT_EQ(4, coords.values[0]); ASSERT_EQ(7, coords.values[1]); ASSERT_EQ(1, coords.values[2]); @@ -121,7 +124,7 @@ TEST_F(PointerCoordsTest, AxisValues) { // Set an existing axis value in place. ASSERT_EQ(OK, coords.setAxisValue(1, 6)); - ASSERT_EQ(0x0000000fU, coords.bits); + ASSERT_EQ(0x0000000fULL, coords.bits); ASSERT_EQ(4, coords.values[0]); ASSERT_EQ(6, coords.values[1]); ASSERT_EQ(1, coords.values[2]); @@ -140,15 +143,15 @@ TEST_F(PointerCoordsTest, AxisValues) { for (size_t axis = 4; axis < PointerCoords::MAX_AXES; axis++) { ASSERT_EQ(OK, coords.setAxisValue(axis, axis)); } - ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcount(coords.bits)); + ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcountll(coords.bits)); // Try to set one more axis beyond maximum number. // Ensure bits are unchanged. ASSERT_EQ(NO_MEMORY, coords.setAxisValue(PointerCoords::MAX_AXES, 100)); - ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcount(coords.bits)); + ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcountll(coords.bits)); } -TEST_F(PointerCoordsTest, ReadAndWriteParcel) { +TEST_F(PointerCoordsTest, Parcel) { Parcel parcel; PointerCoords inCoords; @@ -160,7 +163,7 @@ TEST_F(PointerCoordsTest, ReadAndWriteParcel) { parcel.setDataPosition(0); outCoords.readFromParcel(&parcel); - ASSERT_EQ(0U, outCoords.bits); + ASSERT_EQ(0ULL, outCoords.bits); // Round trip with some values. parcel.freeData(); @@ -213,16 +216,22 @@ TEST_F(KeyEventTest, Properties) { // --- MotionEventTest --- class MotionEventTest : public BaseTest { +protected: + static const nsecs_t ARBITRARY_DOWN_TIME; + static const nsecs_t ARBITRARY_EVENT_TIME; + static const float X_OFFSET; + static const float Y_OFFSET; + + void initializeEventWithHistory(MotionEvent* event); + void assertEqualsEventWithHistory(const MotionEvent* event); }; -TEST_F(MotionEventTest, Properties) { - MotionEvent event; +const nsecs_t MotionEventTest::ARBITRARY_DOWN_TIME = 1; +const nsecs_t MotionEventTest::ARBITRARY_EVENT_TIME = 2; +const float MotionEventTest::X_OFFSET = 1.0f; +const float MotionEventTest::Y_OFFSET = 1.1f; - // Initialize, add samples and get properties. - const nsecs_t ARBITRARY_DOWN_TIME = 1; - const nsecs_t ARBITRARY_EVENT_TIME = 2; - const float X_OFFSET = 1.0f; - const float Y_OFFSET = 1.1f; +void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { int32_t pointerIds[] = { 1, 2 }; PointerCoords pointerCoords[2]; pointerCoords[0].clear(); @@ -245,7 +254,7 @@ TEST_F(MotionEventTest, Properties) { pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28); - event.initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE, + event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, X_OFFSET, Y_OFFSET, 2.0f, 2.1f, @@ -270,7 +279,7 @@ TEST_F(MotionEventTest, Properties) { pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 126); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 127); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 128); - event.addSample(ARBITRARY_EVENT_TIME + 1, pointerCoords); + event->addSample(ARBITRARY_EVENT_TIME + 1, pointerCoords); pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 210); pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 211); @@ -290,128 +299,284 @@ TEST_F(MotionEventTest, Properties) { pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 226); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 227); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 228); - event.addSample(ARBITRARY_EVENT_TIME + 2, pointerCoords); - - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event.getType()); - ASSERT_EQ(2, event.getDeviceId()); - ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event.getSource()); - ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event.getAction()); - ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event.getFlags()); - ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event.getEdgeFlags()); - ASSERT_EQ(AMETA_ALT_ON, event.getMetaState()); - ASSERT_EQ(X_OFFSET, event.getXOffset()); - ASSERT_EQ(Y_OFFSET, event.getYOffset()); - ASSERT_EQ(2.0f, event.getXPrecision()); - ASSERT_EQ(2.1f, event.getYPrecision()); - ASSERT_EQ(ARBITRARY_DOWN_TIME, event.getDownTime()); - - ASSERT_EQ(2U, event.getPointerCount()); - ASSERT_EQ(1, event.getPointerId(0)); - ASSERT_EQ(2, event.getPointerId(1)); - - ASSERT_EQ(2U, event.getHistorySize()); - - // Get data. - ASSERT_EQ(ARBITRARY_EVENT_TIME, event.getHistoricalEventTime(0)); - ASSERT_EQ(ARBITRARY_EVENT_TIME + 1, event.getHistoricalEventTime(1)); - ASSERT_EQ(ARBITRARY_EVENT_TIME + 2, event.getEventTime()); + event->addSample(ARBITRARY_EVENT_TIME + 2, pointerCoords); +} - ASSERT_EQ(11, event.getHistoricalRawPointerCoords(0, 0)-> +void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { + // Check properties. + ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()); + ASSERT_EQ(2, event->getDeviceId()); + ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource()); + ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction()); + ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags()); + ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags()); + ASSERT_EQ(AMETA_ALT_ON, event->getMetaState()); + ASSERT_EQ(X_OFFSET, event->getXOffset()); + ASSERT_EQ(Y_OFFSET, event->getYOffset()); + ASSERT_EQ(2.0f, event->getXPrecision()); + ASSERT_EQ(2.1f, event->getYPrecision()); + ASSERT_EQ(ARBITRARY_DOWN_TIME, event->getDownTime()); + + ASSERT_EQ(2U, event->getPointerCount()); + ASSERT_EQ(1, event->getPointerId(0)); + ASSERT_EQ(2, event->getPointerId(1)); + + ASSERT_EQ(2U, event->getHistorySize()); + + // Check data. + ASSERT_EQ(ARBITRARY_EVENT_TIME, event->getHistoricalEventTime(0)); + ASSERT_EQ(ARBITRARY_EVENT_TIME + 1, event->getHistoricalEventTime(1)); + ASSERT_EQ(ARBITRARY_EVENT_TIME + 2, event->getEventTime()); + + ASSERT_EQ(11, event->getHistoricalRawPointerCoords(0, 0)-> getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(21, event.getHistoricalRawPointerCoords(1, 0)-> + ASSERT_EQ(21, event->getHistoricalRawPointerCoords(1, 0)-> getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(111, event.getHistoricalRawPointerCoords(0, 1)-> + ASSERT_EQ(111, event->getHistoricalRawPointerCoords(0, 1)-> getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(121, event.getHistoricalRawPointerCoords(1, 1)-> + ASSERT_EQ(121, event->getHistoricalRawPointerCoords(1, 1)-> getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(211, event.getRawPointerCoords(0)-> + ASSERT_EQ(211, event->getRawPointerCoords(0)-> getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(221, event.getRawPointerCoords(1)-> + ASSERT_EQ(221, event->getRawPointerCoords(1)-> getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(11, event.getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0)); - ASSERT_EQ(21, event.getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0)); - ASSERT_EQ(111, event.getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1)); - ASSERT_EQ(121, event.getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1)); - ASSERT_EQ(211, event.getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0)); - ASSERT_EQ(221, event.getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1)); - - ASSERT_EQ(10, event.getHistoricalRawX(0, 0)); - ASSERT_EQ(20, event.getHistoricalRawX(1, 0)); - ASSERT_EQ(110, event.getHistoricalRawX(0, 1)); - ASSERT_EQ(120, event.getHistoricalRawX(1, 1)); - ASSERT_EQ(210, event.getRawX(0)); - ASSERT_EQ(220, event.getRawX(1)); - - ASSERT_EQ(11, event.getHistoricalRawY(0, 0)); - ASSERT_EQ(21, event.getHistoricalRawY(1, 0)); - ASSERT_EQ(111, event.getHistoricalRawY(0, 1)); - ASSERT_EQ(121, event.getHistoricalRawY(1, 1)); - ASSERT_EQ(211, event.getRawY(0)); - ASSERT_EQ(221, event.getRawY(1)); - - ASSERT_EQ(X_OFFSET + 10, event.getHistoricalX(0, 0)); - ASSERT_EQ(X_OFFSET + 20, event.getHistoricalX(1, 0)); - ASSERT_EQ(X_OFFSET + 110, event.getHistoricalX(0, 1)); - ASSERT_EQ(X_OFFSET + 120, event.getHistoricalX(1, 1)); - ASSERT_EQ(X_OFFSET + 210, event.getX(0)); - ASSERT_EQ(X_OFFSET + 220, event.getX(1)); - - ASSERT_EQ(Y_OFFSET + 11, event.getHistoricalY(0, 0)); - ASSERT_EQ(Y_OFFSET + 21, event.getHistoricalY(1, 0)); - ASSERT_EQ(Y_OFFSET + 111, event.getHistoricalY(0, 1)); - ASSERT_EQ(Y_OFFSET + 121, event.getHistoricalY(1, 1)); - ASSERT_EQ(Y_OFFSET + 211, event.getY(0)); - ASSERT_EQ(Y_OFFSET + 221, event.getY(1)); - - ASSERT_EQ(12, event.getHistoricalPressure(0, 0)); - ASSERT_EQ(22, event.getHistoricalPressure(1, 0)); - ASSERT_EQ(112, event.getHistoricalPressure(0, 1)); - ASSERT_EQ(122, event.getHistoricalPressure(1, 1)); - ASSERT_EQ(212, event.getPressure(0)); - ASSERT_EQ(222, event.getPressure(1)); + ASSERT_EQ(11, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0)); + ASSERT_EQ(21, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0)); + ASSERT_EQ(111, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1)); + ASSERT_EQ(121, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1)); + ASSERT_EQ(211, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0)); + ASSERT_EQ(221, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1)); + + ASSERT_EQ(10, event->getHistoricalRawX(0, 0)); + ASSERT_EQ(20, event->getHistoricalRawX(1, 0)); + ASSERT_EQ(110, event->getHistoricalRawX(0, 1)); + ASSERT_EQ(120, event->getHistoricalRawX(1, 1)); + ASSERT_EQ(210, event->getRawX(0)); + ASSERT_EQ(220, event->getRawX(1)); + + ASSERT_EQ(11, event->getHistoricalRawY(0, 0)); + ASSERT_EQ(21, event->getHistoricalRawY(1, 0)); + ASSERT_EQ(111, event->getHistoricalRawY(0, 1)); + ASSERT_EQ(121, event->getHistoricalRawY(1, 1)); + ASSERT_EQ(211, event->getRawY(0)); + ASSERT_EQ(221, event->getRawY(1)); + + ASSERT_EQ(X_OFFSET + 10, event->getHistoricalX(0, 0)); + ASSERT_EQ(X_OFFSET + 20, event->getHistoricalX(1, 0)); + ASSERT_EQ(X_OFFSET + 110, event->getHistoricalX(0, 1)); + ASSERT_EQ(X_OFFSET + 120, event->getHistoricalX(1, 1)); + ASSERT_EQ(X_OFFSET + 210, event->getX(0)); + ASSERT_EQ(X_OFFSET + 220, event->getX(1)); + + ASSERT_EQ(Y_OFFSET + 11, event->getHistoricalY(0, 0)); + ASSERT_EQ(Y_OFFSET + 21, event->getHistoricalY(1, 0)); + ASSERT_EQ(Y_OFFSET + 111, event->getHistoricalY(0, 1)); + ASSERT_EQ(Y_OFFSET + 121, event->getHistoricalY(1, 1)); + ASSERT_EQ(Y_OFFSET + 211, event->getY(0)); + ASSERT_EQ(Y_OFFSET + 221, event->getY(1)); + + ASSERT_EQ(12, event->getHistoricalPressure(0, 0)); + ASSERT_EQ(22, event->getHistoricalPressure(1, 0)); + ASSERT_EQ(112, event->getHistoricalPressure(0, 1)); + ASSERT_EQ(122, event->getHistoricalPressure(1, 1)); + ASSERT_EQ(212, event->getPressure(0)); + ASSERT_EQ(222, event->getPressure(1)); + + ASSERT_EQ(13, event->getHistoricalSize(0, 0)); + ASSERT_EQ(23, event->getHistoricalSize(1, 0)); + ASSERT_EQ(113, event->getHistoricalSize(0, 1)); + ASSERT_EQ(123, event->getHistoricalSize(1, 1)); + ASSERT_EQ(213, event->getSize(0)); + ASSERT_EQ(223, event->getSize(1)); + + ASSERT_EQ(14, event->getHistoricalTouchMajor(0, 0)); + ASSERT_EQ(24, event->getHistoricalTouchMajor(1, 0)); + ASSERT_EQ(114, event->getHistoricalTouchMajor(0, 1)); + ASSERT_EQ(124, event->getHistoricalTouchMajor(1, 1)); + ASSERT_EQ(214, event->getTouchMajor(0)); + ASSERT_EQ(224, event->getTouchMajor(1)); + + ASSERT_EQ(15, event->getHistoricalTouchMinor(0, 0)); + ASSERT_EQ(25, event->getHistoricalTouchMinor(1, 0)); + ASSERT_EQ(115, event->getHistoricalTouchMinor(0, 1)); + ASSERT_EQ(125, event->getHistoricalTouchMinor(1, 1)); + ASSERT_EQ(215, event->getTouchMinor(0)); + ASSERT_EQ(225, event->getTouchMinor(1)); + + ASSERT_EQ(16, event->getHistoricalToolMajor(0, 0)); + ASSERT_EQ(26, event->getHistoricalToolMajor(1, 0)); + ASSERT_EQ(116, event->getHistoricalToolMajor(0, 1)); + ASSERT_EQ(126, event->getHistoricalToolMajor(1, 1)); + ASSERT_EQ(216, event->getToolMajor(0)); + ASSERT_EQ(226, event->getToolMajor(1)); + + ASSERT_EQ(17, event->getHistoricalToolMinor(0, 0)); + ASSERT_EQ(27, event->getHistoricalToolMinor(1, 0)); + ASSERT_EQ(117, event->getHistoricalToolMinor(0, 1)); + ASSERT_EQ(127, event->getHistoricalToolMinor(1, 1)); + ASSERT_EQ(217, event->getToolMinor(0)); + ASSERT_EQ(227, event->getToolMinor(1)); + + ASSERT_EQ(18, event->getHistoricalOrientation(0, 0)); + ASSERT_EQ(28, event->getHistoricalOrientation(1, 0)); + ASSERT_EQ(118, event->getHistoricalOrientation(0, 1)); + ASSERT_EQ(128, event->getHistoricalOrientation(1, 1)); + ASSERT_EQ(218, event->getOrientation(0)); + ASSERT_EQ(228, event->getOrientation(1)); +} + +TEST_F(MotionEventTest, Properties) { + MotionEvent event; + + // Initialize, add samples and check properties. + initializeEventWithHistory(&event); + ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&event)); + + // Set source. + event.setSource(AINPUT_SOURCE_JOYSTICK); + ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource()); + + // Set action. + event.setAction(AMOTION_EVENT_ACTION_CANCEL); + ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction()); + + // Set meta state. + event.setMetaState(AMETA_CTRL_ON); + ASSERT_EQ(AMETA_CTRL_ON, event.getMetaState()); +} + +TEST_F(MotionEventTest, CopyFrom_KeepHistory) { + MotionEvent event; + initializeEventWithHistory(&event); + + MotionEvent copy; + copy.copyFrom(&event, true /*keepHistory*/); + + ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&event)); +} + +TEST_F(MotionEventTest, CopyFrom_DoNotKeepHistory) { + MotionEvent event; + initializeEventWithHistory(&event); + + MotionEvent copy; + copy.copyFrom(&event, false /*keepHistory*/); + + ASSERT_EQ(event.getPointerCount(), copy.getPointerCount()); + ASSERT_EQ(0U, copy.getHistorySize()); + + ASSERT_EQ(event.getPointerId(0), copy.getPointerId(0)); + ASSERT_EQ(event.getPointerId(1), copy.getPointerId(1)); + + ASSERT_EQ(event.getEventTime(), copy.getEventTime()); + + ASSERT_EQ(event.getX(0), copy.getX(0)); +} + +TEST_F(MotionEventTest, OffsetLocation) { + MotionEvent event; + initializeEventWithHistory(&event); + + event.offsetLocation(5.0f, -2.0f); + + ASSERT_EQ(X_OFFSET + 5.0f, event.getXOffset()); + ASSERT_EQ(Y_OFFSET - 2.0f, event.getYOffset()); +} + +TEST_F(MotionEventTest, Scale) { + MotionEvent event; + initializeEventWithHistory(&event); - ASSERT_EQ(13, event.getHistoricalSize(0, 0)); - ASSERT_EQ(23, event.getHistoricalSize(1, 0)); - ASSERT_EQ(113, event.getHistoricalSize(0, 1)); - ASSERT_EQ(123, event.getHistoricalSize(1, 1)); + event.scale(2.0f); + + ASSERT_EQ(X_OFFSET * 2, event.getXOffset()); + ASSERT_EQ(Y_OFFSET * 2, event.getYOffset()); + + ASSERT_EQ(210 * 2, event.getRawX(0)); + ASSERT_EQ(211 * 2, event.getRawY(0)); + ASSERT_EQ((X_OFFSET + 210) * 2, event.getX(0)); + ASSERT_EQ((Y_OFFSET + 211) * 2, event.getY(0)); + ASSERT_EQ(212, event.getPressure(0)); ASSERT_EQ(213, event.getSize(0)); - ASSERT_EQ(223, event.getSize(1)); - - ASSERT_EQ(14, event.getHistoricalTouchMajor(0, 0)); - ASSERT_EQ(24, event.getHistoricalTouchMajor(1, 0)); - ASSERT_EQ(114, event.getHistoricalTouchMajor(0, 1)); - ASSERT_EQ(124, event.getHistoricalTouchMajor(1, 1)); - ASSERT_EQ(214, event.getTouchMajor(0)); - ASSERT_EQ(224, event.getTouchMajor(1)); - - ASSERT_EQ(15, event.getHistoricalTouchMinor(0, 0)); - ASSERT_EQ(25, event.getHistoricalTouchMinor(1, 0)); - ASSERT_EQ(115, event.getHistoricalTouchMinor(0, 1)); - ASSERT_EQ(125, event.getHistoricalTouchMinor(1, 1)); - ASSERT_EQ(215, event.getTouchMinor(0)); - ASSERT_EQ(225, event.getTouchMinor(1)); - - ASSERT_EQ(16, event.getHistoricalToolMajor(0, 0)); - ASSERT_EQ(26, event.getHistoricalToolMajor(1, 0)); - ASSERT_EQ(116, event.getHistoricalToolMajor(0, 1)); - ASSERT_EQ(126, event.getHistoricalToolMajor(1, 1)); - ASSERT_EQ(216, event.getToolMajor(0)); - ASSERT_EQ(226, event.getToolMajor(1)); - - ASSERT_EQ(17, event.getHistoricalToolMinor(0, 0)); - ASSERT_EQ(27, event.getHistoricalToolMinor(1, 0)); - ASSERT_EQ(117, event.getHistoricalToolMinor(0, 1)); - ASSERT_EQ(127, event.getHistoricalToolMinor(1, 1)); - ASSERT_EQ(217, event.getToolMinor(0)); - ASSERT_EQ(227, event.getToolMinor(1)); - - ASSERT_EQ(18, event.getHistoricalOrientation(0, 0)); - ASSERT_EQ(28, event.getHistoricalOrientation(1, 0)); - ASSERT_EQ(118, event.getHistoricalOrientation(0, 1)); - ASSERT_EQ(128, event.getHistoricalOrientation(1, 1)); + ASSERT_EQ(214 * 2, event.getTouchMajor(0)); + ASSERT_EQ(215 * 2, event.getTouchMinor(0)); + ASSERT_EQ(216 * 2, event.getToolMajor(0)); + ASSERT_EQ(217 * 2, event.getToolMinor(0)); ASSERT_EQ(218, event.getOrientation(0)); - ASSERT_EQ(228, event.getOrientation(1)); +} + +TEST_F(MotionEventTest, Parcel) { + Parcel parcel; + + MotionEvent inEvent; + initializeEventWithHistory(&inEvent); + MotionEvent outEvent; + + // Round trip. + inEvent.writeToParcel(&parcel); + parcel.setDataPosition(0); + outEvent.readFromParcel(&parcel); + + ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent)); +} + +TEST_F(MotionEventTest, Transform) { + // Generate some points on a circle. + // Each point 'i' is a point on a circle of radius ROTATION centered at (3,2) at an angle + // of ARC * i degrees clockwise relative to the Y axis. + // The geometrical representation is irrelevant to the test, it's just easy to generate + // and check rotation. We set the orientation to the same angle. + // Coordinate system: down is increasing Y, right is increasing X. + const float PI_180 = float(M_PI / 180); + const float RADIUS = 10; + const float ARC = 36; + const float ROTATION = ARC * 2; + + const size_t pointerCount = 11; + int pointerIds[pointerCount]; + PointerCoords pointerCoords[pointerCount]; + for (size_t i = 0; i < pointerCount; i++) { + float angle = float(i * ARC * PI_180); + pointerIds[i] = i; + pointerCoords[i].clear(); + pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, sinf(angle) * RADIUS + 3); + pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, -cosf(angle) * RADIUS + 2); + pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle); + } + MotionEvent event; + event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, + 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords); + float originalRawX = 0 + 3; + float originalRawY = -RADIUS + 2; + + // Check original raw X and Y assumption. + ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001); + ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001); + + // Now translate the motion event so the circle's origin is at (0,0). + event.offsetLocation(-3, -2); + + // Offsetting the location should preserve the raw X and Y of the first point. + ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001); + ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001); + + // Apply a rotation about the origin by ROTATION degrees clockwise. + SkMatrix matrix; + matrix.setRotate(ROTATION); + event.transform(&matrix); + + // Check the points. + for (size_t i = 0; i < pointerCount; i++) { + float angle = float((i * ARC + ROTATION) * PI_180); + ASSERT_NEAR(sinf(angle) * RADIUS, event.getX(i), 0.001); + ASSERT_NEAR(-cosf(angle) * RADIUS, event.getY(i), 0.001); + ASSERT_NEAR(tanf(angle), tanf(event.getOrientation(i)), 0.1); + } + + // Applying the transformation should preserve the raw X and Y of the first point. + ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001); + ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001); } } // namespace android |