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

Commit 414ea4ce authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Android (Google) Code Review
Browse files

Merge "Send cancel events to the correct display when mirroring" into main

parents a387c08f 16463381
Loading
Loading
Loading
Loading
+27 −30
Original line number Diff line number Diff line
@@ -3958,28 +3958,24 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
    android_log_event_list(LOGTAG_INPUT_CANCEL)
            << connection->getInputChannelName().c_str() << reason << LOG_ID_EVENTS;

    sp<WindowInfoHandle> windowHandle;
    if (options.displayId) {
        windowHandle = getWindowHandleLocked(connection->inputChannel->getConnectionToken(),
                                             options.displayId.value());
    } else {
        windowHandle = getWindowHandleLocked(connection->inputChannel->getConnectionToken());
    }

    const bool wasEmpty = connection->outboundQueue.empty();
    // The target to use if we don't find a window associated with the channel.
    const InputTarget fallbackTarget{.inputChannel = connection->inputChannel,
                                     .flags = InputTarget::Flags::DISPATCH_AS_IS};
    const auto& token = connection->inputChannel->getConnectionToken();

    for (size_t i = 0; i < cancelationEvents.size(); i++) {
        std::unique_ptr<EventEntry> cancelationEventEntry = std::move(cancelationEvents[i]);
        std::vector<InputTarget> targets{};
        // The target to use if we don't find a window associated with the channel.
        const InputTarget fallbackTarget{.inputChannel = connection->inputChannel,
                                         .flags = InputTarget::Flags::DISPATCH_AS_IS};

        switch (cancelationEventEntry->type) {
            case EventEntry::Type::KEY: {
                const auto& keyEntry = static_cast<const KeyEntry&>(*cancelationEventEntry);
                if (windowHandle != nullptr) {
                    addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_IS,
                const std::optional<int32_t> targetDisplay = keyEntry.displayId != ADISPLAY_ID_NONE
                        ? std::make_optional(keyEntry.displayId)
                        : std::nullopt;
                if (const auto& window = getWindowHandleLocked(token, targetDisplay); window) {
                    addWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS,
                                          /*pointerIds=*/{}, keyEntry.downTime, targets);
                } else {
                    targets.emplace_back(fallbackTarget);
@@ -3989,14 +3985,18 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
            }
            case EventEntry::Type::MOTION: {
                const auto& motionEntry = static_cast<const MotionEntry&>(*cancelationEventEntry);
                if (windowHandle != nullptr) {
                const std::optional<int32_t> targetDisplay =
                        motionEntry.displayId != ADISPLAY_ID_NONE
                        ? std::make_optional(motionEntry.displayId)
                        : std::nullopt;
                if (const auto& window = getWindowHandleLocked(token, targetDisplay); window) {
                    std::bitset<MAX_POINTER_ID + 1> pointerIds;
                    for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.pointerCount;
                         pointerIndex++) {
                        pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
                    }
                    addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_IS,
                                          pointerIds, motionEntry.downTime, targets);
                    addWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS, pointerIds,
                                          motionEntry.downTime, targets);
                } else {
                    targets.emplace_back(fallbackTarget);
                    const auto it = mDisplayInfos.find(motionEntry.displayId);
@@ -4905,11 +4905,13 @@ const std::vector<sp<WindowInfoHandle>>& InputDispatcher::getWindowHandlesLocked
}

sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
        const sp<IBinder>& windowHandleToken) const {
        const sp<IBinder>& windowHandleToken, std::optional<int32_t> displayId) const {
    if (windowHandleToken == nullptr) {
        return nullptr;
    }

    if (!displayId) {
        // Look through all displays.
        for (auto& it : mWindowHandlesByDisplay) {
            const std::vector<sp<WindowInfoHandle>>& windowHandles = it.second;
            for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
@@ -4921,13 +4923,8 @@ sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
        return nullptr;
    }

sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(const sp<IBinder>& windowHandleToken,
                                                            int displayId) const {
    if (windowHandleToken == nullptr) {
        return nullptr;
    }

    for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
    // Only look through the requested display.
    for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesLocked(*displayId)) {
        if (windowHandle->getToken() == windowHandleToken) {
            return windowHandle;
        }
+3 −6
Original line number Diff line number Diff line
@@ -354,14 +354,11 @@ private:
    // Get a reference to window handles by display, return an empty vector if not found.
    const std::vector<sp<android::gui::WindowInfoHandle>>& getWindowHandlesLocked(
            int32_t displayId) const REQUIRES(mLock);
    sp<android::gui::WindowInfoHandle> getWindowHandleLocked(
            const sp<IBinder>& windowHandleToken) const REQUIRES(mLock);
    ui::Transform getTransformLocked(int32_t displayId) const REQUIRES(mLock);

    // Same function as above, but faster. Since displayId is provided, this avoids the need
    // to loop through all displays.
    sp<android::gui::WindowInfoHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken,
                                                             int displayId) const REQUIRES(mLock);
    sp<android::gui::WindowInfoHandle> getWindowHandleLocked(
            const sp<IBinder>& windowHandleToken, std::optional<int32_t> displayId = {}) const
            REQUIRES(mLock);
    sp<android::gui::WindowInfoHandle> getWindowHandleLocked(
            const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock);
    std::shared_ptr<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const
+30 −0
Original line number Diff line number Diff line
@@ -4699,6 +4699,36 @@ TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorre
    firstWindow->assertNoEvents();
}

TEST_F(InputDispatcherDisplayProjectionTest,
       SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
    auto [firstWindow, secondWindow] = setupScaledDisplayScenario();

    const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
    ui::Transform secondDisplayTransform;
    secondDisplayTransform.set(matrix);
    addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);

    sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
    secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
    addWindow(secondWindowClone);

    // Send hover enter to second window
    mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
                                                 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
    secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
                                           WithCoords(100, 80), WithRawCoords(300, 880),
                                           WithDisplayId(ADISPLAY_ID_DEFAULT)));

    mDispatcher->cancelCurrentTouch();

    // Ensure the cancelation happens with the correct displayId and the correct coordinates.
    secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
                                           WithRawCoords(300, 880),
                                           WithDisplayId(ADISPLAY_ID_DEFAULT)));
    secondWindow->assertNoEvents();
    firstWindow->assertNoEvents();
}

/** Ensure consistent behavior of InputDispatcher in all orientations. */
class InputDispatcherDisplayOrientationFixture
      : public InputDispatcherDisplayProjectionTest,