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

Commit cc2959be authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Move MotionEvent#split implementation to native

There is already a native implementation of split in InputDispatcher.
Prevent code duplication by moving the Java impl to native. The Java
impl is not correct, because it cannot access all values like the
transforms to initialize the split event with.

Bug: 326171104
Test: atest libinput_tests
Change-Id: I4be8799724e07a322099d2fb16901fa748656cec
parent 611aa05b
Loading
Loading
Loading
Loading
+14 −75
Original line number Diff line number Diff line
@@ -1733,6 +1733,8 @@ public final class MotionEvent extends InputEvent implements Parcelable {
    private static native long nativeCopy(long destNativePtr, long sourceNativePtr,
            boolean keepHistory);
    @CriticalNative
    private static native long nativeSplit(long destNativePtr, long sourceNativePtr, int idBits);
    @CriticalNative
    private static native int nativeGetId(long nativePtr);
    @CriticalNative
    private static native int nativeGetDeviceId(long nativePtr);
@@ -3767,86 +3769,23 @@ public final class MotionEvent extends InputEvent implements Parcelable {
    }

    /**
     * Splits a motion event such that it includes only a subset of pointer ids.
     * Splits a motion event such that it includes only a subset of pointer IDs.
     * @param idBits the bitset indicating all of the pointer IDs from this motion event that should
     *               be in the new split event. idBits must be a non-empty subset of the pointer IDs
     *               contained in this event.
     * @hide
     */
    // TODO(b/327503168): Pass downTime as a parameter to split.
    @UnsupportedAppUsage
    @NonNull
    public final MotionEvent split(int idBits) {
        MotionEvent ev = obtain();
        synchronized (gSharedTempLock) {
            final int oldPointerCount = nativeGetPointerCount(mNativePtr);
            ensureSharedTempPointerCapacity(oldPointerCount);
            final PointerProperties[] pp = gSharedTempPointerProperties;
            final PointerCoords[] pc = gSharedTempPointerCoords;
            final int[] map = gSharedTempPointerIndexMap;

            final int oldAction = nativeGetAction(mNativePtr);
            final int oldActionMasked = oldAction & ACTION_MASK;
            final int oldActionPointerIndex = (oldAction & ACTION_POINTER_INDEX_MASK)
                    >> ACTION_POINTER_INDEX_SHIFT;
            int newActionPointerIndex = -1;
            int newPointerCount = 0;
            for (int i = 0; i < oldPointerCount; i++) {
                nativeGetPointerProperties(mNativePtr, i, pp[newPointerCount]);
                final int idBit = 1 << pp[newPointerCount].id;
                if ((idBit & idBits) != 0) {
                    if (i == oldActionPointerIndex) {
                        newActionPointerIndex = newPointerCount;
                    }
                    map[newPointerCount] = i;
                    newPointerCount += 1;
                }
            }

            if (newPointerCount == 0) {
                throw new IllegalArgumentException("idBits did not match any ids in the event");
            }

            final int newAction;
            if (oldActionMasked == ACTION_POINTER_DOWN || oldActionMasked == ACTION_POINTER_UP) {
                if (newActionPointerIndex < 0) {
                    // An unrelated pointer changed.
                    newAction = ACTION_MOVE;
                } else if (newPointerCount == 1) {
                    // The first/last pointer went down/up.
                    newAction = oldActionMasked == ACTION_POINTER_DOWN
                            ? ACTION_DOWN
                            : (getFlags() & FLAG_CANCELED) == 0 ? ACTION_UP : ACTION_CANCEL;
                } else {
                    // A secondary pointer went down/up.
                    newAction = oldActionMasked
                            | (newActionPointerIndex << ACTION_POINTER_INDEX_SHIFT);
                }
            } else {
                // Simple up/down/cancel/move or other motion action.
                newAction = oldAction;
            }

            final int historySize = nativeGetHistorySize(mNativePtr);
            for (int h = 0; h <= historySize; h++) {
                final int historyPos = h == historySize ? HISTORY_CURRENT : h;

                for (int i = 0; i < newPointerCount; i++) {
                    nativeGetPointerCoords(mNativePtr, map[i], historyPos, pc[i]);
                }

                final long eventTimeNanos = nativeGetEventTimeNanos(mNativePtr, historyPos);
                if (h == 0) {
                    ev.initialize(nativeGetDeviceId(mNativePtr), nativeGetSource(mNativePtr),
                            nativeGetDisplayId(mNativePtr),
                            newAction, nativeGetFlags(mNativePtr),
                            nativeGetEdgeFlags(mNativePtr), nativeGetMetaState(mNativePtr),
                            nativeGetButtonState(mNativePtr), nativeGetClassification(mNativePtr),
                            nativeGetXOffset(mNativePtr), nativeGetYOffset(mNativePtr),
                            nativeGetXPrecision(mNativePtr), nativeGetYPrecision(mNativePtr),
                            nativeGetDownTimeNanos(mNativePtr), eventTimeNanos,
                            newPointerCount, pp, pc);
                } else {
                    nativeAddBatch(ev.mNativePtr, eventTimeNanos, pc, 0);
                }
            }
            return ev;
        if (idBits == 0) {
            throw new IllegalArgumentException(
                    "idBits must contain at least one pointer from this motion event");
        }
        MotionEvent event = obtain();
        event.mNativePtr = nativeSplit(event.mNativePtr, this.mNativePtr, idBits);
        return event;
    }

    /**
+13 −0
Original line number Diff line number Diff line
@@ -607,6 +607,18 @@ static jlong android_view_MotionEvent_nativeCopy(jlong destNativePtr, jlong sour
    return reinterpret_cast<jlong>(destEvent);
}

static jlong android_view_MotionEvent_nativeSplit(jlong destNativePtr, jlong sourceNativePtr,
                                                  jint idBits) {
    MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
    if (!destEvent) {
        destEvent = new MotionEvent();
    }
    MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr);
    destEvent->splitFrom(*sourceEvent, static_cast<std::bitset<MAX_POINTER_ID + 1>>(idBits),
                         InputEvent::nextId());
    return reinterpret_cast<jlong>(destEvent);
}

static jint android_view_MotionEvent_nativeGetId(jlong nativePtr) {
    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
    return event->getId();
@@ -822,6 +834,7 @@ static const JNINativeMethod gMotionEventMethods[] = {
        // --------------- @CriticalNative ------------------

        {"nativeCopy", "(JJZ)J", (void*)android_view_MotionEvent_nativeCopy},
        {"nativeSplit", "(JJI)J", (void*)android_view_MotionEvent_nativeSplit},
        {"nativeGetId", "(J)I", (void*)android_view_MotionEvent_nativeGetId},
        {"nativeGetDeviceId", "(J)I", (void*)android_view_MotionEvent_nativeGetDeviceId},
        {"nativeGetSource", "(J)I", (void*)android_view_MotionEvent_nativeGetSource},