diff options
6 files changed, 74 insertions, 0 deletions
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<IBinder>&, 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<IBinder>& oldToken, postCommandLocked(std::move(commandEntry)); } +void InputDispatcher::notifyDropWindowLocked(const sp<IBinder>& token, float x, float y) { + std::unique_ptr<CommandEntry> commandEntry = + std::make_unique<CommandEntry>(&InputDispatcher::doNotifyDropWindowLockedInterruptible); + commandEntry->newToken = token; + commandEntry->x = x; + commandEntry->y = y; + postCommandLocked(std::move(commandEntry)); +} + void InputDispatcher::onAnrLocked(const sp<Connection>& 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<IBinder> 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<IBinder>& oldFocus, const sp<IBinder>& newFocus) REQUIRES(mLock); + void notifyDropWindowLocked(const sp<IBinder>& token, float x, float y) REQUIRES(mLock); void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); void onAnrLocked(std::shared_ptr<InputApplicationHandle> 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<IBinder>& 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<IBinder>& targetToken) { + std::scoped_lock lock(mLock); + ASSERT_EQ(targetToken, mDropTargetWindowToken); + } + private: std::mutex mLock; std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock); @@ -284,6 +289,8 @@ private: std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock); std::condition_variable mNotifyAnr; + sp<IBinder> 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<IBinder>& 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 |