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

Commit 6f5ed5b8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Keep track of pilfered pointer explicitly"

parents 3fee9b9b 060f82be
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -2333,14 +2333,22 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
            }
        }

        // If any existing window is pilfering pointers from newly added window, remove it
        BitSet32 canceledPointers = BitSet32(0);
        for (const TouchedWindow& window : tempTouchState.windows) {
            if (window.isPilferingPointers) {
                canceledPointers |= window.pointerIds;
            }
        }
        tempTouchState.cancelPointersForNonPilferingWindows(canceledPointers);
        // If a window is already pilfering some pointers, give it this new pointer as well and
        // make it pilfering. This will prevent other non-spy windows from getting this pointer,
        // which is a specific behaviour that we want.
        const int32_t pointerId = entry.pointerProperties[pointerIndex].id;
        for (TouchedWindow& touchedWindow : tempTouchState.windows) {
            if (touchedWindow.pointerIds.hasBit(pointerId) &&
                touchedWindow.pilferedPointerIds.count() > 0) {
                // This window is already pilfering some pointers, and this new pointer is also
                // going to it. Therefore, take over this pointer and don't give it to anyone
                // else.
                touchedWindow.pilferedPointerIds.set(pointerId);
            }
        }

        // Restrict all pilfered pointers to the pilfering windows.
        tempTouchState.cancelPointersForNonPilferingWindows();
    } else {
        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */

@@ -3942,8 +3950,8 @@ std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent(
    if (action == AMOTION_EVENT_ACTION_DOWN) {
        LOG_ALWAYS_FATAL_IF(splitDownTime != originalMotionEntry.eventTime,
                            "Split motion event has mismatching downTime and eventTime for "
                            "ACTION_DOWN, motionEntry=%s, splitDownTime=%" PRId64 "ms",
                            originalMotionEntry.getDescription().c_str(), ns2ms(splitDownTime));
                            "ACTION_DOWN, motionEntry=%s, splitDownTime=%" PRId64,
                            originalMotionEntry.getDescription().c_str(), splitDownTime);
    }

    int32_t newId = mIdGenerator.nextId();
@@ -5778,7 +5786,10 @@ status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) {

    // Prevent the gesture from being sent to any other windows.
    // This only blocks relevant pointers to be sent to other windows
    window.isPilferingPointers = true;
    for (BitSet32 idBits(window.pointerIds); !idBits.isEmpty();) {
        uint32_t id = idBits.clearFirstMarkedBit();
        window.pilferedPointerIds.set(id);
    }

    state.cancelPointersForWindowsExcept(window.pointerIds, token);
    return OK;
+36 −5
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ void TouchState::reset() {
void TouchState::removeTouchedPointer(int32_t pointerId) {
    for (TouchedWindow& touchedWindow : windows) {
        touchedWindow.pointerIds.clearBit(pointerId);
        touchedWindow.pilferedPointerIds.reset(pointerId);
    }
}

@@ -42,6 +43,7 @@ void TouchState::removeTouchedPointerFromWindow(
    for (TouchedWindow& touchedWindow : windows) {
        if (touchedWindow.windowHandle == windowHandle) {
            touchedWindow.pointerIds.clearBit(pointerId);
            touchedWindow.pilferedPointerIds.reset(pointerId);
            return;
        }
    }
@@ -137,11 +139,40 @@ void TouchState::cancelPointersForWindowsExcept(const BitSet32 pointerIds,
    std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
}

void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) {
    if (pointerIds.isEmpty()) return;
    std::for_each(windows.begin(), windows.end(), [&pointerIds](TouchedWindow& w) {
        if (!w.isPilferingPointers) {
            w.pointerIds &= BitSet32(~pointerIds.value);
/**
 * For any pointer that's being pilfered, remove it from all of the other windows that currently
 * aren't pilfering it. For example, if we determined that pointer 1 is going to both window A and
 * window B, but window A is currently pilfering pointer 1, then pointer 1 should not go to window
 * B.
 */
void TouchState::cancelPointersForNonPilferingWindows() {
    // First, find all pointers that are being pilfered, across all windows
    std::bitset<MAX_POINTERS> allPilferedPointerIds;
    std::for_each(windows.begin(), windows.end(), [&allPilferedPointerIds](const TouchedWindow& w) {
        allPilferedPointerIds |= w.pilferedPointerIds;
    });

    // Optimization: most of the time, pilfering does not occur
    if (allPilferedPointerIds.none()) return;

    // Now, remove all pointers from every window that's being pilfered by other windows.
    // For example, if window A is pilfering pointer 1 (only), and window B is pilfering pointer 2
    // (only), the remove pointer 2 from window A and pointer 1 from window B. Usually, the set of
    // pilfered pointers will be disjoint across all windows, but there's no reason to cause that
    // limitation here.
    std::for_each(windows.begin(), windows.end(), [&allPilferedPointerIds](TouchedWindow& w) {
        std::bitset<MAX_POINTERS> pilferedByOtherWindows =
                w.pilferedPointerIds ^ allPilferedPointerIds;
        // TODO(b/211379801) : convert pointerIds to use std::bitset, which would allow us to
        // replace the loop below with a bitwise operation. Currently, the XOR operation above is
        // redundant, but is done to make the code more explicit / easier to convert later.
        for (std::size_t i = 0; i < pilferedByOtherWindows.size(); i++) {
            if (pilferedByOtherWindows.test(i) && !w.pilferedPointerIds.test(i)) {
                // Pointer is pilfered by other windows, but not by this one! Remove it from here.
                // We could call 'removeTouchedPointerFromWindow' here, but it's faster to directly
                // manipulate it.
                w.pointerIds.clearBit(i);
            }
        }
    });
    std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ struct TouchState {
    void cancelPointersForWindowsExcept(const BitSet32 pointerIds, const sp<IBinder>& token);
    // Cancel pointers for current set of non-pilfering windows i.e. windows with isPilferingWindow
    // set to false.
    void cancelPointersForNonPilferingWindows(const BitSet32 pointerIds);
    void cancelPointersForNonPilferingWindows();

    sp<android::gui::WindowInfoHandle> getFirstForegroundWindowHandle() const;
    bool isSlippery() const;
+2 −2
Original line number Diff line number Diff line
@@ -63,10 +63,10 @@ std::string TouchedWindow::dump() const {
    std::string hoveringPointers =
            dumpMap(mHoveringPointerIdsByDevice, constToString, bitsetToString);
    out += StringPrintf("name='%s', pointerIds=0x%0x, targetFlags=%s, firstDownTimeInTarget=%s, "
                        "mHoveringPointerIdsByDevice=%s\n",
                        "mHoveringPointerIdsByDevice=%s, pilferedPointerIds=%s\n",
                        windowHandle->getName().c_str(), pointerIds.value,
                        targetFlags.string().c_str(), toString(firstDownTimeInTarget).c_str(),
                        hoveringPointers.c_str());
                        hoveringPointers.c_str(), bitsetToString(pilferedPointerIds).c_str());
    return out;
}

+2 −1
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ struct TouchedWindow {
    sp<gui::WindowInfoHandle> windowHandle;
    ftl::Flags<InputTarget::Flags> targetFlags;
    BitSet32 pointerIds;
    bool isPilferingPointers = false;
    // The pointer ids of the pointers that this window is currently pilfering
    std::bitset<MAX_POINTERS> pilferedPointerIds;
    // Time at which the first action down occurred on this window.
    // NOTE: This is not initialized in case of HOVER entry/exit and DISPATCH_AS_OUTSIDE scenario.
    std::optional<nsecs_t> firstDownTimeInTarget;
Loading