Loading services/inputflinger/dispatcher/InputDispatcher.cpp +10 −0 Original line number Original line Diff line number Diff line Loading @@ -1657,6 +1657,13 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr< InputEventInjectionResult injectionResult; InputEventInjectionResult injectionResult; if (isPointerEvent) { if (isPointerEvent) { // Pointer event. (eg. touchscreen) // Pointer event. (eg. touchscreen) if (mDragState && (entry->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN) { // If drag and drop ongoing and pointer down occur: pilfer drag window pointers pilferPointersLocked(mDragState->dragWindow->getToken()); } injectionResult = injectionResult = findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime, findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime, &conflictingPointerActions); &conflictingPointerActions); Loading Loading @@ -5575,7 +5582,10 @@ void InputDispatcher::removeMonitorChannelLocked(const sp<IBinder>& connectionTo status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { std::scoped_lock _l(mLock); std::scoped_lock _l(mLock); return pilferPointersLocked(token); } status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) { const std::shared_ptr<InputChannel> requestingChannel = getInputChannelLocked(token); const std::shared_ptr<InputChannel> requestingChannel = getInputChannelLocked(token); if (!requestingChannel) { if (!requestingChannel) { ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token"); ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token"); Loading services/inputflinger/dispatcher/InputDispatcher.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -255,6 +255,8 @@ private: void removeConnectionLocked(const sp<Connection>& connection) REQUIRES(mLock); void removeConnectionLocked(const sp<Connection>& connection) REQUIRES(mLock); status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock); template <typename T> template <typename T> struct StrongPointerHash { struct StrongPointerHash { std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); } std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); } Loading services/inputflinger/tests/InputDispatcher_test.cpp +35 −2 Original line number Original line Diff line number Diff line Loading @@ -6094,6 +6094,7 @@ protected: sp<FakeWindowHandle> mWindow; sp<FakeWindowHandle> mWindow; sp<FakeWindowHandle> mSecondWindow; sp<FakeWindowHandle> mSecondWindow; sp<FakeWindowHandle> mDragWindow; sp<FakeWindowHandle> mDragWindow; sp<FakeWindowHandle> mSpyWindow; void SetUp() override { void SetUp() override { InputDispatcherTest::SetUp(); InputDispatcherTest::SetUp(); Loading @@ -6104,8 +6105,13 @@ protected: mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT); mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT); mSecondWindow->setFrame(Rect(100, 0, 200, 100)); mSecondWindow->setFrame(Rect(100, 0, 200, 100)); mSpyWindow = new FakeWindowHandle(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT); mSpyWindow->setSpy(true); mSpyWindow->setTrustedOverlay(true); mSpyWindow->setFrame(Rect(0, 0, 200, 100)); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}}); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}}); } } void injectDown() { void injectDown() { Loading @@ -6116,6 +6122,8 @@ protected: // Window should receive motion event. // Window should receive motion event. mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); // Spy window should also receive motion event mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); } } // Start performing drag, we will create a drag window and transfer touch to it. // Start performing drag, we will create a drag window and transfer touch to it. Loading @@ -6128,8 +6136,9 @@ protected: // The drag window covers the entire display // The drag window covers the entire display mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT); mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT); mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}}); mDispatcher->setInputWindows( mDispatcher->setInputWindows( {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}}); {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}}); // Transfer touch focus to the drag window // Transfer touch focus to the drag window bool transferred = bool transferred = Loading Loading @@ -6207,6 +6216,30 @@ TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) { mSecondWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); } } TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) { performDrag(); // No cancel event after drag start mSpyWindow->assertNoEvents(); const MotionEvent secondFingerDownEvent = MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .eventTime(systemTime(SYSTEM_TIME_MONOTONIC)) .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50)) .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60)) .build(); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT)) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; // Receives cancel for first pointer after next pointer down mSpyWindow->consumeMotionCancel(); mSpyWindow->consumeMotionDown(); mSpyWindow->assertNoEvents(); } TEST_F(InputDispatcherDragTests, DragAndDrop) { TEST_F(InputDispatcherDragTests, DragAndDrop) { performDrag(); performDrag(); Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +10 −0 Original line number Original line Diff line number Diff line Loading @@ -1657,6 +1657,13 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr< InputEventInjectionResult injectionResult; InputEventInjectionResult injectionResult; if (isPointerEvent) { if (isPointerEvent) { // Pointer event. (eg. touchscreen) // Pointer event. (eg. touchscreen) if (mDragState && (entry->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN) { // If drag and drop ongoing and pointer down occur: pilfer drag window pointers pilferPointersLocked(mDragState->dragWindow->getToken()); } injectionResult = injectionResult = findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime, findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime, &conflictingPointerActions); &conflictingPointerActions); Loading Loading @@ -5575,7 +5582,10 @@ void InputDispatcher::removeMonitorChannelLocked(const sp<IBinder>& connectionTo status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { std::scoped_lock _l(mLock); std::scoped_lock _l(mLock); return pilferPointersLocked(token); } status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) { const std::shared_ptr<InputChannel> requestingChannel = getInputChannelLocked(token); const std::shared_ptr<InputChannel> requestingChannel = getInputChannelLocked(token); if (!requestingChannel) { if (!requestingChannel) { ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token"); ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token"); Loading
services/inputflinger/dispatcher/InputDispatcher.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -255,6 +255,8 @@ private: void removeConnectionLocked(const sp<Connection>& connection) REQUIRES(mLock); void removeConnectionLocked(const sp<Connection>& connection) REQUIRES(mLock); status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock); template <typename T> template <typename T> struct StrongPointerHash { struct StrongPointerHash { std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); } std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); } Loading
services/inputflinger/tests/InputDispatcher_test.cpp +35 −2 Original line number Original line Diff line number Diff line Loading @@ -6094,6 +6094,7 @@ protected: sp<FakeWindowHandle> mWindow; sp<FakeWindowHandle> mWindow; sp<FakeWindowHandle> mSecondWindow; sp<FakeWindowHandle> mSecondWindow; sp<FakeWindowHandle> mDragWindow; sp<FakeWindowHandle> mDragWindow; sp<FakeWindowHandle> mSpyWindow; void SetUp() override { void SetUp() override { InputDispatcherTest::SetUp(); InputDispatcherTest::SetUp(); Loading @@ -6104,8 +6105,13 @@ protected: mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT); mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT); mSecondWindow->setFrame(Rect(100, 0, 200, 100)); mSecondWindow->setFrame(Rect(100, 0, 200, 100)); mSpyWindow = new FakeWindowHandle(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT); mSpyWindow->setSpy(true); mSpyWindow->setTrustedOverlay(true); mSpyWindow->setFrame(Rect(0, 0, 200, 100)); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}}); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}}); } } void injectDown() { void injectDown() { Loading @@ -6116,6 +6122,8 @@ protected: // Window should receive motion event. // Window should receive motion event. mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); // Spy window should also receive motion event mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); } } // Start performing drag, we will create a drag window and transfer touch to it. // Start performing drag, we will create a drag window and transfer touch to it. Loading @@ -6128,8 +6136,9 @@ protected: // The drag window covers the entire display // The drag window covers the entire display mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT); mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT); mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}}); mDispatcher->setInputWindows( mDispatcher->setInputWindows( {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}}); {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}}); // Transfer touch focus to the drag window // Transfer touch focus to the drag window bool transferred = bool transferred = Loading Loading @@ -6207,6 +6216,30 @@ TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) { mSecondWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); } } TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) { performDrag(); // No cancel event after drag start mSpyWindow->assertNoEvents(); const MotionEvent secondFingerDownEvent = MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .eventTime(systemTime(SYSTEM_TIME_MONOTONIC)) .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50)) .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60)) .build(); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT)) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; // Receives cancel for first pointer after next pointer down mSpyWindow->consumeMotionCancel(); mSpyWindow->consumeMotionDown(); mSpyWindow->assertNoEvents(); } TEST_F(InputDispatcherDragTests, DragAndDrop) { TEST_F(InputDispatcherDragTests, DragAndDrop) { performDrag(); performDrag(); Loading