Loading include/input/Input.h +2 −0 Original line number Diff line number Diff line Loading @@ -837,6 +837,8 @@ protected: std::vector<PointerCoords> mSamplePointerCoords; }; std::ostream& operator<<(std::ostream& out, const MotionEvent& event); /* * Focus events. */ Loading libs/input/Input.cpp +69 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ #include <inttypes.h> #include <string.h> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <cutils/compiler.h> #include <gui/constants.h> #include <input/DisplayViewport.h> #include <input/Input.h> Loading Loading @@ -542,7 +544,14 @@ void MotionEvent::setCursorPosition(float x, float y) { } const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) { LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this; } const size_t position = getHistorySize() * getPointerCount() + pointerIndex; if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) { LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this; } return &mSamplePointerCoords[position]; } float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { Loading @@ -555,7 +564,18 @@ float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( size_t pointerIndex, size_t historicalIndex) const { return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) { LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this; } if (CC_UNLIKELY(historicalIndex < 0 || historicalIndex > getHistorySize())) { LOG(FATAL) << __func__ << ": Invalid historical index " << historicalIndex << " for " << *this; } const size_t position = historicalIndex * getPointerCount() + pointerIndex; if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) { LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this; } return &mSamplePointerCoords[position]; } float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, Loading Loading @@ -903,6 +923,53 @@ PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, return out; } std::ostream& operator<<(std::ostream& out, const MotionEvent& event) { out << "MotionEvent { action=" << MotionEvent::actionToString(event.getAction()); if (event.getActionButton() != 0) { out << ", actionButton=" << std::to_string(event.getActionButton()); } const size_t pointerCount = event.getPointerCount(); for (size_t i = 0; i < pointerCount; i++) { out << ", id[" << i << "]=" << event.getPointerId(i); float x = event.getX(i); float y = event.getY(i); if (x != 0 || y != 0) { out << ", x[" << i << "]=" << x; out << ", y[" << i << "]=" << y; } int toolType = event.getToolType(i); if (toolType != AMOTION_EVENT_TOOL_TYPE_FINGER) { out << ", toolType[" << i << "]=" << toolType; } } if (event.getButtonState() != 0) { out << ", buttonState=" << event.getButtonState(); } if (event.getClassification() != MotionClassification::NONE) { out << ", classification=" << motionClassificationToString(event.getClassification()); } if (event.getMetaState() != 0) { out << ", metaState=" << event.getMetaState(); } if (event.getEdgeFlags() != 0) { out << ", edgeFlags=" << event.getEdgeFlags(); } if (pointerCount != 1) { out << ", pointerCount=" << pointerCount; } if (event.getHistorySize() != 0) { out << ", historySize=" << event.getHistorySize(); } out << ", eventTime=" << event.getEventTime(); out << ", downTime=" << event.getDownTime(); out << ", deviceId=" << event.getDeviceId(); out << ", source=" << inputEventSourceToString(event.getSource()); out << ", displayId=" << event.getDisplayId(); out << ", eventId=" << event.getId(); out << "}"; return out; } // --- FocusEvent --- void FocusEvent::initialize(int32_t id, bool hasFocus) { Loading services/inputflinger/dispatcher/InputDispatcher.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -2507,7 +2507,7 @@ void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (!mDragState) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { return; } Loading Loading @@ -4765,9 +4765,11 @@ void InputDispatcher::setInputWindowsLocked( // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We // could just clear the state here. if (mDragState && if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId && std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) == windowHandles.end()) { ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str()); sendDropWindowCommandLocked(nullptr, 0, 0); mDragState.reset(); } } Loading services/inputflinger/tests/InputDispatcher_test.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -6407,6 +6407,58 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { mSecondWindow->consumeMotionMove(); } TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { performDrag(); // Update window of second display. sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID); mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); // Let second display has a touch state. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .displayId(SECOND_DISPLAY_ID) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER) .x(100) .y(100)) .build())); windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, SECOND_DISPLAY_ID, 0 /* expectedFlag */); // Update window again. mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); // 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(); } class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { Loading Loading
include/input/Input.h +2 −0 Original line number Diff line number Diff line Loading @@ -837,6 +837,8 @@ protected: std::vector<PointerCoords> mSamplePointerCoords; }; std::ostream& operator<<(std::ostream& out, const MotionEvent& event); /* * Focus events. */ Loading
libs/input/Input.cpp +69 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ #include <inttypes.h> #include <string.h> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <cutils/compiler.h> #include <gui/constants.h> #include <input/DisplayViewport.h> #include <input/Input.h> Loading Loading @@ -542,7 +544,14 @@ void MotionEvent::setCursorPosition(float x, float y) { } const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) { LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this; } const size_t position = getHistorySize() * getPointerCount() + pointerIndex; if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) { LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this; } return &mSamplePointerCoords[position]; } float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { Loading @@ -555,7 +564,18 @@ float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( size_t pointerIndex, size_t historicalIndex) const { return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) { LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this; } if (CC_UNLIKELY(historicalIndex < 0 || historicalIndex > getHistorySize())) { LOG(FATAL) << __func__ << ": Invalid historical index " << historicalIndex << " for " << *this; } const size_t position = historicalIndex * getPointerCount() + pointerIndex; if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) { LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this; } return &mSamplePointerCoords[position]; } float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, Loading Loading @@ -903,6 +923,53 @@ PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, return out; } std::ostream& operator<<(std::ostream& out, const MotionEvent& event) { out << "MotionEvent { action=" << MotionEvent::actionToString(event.getAction()); if (event.getActionButton() != 0) { out << ", actionButton=" << std::to_string(event.getActionButton()); } const size_t pointerCount = event.getPointerCount(); for (size_t i = 0; i < pointerCount; i++) { out << ", id[" << i << "]=" << event.getPointerId(i); float x = event.getX(i); float y = event.getY(i); if (x != 0 || y != 0) { out << ", x[" << i << "]=" << x; out << ", y[" << i << "]=" << y; } int toolType = event.getToolType(i); if (toolType != AMOTION_EVENT_TOOL_TYPE_FINGER) { out << ", toolType[" << i << "]=" << toolType; } } if (event.getButtonState() != 0) { out << ", buttonState=" << event.getButtonState(); } if (event.getClassification() != MotionClassification::NONE) { out << ", classification=" << motionClassificationToString(event.getClassification()); } if (event.getMetaState() != 0) { out << ", metaState=" << event.getMetaState(); } if (event.getEdgeFlags() != 0) { out << ", edgeFlags=" << event.getEdgeFlags(); } if (pointerCount != 1) { out << ", pointerCount=" << pointerCount; } if (event.getHistorySize() != 0) { out << ", historySize=" << event.getHistorySize(); } out << ", eventTime=" << event.getEventTime(); out << ", downTime=" << event.getDownTime(); out << ", deviceId=" << event.getDeviceId(); out << ", source=" << inputEventSourceToString(event.getSource()); out << ", displayId=" << event.getDisplayId(); out << ", eventId=" << event.getId(); out << "}"; return out; } // --- FocusEvent --- void FocusEvent::initialize(int32_t id, bool hasFocus) { Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -2507,7 +2507,7 @@ void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (!mDragState) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { return; } Loading Loading @@ -4765,9 +4765,11 @@ void InputDispatcher::setInputWindowsLocked( // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We // could just clear the state here. if (mDragState && if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId && std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) == windowHandles.end()) { ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str()); sendDropWindowCommandLocked(nullptr, 0, 0); mDragState.reset(); } } Loading
services/inputflinger/tests/InputDispatcher_test.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -6407,6 +6407,58 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { mSecondWindow->consumeMotionMove(); } TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { performDrag(); // Update window of second display. sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID); mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); // Let second display has a touch state. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .displayId(SECOND_DISPLAY_ID) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER) .x(100) .y(100)) .build())); windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, SECOND_DISPLAY_ID, 0 /* expectedFlag */); // Update window again. mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); // 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(); } class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { Loading