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

Commit e476b108 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8903569 from 190ac25e to tm-qpr1-release

Change-Id: I6f57426d6699a1e85281f48ee82e44e32e1e61aa
parents 8f6e2c7a 190ac25e
Loading
Loading
Loading
Loading
+28 −27
Original line number Diff line number Diff line
@@ -2195,10 +2195,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(

            // Update the temporary touch state.
            BitSet32 pointerIds;
            if (isSplit) {
                uint32_t pointerId = entry.pointerProperties[pointerIndex].id;
                pointerIds.markBit(pointerId);
            }
            pointerIds.markBit(entry.pointerProperties[pointerIndex].id);

            tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds);
        }
@@ -2275,9 +2272,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
                }

                BitSet32 pointerIds;
                if (isSplit) {
                pointerIds.markBit(entry.pointerProperties[0].id);
                }
                tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
            }
        }
@@ -2453,21 +2448,28 @@ Failed:
            }
        } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
            // One pointer went up.
            if (isSplit) {
            int32_t pointerIndex = getMotionEventActionPointerIndex(action);
            uint32_t pointerId = entry.pointerProperties[pointerIndex].id;

            for (size_t i = 0; i < tempTouchState.windows.size();) {
                TouchedWindow& touchedWindow = tempTouchState.windows[i];
                    if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
                touchedWindow.pointerIds.clearBit(pointerId);
                if (touchedWindow.pointerIds.isEmpty()) {
                    tempTouchState.windows.erase(tempTouchState.windows.begin() + i);
                    continue;
                }
                    }
                i += 1;
            }
        } else if (!isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
            // If no split, we suppose all touched windows should receive pointer down.
            const int32_t pointerIndex = getMotionEventActionPointerIndex(action);
            for (size_t i = 0; i < tempTouchState.windows.size(); i++) {
                TouchedWindow& touchedWindow = tempTouchState.windows[i];
                // Ignore drag window for it should just track one pointer.
                if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
                    continue;
                }
                touchedWindow.pointerIds.markBit(entry.pointerProperties[pointerIndex].id);
            }
        }

@@ -5087,14 +5089,13 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<

        // Store the dragging window.
        if (isDragDrop) {
            if (pointerIds.count() > 1) {
                ALOGW("The drag and drop cannot be started when there is more than 1 pointer on the"
                      " window.");
            if (pointerIds.count() != 1) {
                ALOGW("The drag and drop cannot be started when there is no pointer or more than 1"
                      " pointer on the window.");
                return false;
            }
            // If the window didn't not support split or the source is mouse, the pointerIds count
            // would be 0, so we have to track the pointer 0.
            const int32_t id = pointerIds.count() == 0 ? 0 : pointerIds.firstMarkedBit();
            // Track the pointer id for drag window and generate the drag state.
            const int32_t id = pointerIds.firstMarkedBit();
            mDragState = std::make_unique<DragState>(toWindowHandle, id);
        }

+2 −2
Original line number Diff line number Diff line
@@ -43,8 +43,8 @@ std::string dispatchModeToString(int32_t dispatchMode) {
}

void InputTarget::addPointers(BitSet32 newPointerIds, const ui::Transform& transform) {
    // The pointerIds can be empty, but still a valid InputTarget. This can happen for Monitors
    // and non splittable windows since we will just use all the pointers from the input event.
    // The pointerIds can be empty, but still a valid InputTarget. This can happen when there is no
    // valid pointer property from the input event.
    if (newPointerIds.isEmpty()) {
        setDefaultPointerTransform(transform);
        return;
+1 −1
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ namespace inputdispatcher {
struct TouchedWindow {
    sp<gui::WindowInfoHandle> windowHandle;
    int32_t targetFlags;
    BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set
    BitSet32 pointerIds;
};

} // namespace inputdispatcher
+98 −40
Original line number Diff line number Diff line
@@ -6125,6 +6125,8 @@ protected:
    sp<FakeWindowHandle> mWindow;
    sp<FakeWindowHandle> mSecondWindow;
    sp<FakeWindowHandle> mDragWindow;
    // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
    static constexpr int32_t MOUSE_POINTER_ID = 1;

    void SetUp() override {
        InputDispatcherTest::SetUp();
@@ -6139,11 +6141,41 @@ protected:
        mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
    }

    void injectDown() {
    void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
        switch (fromSource) {
            case AINPUT_SOURCE_TOUCHSCREEN:
                ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
                  injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                                   {50, 50}))
                          injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
                                           ADISPLAY_ID_DEFAULT, {50, 50}))
                        << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
                break;
            case AINPUT_SOURCE_STYLUS:
                ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
                          injectMotionEvent(
                                  mDispatcher,
                                  MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
                                                     AINPUT_SOURCE_STYLUS)
                                          .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
                                          .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
                                                           .x(50)
                                                           .y(50))
                                          .build()));
                break;
            case AINPUT_SOURCE_MOUSE:
                ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
                          injectMotionEvent(
                                  mDispatcher,
                                  MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
                                          .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
                                          .pointer(PointerBuilder(MOUSE_POINTER_ID,
                                                                  AMOTION_EVENT_TOOL_TYPE_MOUSE)
                                                           .x(50)
                                                           .y(50))
                                          .build()));
                break;
            default:
                FAIL() << "Source " << fromSource << " doesn't support drag and drop";
        }

        // Window should receive motion event.
        mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
@@ -6152,9 +6184,9 @@ protected:
    // Start performing drag, we will create a drag window and transfer touch to it.
    // @param sendDown : if true, send a motion down on first window before perform drag and drop.
    // Returns true on success.
    bool performDrag(bool sendDown = true) {
    bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
        if (sendDown) {
            injectDown();
            injectDown(fromSource);
        }

        // The drag window covers the entire display
@@ -6172,36 +6204,10 @@ protected:
        }
        return transferred;
    }

    // Start performing drag, we will create a drag window and transfer touch to it.
    void performStylusDrag() {
        ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
                  injectMotionEvent(mDispatcher,
                                    MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
                                                       AINPUT_SOURCE_STYLUS)
                                            .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
                                            .pointer(PointerBuilder(0,
                                                                    AMOTION_EVENT_TOOL_TYPE_STYLUS)
                                                             .x(50)
                                                             .y(50))
                                            .build()));
        mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);

        // The drag window covers the entire display
        mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
        mDispatcher->setInputWindows(
                {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});

        // Transfer touch focus to the drag window
        mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
                                        true /* isDragDrop */);
        mWindow->consumeMotionCancel();
        mDragWindow->consumeMotionDown();
    }
};

TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
    performDrag();
    startDrag();

    // Move on window.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -6239,7 +6245,7 @@ TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
}

TEST_F(InputDispatcherDragTests, DragAndDrop) {
    performDrag();
    startDrag();

    // Move on window.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -6271,7 +6277,7 @@ TEST_F(InputDispatcherDragTests, DragAndDrop) {
}

TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
    performStylusDrag();
    startDrag(true, AINPUT_SOURCE_STYLUS);

    // Move on window and keep button pressed.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -6318,7 +6324,7 @@ TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
}

TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
    performDrag();
    startDrag();

    // Set second window invisible.
    mSecondWindow->setVisible(false);
@@ -6354,6 +6360,9 @@ TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
}

TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
    // Ensure window could track pointerIds if it didn't support split touch.
    mWindow->setPreventSplitting(true);

    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                               {50, 50}))
@@ -6374,7 +6383,7 @@ TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
    mWindow->consumeMotionPointerDown(1 /* pointerIndex */);

    // Should not perform drag and drop when window has multi fingers.
    ASSERT_FALSE(performDrag(false));
    ASSERT_FALSE(startDrag(false));
}

TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
@@ -6402,7 +6411,7 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
    mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);

    // Perform drag and drop from first window.
    ASSERT_TRUE(performDrag(false));
    ASSERT_TRUE(startDrag(false));

    // Move on window.
    const MotionEvent secondFingerMoveEvent =
@@ -6437,7 +6446,7 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
}

TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
    performDrag();
    startDrag();

    // Update window of second display.
    sp<FakeWindowHandle> windowInSecondary =
@@ -6488,6 +6497,55 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
    mSecondWindow->assertNoEvents();
}

TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
    startDrag(true, AINPUT_SOURCE_MOUSE);
    // Move on window.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher,
                                MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
                                        .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
                                        .pointer(PointerBuilder(MOUSE_POINTER_ID,
                                                                AMOTION_EVENT_TOOL_TYPE_MOUSE)
                                                         .x(50)
                                                         .y(50))
                                        .build()))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
    mWindow->consumeDragEvent(false, 50, 50);
    mSecondWindow->assertNoEvents();

    // Move to another window.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher,
                                MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
                                        .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
                                        .pointer(PointerBuilder(MOUSE_POINTER_ID,
                                                                AMOTION_EVENT_TOOL_TYPE_MOUSE)
                                                         .x(150)
                                                         .y(50))
                                        .build()))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
    mWindow->consumeDragEvent(true, 150, 50);
    mSecondWindow->consumeDragEvent(false, 50, 50);

    // drop to another window.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher,
                                MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
                                        .buttonState(0)
                                        .pointer(PointerBuilder(MOUSE_POINTER_ID,
                                                                AMOTION_EVENT_TOOL_TYPE_MOUSE)
                                                         .x(150)
                                                         .y(50))
                                        .build()))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
    mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
    mWindow->assertNoEvents();
    mSecondWindow->assertNoEvents();
}

class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};

TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {