Loading libs/gui/tests/EndToEndNativeInputTest.cpp +61 −7 Original line number Diff line number Diff line Loading @@ -112,22 +112,31 @@ public: if (consumed != OK) { return nullptr; } mInputConsumer->sendFinishedSignal(seqId, true); status_t status = mInputConsumer->sendFinishedSignal(seqId, true); EXPECT_EQ(OK, status) << "Could not send finished signal"; return ev; } void assertFocusChange(bool hasFocus) { InputEvent *ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, ev->getType()); FocusEvent *focusEvent = static_cast<FocusEvent *>(ev); EXPECT_EQ(hasFocus, focusEvent->getHasFocus()); } void expectTap(int x, int y) { InputEvent* ev = consumeEvent(); EXPECT_TRUE(ev != nullptr); EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION); ASSERT_NE(ev, nullptr); ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); MotionEvent* mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); EXPECT_EQ(x, mev->getX(0)); EXPECT_EQ(y, mev->getY(0)); ev = consumeEvent(); EXPECT_TRUE(ev != nullptr); EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION); ASSERT_NE(ev, nullptr); ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); } Loading Loading @@ -212,7 +221,7 @@ public: ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); const auto display = mComposerClient->getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); ASSERT_NE(display, nullptr); DisplayInfo info; ASSERT_EQ(NO_ERROR, mComposerClient->getDisplayInfo(display, &info)); Loading Loading @@ -259,18 +268,28 @@ void injectTap(int x, int y) { TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); surface->assertFocusChange(true); injectTap(101, 101); EXPECT_TRUE(surface->consumeEvent() != nullptr); EXPECT_NE(surface->consumeEvent(), nullptr); } /** * Set up two surfaces side-by-side. Tap each surface. * Next, swap the positions of the two surfaces. Inject tap into the two * original locations. Ensure that the tap is received by the surfaces in the * reverse order. */ TEST_F(InputSurfacesTest, input_respects_positioning) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); surface->assertFocusChange(true); std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100); surface2->showAt(200, 200); surface->assertFocusChange(false); surface2->assertFocusChange(true); injectTap(201, 201); surface2->expectTap(1, 1); Loading @@ -297,11 +316,16 @@ TEST_F(InputSurfacesTest, input_respects_layering) { std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100); surface->showAt(10, 10); surface->assertFocusChange(true); surface2->showAt(10, 10); surface->assertFocusChange(false); surface2->assertFocusChange(true); surface->doTransaction([](auto &t, auto &sc) { t.setLayer(sc, LAYER_BASE + 1); }); surface2->assertFocusChange(false); surface->assertFocusChange(true); injectTap(11, 11); surface->expectTap(1, 1); Loading @@ -309,6 +333,8 @@ TEST_F(InputSurfacesTest, input_respects_layering) { surface2->doTransaction([](auto &t, auto &sc) { t.setLayer(sc, LAYER_BASE + 1); }); surface2->assertFocusChange(true); surface->assertFocusChange(false); injectTap(11, 11); surface2->expectTap(1, 1); Loading @@ -316,6 +342,8 @@ TEST_F(InputSurfacesTest, input_respects_layering) { surface2->doTransaction([](auto &t, auto &sc) { t.hide(sc); }); surface2->assertFocusChange(false); surface->assertFocusChange(true); injectTap(11, 11); surface->expectTap(1, 1); Loading @@ -328,9 +356,12 @@ TEST_F(InputSurfacesTest, input_respects_surface_insets) { std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(100, 100); bgSurface->assertFocusChange(true); fgSurface->mInputInfo.surfaceInset = 5; fgSurface->showAt(100, 100); fgSurface->assertFocusChange(true); bgSurface->assertFocusChange(false); injectTap(106, 106); fgSurface->expectTap(1, 1); Loading @@ -344,9 +375,12 @@ TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) { std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> childSurface = makeSurface(100, 100); parentSurface->showAt(100, 100); parentSurface->assertFocusChange(true); childSurface->mInputInfo.surfaceInset = 10; childSurface->showAt(100, 100); childSurface->assertFocusChange(true); parentSurface->assertFocusChange(false); childSurface->doTransaction([&](auto &t, auto &sc) { t.setPosition(sc, -5, -5); Loading @@ -365,9 +399,12 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) { std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(100, 100); bgSurface->assertFocusChange(true); fgSurface->mInputInfo.surfaceInset = 5; fgSurface->showAt(100, 100); bgSurface->assertFocusChange(false); fgSurface->assertFocusChange(true); fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); }); Loading @@ -384,6 +421,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) { // In case we pass the very big inset without any checking. fgSurface->mInputInfo.surfaceInset = INT32_MAX; fgSurface->showAt(100, 100); fgSurface->assertFocusChange(true); fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); Loading @@ -400,6 +438,7 @@ TEST_F(InputSurfacesTest, input_ignores_transparent_region) { t.setTransparentRegionHint(sc, transparentRegion); }); surface->showAt(100, 100); surface->assertFocusChange(true); injectTap(101, 101); surface->expectTap(1, 1); } Loading @@ -414,7 +453,10 @@ TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) { InputSurface::makeBufferInputSurface(mComposerClient, 100, 100); bgSurface->showAt(10, 10); bgSurface->assertFocusChange(true); bufferSurface->showAt(10, 10); bgSurface->assertFocusChange(false); bufferSurface->assertFocusChange(true); injectTap(11, 11); bufferSurface->expectTap(1, 1); Loading @@ -431,7 +473,10 @@ TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) { postBuffer(bufferSurface->mSurfaceControl); bgSurface->showAt(10, 10); bgSurface->assertFocusChange(true); bufferSurface->showAt(10, 10); bufferSurface->assertFocusChange(true); bgSurface->assertFocusChange(false); injectTap(11, 11); bufferSurface->expectTap(1, 1); Loading @@ -447,7 +492,10 @@ TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) { std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(10, 10); bgSurface->assertFocusChange(true); fgSurface->showAt(10, 10); bgSurface->assertFocusChange(false); fgSurface->assertFocusChange(true); injectTap(11, 11); fgSurface->expectTap(1, 1); Loading @@ -464,12 +512,17 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { InputSurface::makeContainerInputSurface(mComposerClient, 100, 100); bgSurface->showAt(10, 10); bgSurface->assertFocusChange(true); containerSurface->showAt(10, 10); bgSurface->assertFocusChange(false); containerSurface->assertFocusChange(true); injectTap(11, 11); containerSurface->expectTap(1, 1); containerSurface->doTransaction([](auto &t, auto &sc) { t.hide(sc); }); containerSurface->assertFocusChange(false); bgSurface->assertFocusChange(true); injectTap(11, 11); bgSurface->expectTap(1, 1); Loading @@ -478,6 +531,7 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { TEST_F(InputSurfacesTest, input_respects_outscreen) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(-1, -1); surface->assertFocusChange(true); injectTap(0, 0); surface->expectTap(1, 1); Loading services/inputflinger/dispatcher/Entry.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,21 @@ void DeviceResetEntry::appendDescription(std::string& msg) const { msg += StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x", deviceId, policyFlags); } // --- FocusEntry --- // Focus notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries FocusEntry::FocusEntry(uint32_t sequenceNum, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus) : EventEntry(sequenceNum, Type::FOCUS, eventTime, POLICY_FLAG_PASS_TO_USER), connectionToken(connectionToken), hasFocus(hasFocus) {} FocusEntry::~FocusEntry() {} void FocusEntry::appendDescription(std::string& msg) const { msg += StringPrintf("FocusEvent(hasFocus=%s)", hasFocus ? "true" : "false"); } // --- KeyEntry --- KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source, Loading services/inputflinger/dispatcher/Entry.h +20 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,13 @@ namespace android::inputdispatcher { constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0; struct EventEntry { enum class Type { CONFIGURATION_CHANGED, DEVICE_RESET, KEY, MOTION }; enum class Type { CONFIGURATION_CHANGED, DEVICE_RESET, FOCUS, KEY, MOTION, }; static const char* typeToString(Type type) { switch (type) { Loading @@ -41,6 +47,8 @@ struct EventEntry { return "CONFIGURATION_CHANGED"; case Type::DEVICE_RESET: return "DEVICE_RESET"; case Type::FOCUS: return "FOCUS"; case Type::KEY: return "KEY"; case Type::MOTION: Loading Loading @@ -102,6 +110,17 @@ protected: virtual ~DeviceResetEntry(); }; struct FocusEntry : EventEntry { sp<IBinder> connectionToken; bool hasFocus; FocusEntry(uint32_t sequenceNum, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus); virtual void appendDescription(std::string& msg) const; protected: virtual ~FocusEntry(); }; struct KeyEntry : EventEntry { int32_t deviceId; uint32_t source; Loading services/inputflinger/dispatcher/InputDispatcher.cpp +53 −1 Original line number Diff line number Diff line Loading @@ -530,6 +530,14 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { break; } case EventEntry::Type::FOCUS: { FocusEntry* typedEntry = static_cast<FocusEntry*>(mPendingEvent); dispatchFocusLocked(currentTime, typedEntry); done = true; dropReason = DropReason::NOT_DROPPED; // focus events are never dropped break; } case EventEntry::Type::KEY: { KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent); if (isAppSwitchDue) { Loading Loading @@ -634,7 +642,8 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::FOCUS: { // nothing to do break; } Loading Loading @@ -773,6 +782,7 @@ void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason } break; } case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("Should not drop %s events", EventEntry::typeToString(entry.type)); Loading Loading @@ -933,6 +943,25 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime, DeviceReset return true; } void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) { FocusEntry* focusEntry = new FocusEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, now(), window.getToken(), hasFocus); enqueueInboundEventLocked(focusEntry); } void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) { sp<InputChannel> channel = getInputChannelLocked(entry->connectionToken); if (channel == nullptr) { return; // Window has gone away } InputTarget target; target.inputChannel = channel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; entry->dispatchInProgress = true; dispatchEventLocked(currentTime, entry, {target}); } bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { // Preprocessing. Loading Loading @@ -1315,6 +1344,7 @@ int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) { displayId = motionEntry.displayId; break; } case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { ALOGE("%s events do not have a target display", EventEntry::typeToString(entry.type)); Loading Loading @@ -2062,6 +2092,10 @@ std::string InputDispatcher::getApplicationWindowLabel( } void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { if (eventEntry.type == EventEntry::Type::FOCUS) { // Focus events are passed to apps, but do not represent user activity. return; } int32_t displayId = getTargetDisplayId(eventEntry); sp<InputWindowHandle> focusedWindowHandle = getValueByKey(mFocusedWindowHandlesByDisplay, displayId); Loading Loading @@ -2096,6 +2130,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { eventType = USER_ACTIVITY_EVENT_BUTTON; break; } case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events are not user activity", Loading Loading @@ -2292,6 +2327,9 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio break; } case EventEntry::Type::FOCUS: { break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events should not go to apps", Loading Loading @@ -2427,6 +2465,14 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, reportTouchEventForStatistics(*motionEntry); break; } case EventEntry::Type::FOCUS: { FocusEntry* focusEntry = static_cast<FocusEntry*>(eventEntry); status = connection->inputPublisher.publishFocusEvent(dispatchEntry->seq, focusEntry->hasFocus, mInTouchMode); break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events", Loading Loading @@ -2666,6 +2712,10 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( *cancelationEventEntry)); break; } case EventEntry::Type::FOCUS: { LOG_ALWAYS_FATAL("Canceling focus events is not supported"); break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", Loading Loading @@ -3456,6 +3506,7 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>& CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, "focus left window"); synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options); enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/); } mFocusedWindowHandlesByDisplay.erase(displayId); } Loading @@ -3465,6 +3516,7 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>& newFocusedWindowHandle->getName().c_str(), displayId); } mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle; enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/); } if (mFocusedDisplayId == displayId) { Loading services/inputflinger/dispatcher/InputDispatcher.h +4 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,9 @@ private: // Cleans up input state when dropping an inbound event. void dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) REQUIRES(mLock); // Enqueues a focus event. void enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) REQUIRES(mLock); // Adds an event to a queue of recent events for debugging purposes. void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock); Loading Loading @@ -299,6 +302,7 @@ private: nsecs_t* nextWakeupTime) REQUIRES(mLock); bool dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock); void dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) REQUIRES(mLock); void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry, const std::vector<InputTarget>& inputTargets) REQUIRES(mLock); Loading Loading
libs/gui/tests/EndToEndNativeInputTest.cpp +61 −7 Original line number Diff line number Diff line Loading @@ -112,22 +112,31 @@ public: if (consumed != OK) { return nullptr; } mInputConsumer->sendFinishedSignal(seqId, true); status_t status = mInputConsumer->sendFinishedSignal(seqId, true); EXPECT_EQ(OK, status) << "Could not send finished signal"; return ev; } void assertFocusChange(bool hasFocus) { InputEvent *ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, ev->getType()); FocusEvent *focusEvent = static_cast<FocusEvent *>(ev); EXPECT_EQ(hasFocus, focusEvent->getHasFocus()); } void expectTap(int x, int y) { InputEvent* ev = consumeEvent(); EXPECT_TRUE(ev != nullptr); EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION); ASSERT_NE(ev, nullptr); ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); MotionEvent* mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); EXPECT_EQ(x, mev->getX(0)); EXPECT_EQ(y, mev->getY(0)); ev = consumeEvent(); EXPECT_TRUE(ev != nullptr); EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION); ASSERT_NE(ev, nullptr); ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); } Loading Loading @@ -212,7 +221,7 @@ public: ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); const auto display = mComposerClient->getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); ASSERT_NE(display, nullptr); DisplayInfo info; ASSERT_EQ(NO_ERROR, mComposerClient->getDisplayInfo(display, &info)); Loading Loading @@ -259,18 +268,28 @@ void injectTap(int x, int y) { TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); surface->assertFocusChange(true); injectTap(101, 101); EXPECT_TRUE(surface->consumeEvent() != nullptr); EXPECT_NE(surface->consumeEvent(), nullptr); } /** * Set up two surfaces side-by-side. Tap each surface. * Next, swap the positions of the two surfaces. Inject tap into the two * original locations. Ensure that the tap is received by the surfaces in the * reverse order. */ TEST_F(InputSurfacesTest, input_respects_positioning) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); surface->assertFocusChange(true); std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100); surface2->showAt(200, 200); surface->assertFocusChange(false); surface2->assertFocusChange(true); injectTap(201, 201); surface2->expectTap(1, 1); Loading @@ -297,11 +316,16 @@ TEST_F(InputSurfacesTest, input_respects_layering) { std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100); surface->showAt(10, 10); surface->assertFocusChange(true); surface2->showAt(10, 10); surface->assertFocusChange(false); surface2->assertFocusChange(true); surface->doTransaction([](auto &t, auto &sc) { t.setLayer(sc, LAYER_BASE + 1); }); surface2->assertFocusChange(false); surface->assertFocusChange(true); injectTap(11, 11); surface->expectTap(1, 1); Loading @@ -309,6 +333,8 @@ TEST_F(InputSurfacesTest, input_respects_layering) { surface2->doTransaction([](auto &t, auto &sc) { t.setLayer(sc, LAYER_BASE + 1); }); surface2->assertFocusChange(true); surface->assertFocusChange(false); injectTap(11, 11); surface2->expectTap(1, 1); Loading @@ -316,6 +342,8 @@ TEST_F(InputSurfacesTest, input_respects_layering) { surface2->doTransaction([](auto &t, auto &sc) { t.hide(sc); }); surface2->assertFocusChange(false); surface->assertFocusChange(true); injectTap(11, 11); surface->expectTap(1, 1); Loading @@ -328,9 +356,12 @@ TEST_F(InputSurfacesTest, input_respects_surface_insets) { std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(100, 100); bgSurface->assertFocusChange(true); fgSurface->mInputInfo.surfaceInset = 5; fgSurface->showAt(100, 100); fgSurface->assertFocusChange(true); bgSurface->assertFocusChange(false); injectTap(106, 106); fgSurface->expectTap(1, 1); Loading @@ -344,9 +375,12 @@ TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) { std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> childSurface = makeSurface(100, 100); parentSurface->showAt(100, 100); parentSurface->assertFocusChange(true); childSurface->mInputInfo.surfaceInset = 10; childSurface->showAt(100, 100); childSurface->assertFocusChange(true); parentSurface->assertFocusChange(false); childSurface->doTransaction([&](auto &t, auto &sc) { t.setPosition(sc, -5, -5); Loading @@ -365,9 +399,12 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) { std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(100, 100); bgSurface->assertFocusChange(true); fgSurface->mInputInfo.surfaceInset = 5; fgSurface->showAt(100, 100); bgSurface->assertFocusChange(false); fgSurface->assertFocusChange(true); fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); }); Loading @@ -384,6 +421,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) { // In case we pass the very big inset without any checking. fgSurface->mInputInfo.surfaceInset = INT32_MAX; fgSurface->showAt(100, 100); fgSurface->assertFocusChange(true); fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); Loading @@ -400,6 +438,7 @@ TEST_F(InputSurfacesTest, input_ignores_transparent_region) { t.setTransparentRegionHint(sc, transparentRegion); }); surface->showAt(100, 100); surface->assertFocusChange(true); injectTap(101, 101); surface->expectTap(1, 1); } Loading @@ -414,7 +453,10 @@ TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) { InputSurface::makeBufferInputSurface(mComposerClient, 100, 100); bgSurface->showAt(10, 10); bgSurface->assertFocusChange(true); bufferSurface->showAt(10, 10); bgSurface->assertFocusChange(false); bufferSurface->assertFocusChange(true); injectTap(11, 11); bufferSurface->expectTap(1, 1); Loading @@ -431,7 +473,10 @@ TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) { postBuffer(bufferSurface->mSurfaceControl); bgSurface->showAt(10, 10); bgSurface->assertFocusChange(true); bufferSurface->showAt(10, 10); bufferSurface->assertFocusChange(true); bgSurface->assertFocusChange(false); injectTap(11, 11); bufferSurface->expectTap(1, 1); Loading @@ -447,7 +492,10 @@ TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) { std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(10, 10); bgSurface->assertFocusChange(true); fgSurface->showAt(10, 10); bgSurface->assertFocusChange(false); fgSurface->assertFocusChange(true); injectTap(11, 11); fgSurface->expectTap(1, 1); Loading @@ -464,12 +512,17 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { InputSurface::makeContainerInputSurface(mComposerClient, 100, 100); bgSurface->showAt(10, 10); bgSurface->assertFocusChange(true); containerSurface->showAt(10, 10); bgSurface->assertFocusChange(false); containerSurface->assertFocusChange(true); injectTap(11, 11); containerSurface->expectTap(1, 1); containerSurface->doTransaction([](auto &t, auto &sc) { t.hide(sc); }); containerSurface->assertFocusChange(false); bgSurface->assertFocusChange(true); injectTap(11, 11); bgSurface->expectTap(1, 1); Loading @@ -478,6 +531,7 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { TEST_F(InputSurfacesTest, input_respects_outscreen) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(-1, -1); surface->assertFocusChange(true); injectTap(0, 0); surface->expectTap(1, 1); Loading
services/inputflinger/dispatcher/Entry.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,21 @@ void DeviceResetEntry::appendDescription(std::string& msg) const { msg += StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x", deviceId, policyFlags); } // --- FocusEntry --- // Focus notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries FocusEntry::FocusEntry(uint32_t sequenceNum, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus) : EventEntry(sequenceNum, Type::FOCUS, eventTime, POLICY_FLAG_PASS_TO_USER), connectionToken(connectionToken), hasFocus(hasFocus) {} FocusEntry::~FocusEntry() {} void FocusEntry::appendDescription(std::string& msg) const { msg += StringPrintf("FocusEvent(hasFocus=%s)", hasFocus ? "true" : "false"); } // --- KeyEntry --- KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source, Loading
services/inputflinger/dispatcher/Entry.h +20 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,13 @@ namespace android::inputdispatcher { constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0; struct EventEntry { enum class Type { CONFIGURATION_CHANGED, DEVICE_RESET, KEY, MOTION }; enum class Type { CONFIGURATION_CHANGED, DEVICE_RESET, FOCUS, KEY, MOTION, }; static const char* typeToString(Type type) { switch (type) { Loading @@ -41,6 +47,8 @@ struct EventEntry { return "CONFIGURATION_CHANGED"; case Type::DEVICE_RESET: return "DEVICE_RESET"; case Type::FOCUS: return "FOCUS"; case Type::KEY: return "KEY"; case Type::MOTION: Loading Loading @@ -102,6 +110,17 @@ protected: virtual ~DeviceResetEntry(); }; struct FocusEntry : EventEntry { sp<IBinder> connectionToken; bool hasFocus; FocusEntry(uint32_t sequenceNum, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus); virtual void appendDescription(std::string& msg) const; protected: virtual ~FocusEntry(); }; struct KeyEntry : EventEntry { int32_t deviceId; uint32_t source; Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +53 −1 Original line number Diff line number Diff line Loading @@ -530,6 +530,14 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { break; } case EventEntry::Type::FOCUS: { FocusEntry* typedEntry = static_cast<FocusEntry*>(mPendingEvent); dispatchFocusLocked(currentTime, typedEntry); done = true; dropReason = DropReason::NOT_DROPPED; // focus events are never dropped break; } case EventEntry::Type::KEY: { KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent); if (isAppSwitchDue) { Loading Loading @@ -634,7 +642,8 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::FOCUS: { // nothing to do break; } Loading Loading @@ -773,6 +782,7 @@ void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason } break; } case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("Should not drop %s events", EventEntry::typeToString(entry.type)); Loading Loading @@ -933,6 +943,25 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime, DeviceReset return true; } void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) { FocusEntry* focusEntry = new FocusEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, now(), window.getToken(), hasFocus); enqueueInboundEventLocked(focusEntry); } void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) { sp<InputChannel> channel = getInputChannelLocked(entry->connectionToken); if (channel == nullptr) { return; // Window has gone away } InputTarget target; target.inputChannel = channel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; entry->dispatchInProgress = true; dispatchEventLocked(currentTime, entry, {target}); } bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { // Preprocessing. Loading Loading @@ -1315,6 +1344,7 @@ int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) { displayId = motionEntry.displayId; break; } case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { ALOGE("%s events do not have a target display", EventEntry::typeToString(entry.type)); Loading Loading @@ -2062,6 +2092,10 @@ std::string InputDispatcher::getApplicationWindowLabel( } void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { if (eventEntry.type == EventEntry::Type::FOCUS) { // Focus events are passed to apps, but do not represent user activity. return; } int32_t displayId = getTargetDisplayId(eventEntry); sp<InputWindowHandle> focusedWindowHandle = getValueByKey(mFocusedWindowHandlesByDisplay, displayId); Loading Loading @@ -2096,6 +2130,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { eventType = USER_ACTIVITY_EVENT_BUTTON; break; } case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events are not user activity", Loading Loading @@ -2292,6 +2327,9 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio break; } case EventEntry::Type::FOCUS: { break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events should not go to apps", Loading Loading @@ -2427,6 +2465,14 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, reportTouchEventForStatistics(*motionEntry); break; } case EventEntry::Type::FOCUS: { FocusEntry* focusEntry = static_cast<FocusEntry*>(eventEntry); status = connection->inputPublisher.publishFocusEvent(dispatchEntry->seq, focusEntry->hasFocus, mInTouchMode); break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events", Loading Loading @@ -2666,6 +2712,10 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( *cancelationEventEntry)); break; } case EventEntry::Type::FOCUS: { LOG_ALWAYS_FATAL("Canceling focus events is not supported"); break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", Loading Loading @@ -3456,6 +3506,7 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>& CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, "focus left window"); synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options); enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/); } mFocusedWindowHandlesByDisplay.erase(displayId); } Loading @@ -3465,6 +3516,7 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>& newFocusedWindowHandle->getName().c_str(), displayId); } mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle; enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/); } if (mFocusedDisplayId == displayId) { Loading
services/inputflinger/dispatcher/InputDispatcher.h +4 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,9 @@ private: // Cleans up input state when dropping an inbound event. void dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) REQUIRES(mLock); // Enqueues a focus event. void enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) REQUIRES(mLock); // Adds an event to a queue of recent events for debugging purposes. void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock); Loading Loading @@ -299,6 +302,7 @@ private: nsecs_t* nextWakeupTime) REQUIRES(mLock); bool dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock); void dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) REQUIRES(mLock); void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry, const std::vector<InputTarget>& inputTargets) REQUIRES(mLock); Loading