From f452d0b9bbfa019422801b7ae132bb31fccd181e Mon Sep 17 00:00:00 2001 From: arthurhung Date: Wed, 6 Jan 2021 00:19:52 +0800 Subject: Move drag event to InputDispatcher (5/n) This CL add 'notifyDropWindow' to tell the policy about the dropping window has been detected. That could help the drag controller to handle the drop event and dispatch the clip data to the corresponding client. Bug: 158242495 Test: atest inputflinger_tests Change-Id: If7bce072dff5bdacb7eb765f94eb73ed63a58170 --- .../benchmarks/InputDispatcher_benchmarks.cpp | 2 + services/inputflinger/dispatcher/Entry.h | 2 + .../inputflinger/dispatcher/InputDispatcher.cpp | 20 ++++++++++ services/inputflinger/dispatcher/InputDispatcher.h | 3 ++ .../include/InputDispatcherPolicyInterface.h | 3 ++ .../inputflinger/tests/InputDispatcher_test.cpp | 44 ++++++++++++++++++++++ 6 files changed, 74 insertions(+) diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index b2ddb42eab..7bd0c6b1b8 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -113,6 +113,8 @@ private: void setPointerCapture(bool enabled) override {} + void notifyDropWindow(const sp&, float x, float y) override {} + InputDispatcherConfiguration mConfig; }; diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index e5fb26c177..f3ef64ba8e 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -287,6 +287,8 @@ struct CommandEntry { int32_t pid; nsecs_t consumeTime; // time when the event was consumed by InputConsumer int32_t displayId; + float x; + float y; }; } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index fe46d17493..397a9d78e5 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2345,6 +2345,10 @@ void InputDispatcher::addDragEventLocked(const MotionEntry& entry, TouchState& s } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { + if (state.dragHoverWindowHandle && maskedAction == AMOTION_EVENT_ACTION_UP) { + vec2 local = state.dragHoverWindowHandle->getInfo()->transform.transform(x, y); + notifyDropWindowLocked(state.dragHoverWindowHandle->getToken(), local.x, local.y); + } state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; } @@ -5302,6 +5306,15 @@ void InputDispatcher::notifyFocusChangedLocked(const sp& oldToken, postCommandLocked(std::move(commandEntry)); } +void InputDispatcher::notifyDropWindowLocked(const sp& token, float x, float y) { + std::unique_ptr commandEntry = + std::make_unique(&InputDispatcher::doNotifyDropWindowLockedInterruptible); + commandEntry->newToken = token; + commandEntry->x = x; + commandEntry->y = y; + postCommandLocked(std::move(commandEntry)); +} + void InputDispatcher::onAnrLocked(const sp& connection) { if (connection == nullptr) { LOG_ALWAYS_FATAL("Caller must check for nullness"); @@ -5411,6 +5424,13 @@ void InputDispatcher::doNotifyFocusChangedLockedInterruptible(CommandEntry* comm mLock.lock(); } +void InputDispatcher::doNotifyDropWindowLockedInterruptible(CommandEntry* commandEntry) { + sp newToken = commandEntry->newToken; + mLock.unlock(); + mPolicy->notifyDropWindow(newToken, commandEntry->x, commandEntry->y); + mLock.lock(); +} + void InputDispatcher::doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) { mLock.unlock(); diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index b2f3625a73..593ec23e23 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -592,6 +592,7 @@ private: void onFocusChangedLocked(const FocusResolver::FocusChanges& changes) REQUIRES(mLock); void notifyFocusChangedLocked(const sp& oldFocus, const sp& newFocus) REQUIRES(mLock); + void notifyDropWindowLocked(const sp& token, float x, float y) REQUIRES(mLock); void onAnrLocked(const sp& connection) REQUIRES(mLock); void onAnrLocked(std::shared_ptr application) REQUIRES(mLock); void onUntrustedTouchLocked(const std::string& obscuringPackage) REQUIRES(mLock); @@ -607,6 +608,8 @@ private: REQUIRES(mLock); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); + void doNotifyDropWindowLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); + // ANR-related callbacks - start void doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyWindowUnresponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 439d85e06e..219f45a7c3 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -157,6 +157,9 @@ public: * InputDispatcher is solely responsible for updating the Pointer Capture state. */ virtual void setPointerCapture(bool enabled) = 0; + + /* Notifies the policy that the drag window has moved over to another window */ + virtual void notifyDropWindow(const sp& token, float x, float y) = 0; }; } // namespace android diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 32f9b69806..cedda6e91c 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -266,6 +266,11 @@ public: mPointerCaptureEnabled.reset(); } + void assertDropTargetEquals(const sp& targetToken) { + std::scoped_lock lock(mLock); + ASSERT_EQ(targetToken, mDropTargetWindowToken); + } + private: std::mutex mLock; std::unique_ptr mFilteredEvent GUARDED_BY(mLock); @@ -284,6 +289,8 @@ private: std::queue mResponsiveMonitorPids GUARDED_BY(mLock); std::condition_variable mNotifyAnr; + sp mDropTargetWindowToken GUARDED_BY(mLock); + void notifyConfigurationChanged(nsecs_t when) override { std::scoped_lock lock(mLock); mConfigurationChangedTime = when; @@ -392,6 +399,11 @@ private: mPointerCaptureChangedCondition.notify_all(); } + void notifyDropWindow(const sp& token, float x, float y) override { + std::scoped_lock lock(mLock); + mDropTargetWindowToken = token; + } + void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action, int32_t displayId) { std::scoped_lock lock(mLock); @@ -4789,4 +4801,36 @@ TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) { mSecondWindow->assertNoEvents(); } +TEST_F(InputDispatcherDragTests, DragAndDrop) { + performDrag(); + + // Move on window. + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {50, 50})) + << "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, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {150, 50})) + << "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, + injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {150, 50})) + << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; + mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); + mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken()); + mWindow->assertNoEvents(); + mSecondWindow->assertNoEvents(); +} + } // namespace android::inputdispatcher -- cgit v1.2.3-59-g8ed1b