Loading services/inputflinger/dispatcher/InputDispatcher.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -4674,11 +4674,13 @@ void InputDispatcher::setInputWindowsLocked( if (wallpaper != nullptr) { sp<Connection> wallpaperConnection = getConnectionLocked(wallpaper->getToken()); if (wallpaperConnection != nullptr) { synthesizeCancelationEventsForConnectionLocked(wallpaperConnection, options); } } } } state.windows.erase(state.windows.begin() + i); } else { ++i; Loading services/inputflinger/tests/InputDispatcher_test.cpp +47 −0 Original line number Diff line number Diff line Loading @@ -1627,6 +1627,53 @@ TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCance wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); } /** * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above, * with the following differences: * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to * clean up the connection. * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful. * Ensure that there's no crash in the dispatcher. */ TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> foregroundWindow = new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT); foregroundWindow->setHasWallpaper(true); sp<FakeWindowHandle> wallpaperWindow = new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT); wallpaperWindow->setType(WindowInfo::Type::WALLPAPER); constexpr int expectedWallpaperFlags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED; mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}}); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {100, 200})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; // Both foreground window and its wallpaper should receive the touch down foregroundWindow->consumeMotionDown(); wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {110, 200})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; foregroundWindow->consumeMotionMove(); wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); // Wallpaper closes its channel, but the window remains. wallpaperWindow->destroyReceiver(); mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token); // Now the foreground window goes away, but the wallpaper stays, even though its channel // is no longer valid. mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}}); foregroundWindow->consumeMotionCancel(); } /** * A single window that receives touch (on top), and a wallpaper window underneath it. * The top window gets a multitouch gesture. Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -4674,11 +4674,13 @@ void InputDispatcher::setInputWindowsLocked( if (wallpaper != nullptr) { sp<Connection> wallpaperConnection = getConnectionLocked(wallpaper->getToken()); if (wallpaperConnection != nullptr) { synthesizeCancelationEventsForConnectionLocked(wallpaperConnection, options); } } } } state.windows.erase(state.windows.begin() + i); } else { ++i; Loading
services/inputflinger/tests/InputDispatcher_test.cpp +47 −0 Original line number Diff line number Diff line Loading @@ -1627,6 +1627,53 @@ TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCance wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); } /** * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above, * with the following differences: * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to * clean up the connection. * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful. * Ensure that there's no crash in the dispatcher. */ TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> foregroundWindow = new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT); foregroundWindow->setHasWallpaper(true); sp<FakeWindowHandle> wallpaperWindow = new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT); wallpaperWindow->setType(WindowInfo::Type::WALLPAPER); constexpr int expectedWallpaperFlags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED; mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}}); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {100, 200})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; // Both foreground window and its wallpaper should receive the touch down foregroundWindow->consumeMotionDown(); wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {110, 200})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; foregroundWindow->consumeMotionMove(); wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); // Wallpaper closes its channel, but the window remains. wallpaperWindow->destroyReceiver(); mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token); // Now the foreground window goes away, but the wallpaper stays, even though its channel // is no longer valid. mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}}); foregroundWindow->consumeMotionCancel(); } /** * A single window that receives touch (on top), and a wallpaper window underneath it. * The top window gets a multitouch gesture. Loading