Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9dabf6ba authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

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
parent 6bc08fd2
Loading
Loading
Loading
Loading
+36 −52
Original line number Diff line number Diff line
@@ -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)) {
    if (historyPos != HISTORY_CURRENT &&
        !validateHistoryPos(env, historyPos, event->getHistorySize())) {
        return;
    }
        rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);

    // Obtain the following axis values directly from the MotionEvent instead of from the raw
    // PointerCoords.
    const static std::array<std::pair<int32_t /*axis*/, jfieldID>, 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, event->getTransform(), outPointerCoordsObj);
    pointerCoordsFromNative(env, rawPointerCoords, bits, outPointerCoordsObj);
}

static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,