From 9dabf6bac519bde9432575195859810dadd9f74e Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Fri, 24 Sep 2021 07:50:01 -0700 Subject: [PATCH] Populate PointerCoords values using values from MotionEvent Some values in MotionEvent, such as AXIS_X and AXIS_Y, will be transformed into a different coordinate space. This means the value will differ from the one stored in the native PointerCoords. When populating the java PointerCoords object, we need to make sure to use the transformed values from MotionEvent instead of the raw values stored in the native PointerCoords. Bug: 179274888 Test: atest MotionEventTest (CTS) Change-Id: Iffa459fdeba1ef23fe3bf7e36e897d120d9c457c --- core/jni/android_view_MotionEvent.cpp | 90 +++++++++++---------------- 1 file changed, 37 insertions(+), 53 deletions(-) diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp index efd0547c559ba..292f30510aa0f 100644 --- a/core/jni/android_view_MotionEvent.cpp +++ b/core/jni/android_view_MotionEvent.cpp @@ -265,49 +265,9 @@ static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize, } static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords, - ui::Transform transform, jobject outPointerCoordsObj) { - float rawX = rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X); - float rawY = rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y); - vec2 transformed = transform.transform(rawX, rawY); - - float rawRelX = rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X); - float rawRelY = rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y); - // Apply only rotation and scale, not translation. - const vec2 transformedOrigin = transform.transform(0, 0); - const vec2 transformedRel = transform.transform(rawRelX, rawRelY) - transformedOrigin; - - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x, transformed.x); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y, transformed.y); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure, - rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size, - rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_SIZE)); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMajor, - rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR)); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMinor, - rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR)); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMajor, - rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR)); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMinor, - rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR)); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation, - rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.relativeX, transformedRel.x); - env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.relativeY, transformedRel.y); - + const BitSet64& axesBitsToCopy, jobject outPointerCoordsObj) { + BitSet64 bits = axesBitsToCopy; uint64_t outBits = 0; - BitSet64 bits = BitSet64(rawPointerCoords->bits); - bits.clearBit(AMOTION_EVENT_AXIS_X); - bits.clearBit(AMOTION_EVENT_AXIS_Y); - bits.clearBit(AMOTION_EVENT_AXIS_PRESSURE); - bits.clearBit(AMOTION_EVENT_AXIS_SIZE); - bits.clearBit(AMOTION_EVENT_AXIS_TOUCH_MAJOR); - bits.clearBit(AMOTION_EVENT_AXIS_TOUCH_MINOR); - bits.clearBit(AMOTION_EVENT_AXIS_TOOL_MAJOR); - bits.clearBit(AMOTION_EVENT_AXIS_TOOL_MINOR); - bits.clearBit(AMOTION_EVENT_AXIS_ORIENTATION); - bits.clearBit(AMOTION_EVENT_AXIS_RELATIVE_X); - bits.clearBit(AMOTION_EVENT_AXIS_RELATIVE_Y); if (!bits.isEmpty()) { uint32_t packedAxesCount = bits.count(); jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount, @@ -444,18 +404,42 @@ static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass || !validatePointerCoords(env, outPointerCoordsObj)) { return; } - - const PointerCoords* rawPointerCoords; - if (historyPos == HISTORY_CURRENT) { - rawPointerCoords = event->getRawPointerCoords(pointerIndex); - } else { - size_t historySize = event->getHistorySize(); - if (!validateHistoryPos(env, historyPos, historySize)) { - return; - } - rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos); + if (historyPos != HISTORY_CURRENT && + !validateHistoryPos(env, historyPos, event->getHistorySize())) { + return; } - pointerCoordsFromNative(env, rawPointerCoords, event->getTransform(), outPointerCoordsObj); + + // Obtain the following axis values directly from the MotionEvent instead of from the raw + // PointerCoords. + const static std::array, 11> kAxesFromMotionEvent = {{ + {AMOTION_EVENT_AXIS_X, gPointerCoordsClassInfo.x}, + {AMOTION_EVENT_AXIS_Y, gPointerCoordsClassInfo.y}, + {AMOTION_EVENT_AXIS_PRESSURE, gPointerCoordsClassInfo.pressure}, + {AMOTION_EVENT_AXIS_SIZE, gPointerCoordsClassInfo.size}, + {AMOTION_EVENT_AXIS_TOUCH_MAJOR, gPointerCoordsClassInfo.touchMajor}, + {AMOTION_EVENT_AXIS_TOUCH_MINOR, gPointerCoordsClassInfo.touchMinor}, + {AMOTION_EVENT_AXIS_TOOL_MAJOR, gPointerCoordsClassInfo.toolMajor}, + {AMOTION_EVENT_AXIS_TOOL_MINOR, gPointerCoordsClassInfo.toolMinor}, + {AMOTION_EVENT_AXIS_ORIENTATION, gPointerCoordsClassInfo.orientation}, + {AMOTION_EVENT_AXIS_RELATIVE_X, gPointerCoordsClassInfo.relativeX}, + {AMOTION_EVENT_AXIS_RELATIVE_Y, gPointerCoordsClassInfo.relativeY}, + }}; + for (const auto& [axis, fieldId] : kAxesFromMotionEvent) { + const float value = historyPos == HISTORY_CURRENT + ? event->getAxisValue(axis, pointerIndex) + : event->getHistoricalAxisValue(axis, pointerIndex, historyPos); + env->SetFloatField(outPointerCoordsObj, fieldId, value); + } + + const PointerCoords* rawPointerCoords = historyPos == HISTORY_CURRENT + ? event->getRawPointerCoords(pointerIndex) + : event->getHistoricalRawPointerCoords(pointerIndex, historyPos); + + BitSet64 bits = BitSet64(rawPointerCoords->bits); + for (const auto [axis, _] : kAxesFromMotionEvent) { + bits.clearBit(axis); + } + pointerCoordsFromNative(env, rawPointerCoords, bits, outPointerCoordsObj); } static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,