diff options
Diffstat (limited to 'libs/gui/tests/EndToEndNativeInputTest.cpp')
-rw-r--r-- | libs/gui/tests/EndToEndNativeInputTest.cpp | 214 |
1 files changed, 199 insertions, 15 deletions
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index e9ad011b8e..743c8433cd 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -24,6 +24,7 @@ #include <memory> +#include <android/keycodes.h> #include <android/native_window.h> #include <binder/Binder.h> @@ -37,9 +38,9 @@ #include <gui/SurfaceControl.h> #include <android/os/IInputFlinger.h> +#include <gui/WindowInfo.h> #include <input/Input.h> #include <input/InputTransport.h> -#include <input/InputWindow.h> #include <ui/DisplayMode.h> #include <ui/Rect.h> @@ -49,6 +50,11 @@ using android::os::IInputFlinger; using android::hardware::graphics::common::V1_1::BufferUsage; +using android::gui::FocusRequest; +using android::gui::InputApplicationInfo; +using android::gui::TouchOcclusionMode; +using android::gui::WindowInfo; + namespace android::test { using Transaction = SurfaceComposerClient::Transaction; @@ -115,8 +121,8 @@ public: return std::make_unique<InputSurface>(surfaceControl, width, height); } - InputEvent* consumeEvent() { - waitForEventAvailable(); + InputEvent *consumeEvent(int timeoutMs = 3000) { + waitForEventAvailable(timeoutMs); InputEvent *ev; uint32_t seqId; @@ -177,6 +183,24 @@ public: EXPECT_EQ(flags, mev->getFlags() & flags); } + void expectKey(uint32_t keycode) { + InputEvent *ev = consumeEvent(); + ASSERT_NE(ev, nullptr); + ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType()); + KeyEvent *keyEvent = static_cast<KeyEvent *>(ev); + EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, keyEvent->getAction()); + EXPECT_EQ(keycode, keyEvent->getKeyCode()); + EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS); + + ev = consumeEvent(); + ASSERT_NE(ev, nullptr); + ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType()); + keyEvent = static_cast<KeyEvent *>(ev); + EXPECT_EQ(AMOTION_EVENT_ACTION_UP, keyEvent->getAction()); + EXPECT_EQ(keycode, keyEvent->getKeyCode()); + EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS); + } + virtual ~InputSurface() { mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); } @@ -214,19 +238,19 @@ public: } private: - void waitForEventAvailable() { + void waitForEventAvailable(int timeoutMs) { struct pollfd fd; fd.fd = mClientChannel->getFd(); fd.events = POLLIN; - poll(&fd, 1, 3000); + poll(&fd, 1, timeoutMs); } void populateInputInfo(int width, int height) { mInputInfo.token = mClientChannel->getConnectionToken(); mInputInfo.name = "Test info"; - mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; - mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; + mInputInfo.flags = WindowInfo::Flag::NOT_TOUCH_MODAL; + mInputInfo.type = WindowInfo::Type::BASE_APPLICATION; mInputInfo.dispatchingTimeout = 5s; mInputInfo.globalScaleFactor = 1.0; mInputInfo.focusable = true; @@ -253,7 +277,7 @@ public: std::shared_ptr<InputChannel> mClientChannel; sp<IInputFlinger> mInputFlinger; - InputWindowInfo mInputInfo; + WindowInfo mInputInfo; PreallocatedInputEventFactory mInputEventFactory; InputConsumer* mInputConsumer; @@ -362,6 +386,14 @@ void injectTap(int x, int y) { } } +void injectKey(uint32_t keycode) { + char *buf1; + asprintf(&buf1, "%d", keycode); + if (fork() == 0) { + execlp("input", "input", "keyevent", buf1, NULL); + } +} + TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); @@ -613,6 +645,9 @@ TEST_F(InputSurfacesTest, can_be_focused) { surface->requestFocus(); surface->assertFocusChange(true); + + injectKey(AKEYCODE_V); + surface->expectKey(AKEYCODE_V); } TEST_F(InputSurfacesTest, rotate_surface) { @@ -690,7 +725,7 @@ TEST_F(InputSurfacesTest, touch_flag_obscured) { // Add non touchable window to fully cover touchable window. Window behind gets touch, but // with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); - nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; + nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; nonTouchableSurface->mInputInfo.ownerUid = 22222; // Overriding occlusion mode otherwise the touch would be discarded at InputDispatcher by // the default obscured/untrusted touch filter introduced in S. @@ -710,8 +745,8 @@ TEST_F(InputSurfacesTest, touch_flag_partially_obscured_with_crop) { // AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); - nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; - parentSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; + nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; + parentSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; nonTouchableSurface->mInputInfo.ownerUid = 22222; parentSurface->mInputInfo.ownerUid = 22222; nonTouchableSurface->showAt(0, 0); @@ -734,8 +769,8 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_crop) { // the touchable window. Window behind gets touch with no obscured flags. std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); - nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; - parentSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; + nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; + parentSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; nonTouchableSurface->mInputInfo.ownerUid = 22222; parentSurface->mInputInfo.ownerUid = 22222; nonTouchableSurface->showAt(0, 0); @@ -755,7 +790,7 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_bql) { std::unique_ptr<InputSurface> bufferSurface = InputSurface::makeBufferInputSurface(mComposerClient, 0, 0); - bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; + bufferSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; bufferSurface->mInputInfo.ownerUid = 22222; surface->showAt(10, 10); @@ -770,7 +805,7 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) { std::unique_ptr<BlastInputSurface> bufferSurface = BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0); - bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; + bufferSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; bufferSurface->mInputInfo.ownerUid = 22222; surface->showAt(10, 10); @@ -780,4 +815,153 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) { surface->expectTap(1, 1); } +TEST_F(InputSurfacesTest, strict_unobscured_input_unobscured_window) { + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + surface->doTransaction( + [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); + surface->showAt(100, 100); + + injectTap(101, 101); + + EXPECT_NE(surface->consumeEvent(), nullptr); + EXPECT_NE(surface->consumeEvent(), nullptr); + + surface->requestFocus(); + surface->assertFocusChange(true); + injectKey(AKEYCODE_V); + surface->expectKey(AKEYCODE_V); +} + +TEST_F(InputSurfacesTest, strict_unobscured_input_scaled_without_crop_window) { + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + surface->doTransaction([&](auto &t, auto &sc) { + t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); + t.setMatrix(sc, 2.0, 0, 0, 2.0); + }); + surface->showAt(100, 100); + + injectTap(101, 101); + + EXPECT_NE(surface->consumeEvent(), nullptr); + EXPECT_NE(surface->consumeEvent(), nullptr); + + surface->requestFocus(); + surface->assertFocusChange(true); + injectKey(AKEYCODE_V); + surface->expectKey(AKEYCODE_V); +} + +TEST_F(InputSurfacesTest, strict_unobscured_input_obscured_window) { + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + surface->mInputInfo.ownerUid = 11111; + surface->doTransaction( + [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); + surface->showAt(100, 100); + std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100); + obscuringSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; + obscuringSurface->mInputInfo.ownerUid = 22222; + obscuringSurface->showAt(100, 100); + injectTap(101, 101); + EXPECT_EQ(surface->consumeEvent(100), nullptr); + + surface->requestFocus(); + surface->assertFocusChange(true); + injectKey(AKEYCODE_V); + EXPECT_EQ(surface->consumeEvent(100), nullptr); +} + +TEST_F(InputSurfacesTest, strict_unobscured_input_partially_obscured_window) { + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + surface->mInputInfo.ownerUid = 11111; + surface->doTransaction( + [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); + surface->showAt(100, 100); + std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100); + obscuringSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; + obscuringSurface->mInputInfo.ownerUid = 22222; + obscuringSurface->showAt(190, 190); + + injectTap(101, 101); + + EXPECT_EQ(surface->consumeEvent(100), nullptr); + + surface->requestFocus(); + surface->assertFocusChange(true); + injectKey(AKEYCODE_V); + EXPECT_EQ(surface->consumeEvent(100), nullptr); +} + +TEST_F(InputSurfacesTest, strict_unobscured_input_alpha_window) { + std::unique_ptr<InputSurface> parentSurface = makeSurface(300, 300); + parentSurface->showAt(0, 0, Rect(0, 0, 300, 300)); + + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + surface->showAt(100, 100); + surface->doTransaction([&](auto &t, auto &sc) { + t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); + t.reparent(sc, parentSurface->mSurfaceControl); + t.setAlpha(parentSurface->mSurfaceControl, 0.9f); + }); + + injectTap(101, 101); + + EXPECT_EQ(surface->consumeEvent(100), nullptr); + + surface->requestFocus(); + surface->assertFocusChange(true); + injectKey(AKEYCODE_V); + EXPECT_EQ(surface->consumeEvent(100), nullptr); +} + +TEST_F(InputSurfacesTest, strict_unobscured_input_cropped_window) { + std::unique_ptr<InputSurface> parentSurface = makeSurface(300, 300); + parentSurface->showAt(0, 0, Rect(0, 0, 300, 300)); + + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + surface->doTransaction([&](auto &t, auto &sc) { + t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); + t.reparent(sc, parentSurface->mSurfaceControl); + t.setCrop(parentSurface->mSurfaceControl, Rect(10, 10, 100, 100)); + }); + surface->showAt(100, 100); + + injectTap(111, 111); + + EXPECT_EQ(surface->consumeEvent(100), nullptr); + + surface->requestFocus(); + surface->assertFocusChange(true); + injectKey(AKEYCODE_V); + EXPECT_EQ(surface->consumeEvent(100), nullptr); +} + +TEST_F(InputSurfacesTest, ignore_touch_region_with_zero_sized_blast) { + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + + std::unique_ptr<BlastInputSurface> bufferSurface = + BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0); + + surface->showAt(100, 100); + bufferSurface->mInputInfo.touchableRegion.orSelf(Rect(0, 0, 200, 200)); + bufferSurface->showAt(100, 100, Rect::EMPTY_RECT); + + injectTap(101, 101); + surface->expectTap(1, 1); +} + +TEST_F(InputSurfacesTest, drop_input_policy) { + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + surface->doTransaction( + [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::ALL); }); + surface->showAt(100, 100); + + injectTap(101, 101); + + EXPECT_EQ(surface->consumeEvent(100), nullptr); + + surface->requestFocus(); + surface->assertFocusChange(true); + injectKey(AKEYCODE_V); + EXPECT_EQ(surface->consumeEvent(100), nullptr); +} } // namespace android::test |