Skip to content

Commit 35bb1fe

Browse files
Linnan LiCherrypicker Worker
authored andcommitted
Add the tests related with obscured flags
Currently, only touch events have implemented the FLAG_WINDOW_IS_OBSCURED and FLAG_WINDOW_IS_PARTIALLY_OBSCURED flags. For hover events, we have not implemented these flags. Since hover events are also motion events, we need to implement these two flags for the dispatching of hover events as well. Here, we will first add a test to simulate this situation. The next issues we need to address are: - For completely obscured situations, we need to add the FLAG_WINDOW_IS_OBSCURED flag for hover events. - For partially obscured situations, we need to add the FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag for hover events. - If the window has already received a HOVER_ENTER event, and the mouse pointer's hover event moves to a position where no window exists, we need to supplement the window with a HOVER_EXIT event. Bug: 328160937 Test: atest inputflinger_tests Flag: TEST_ONLY Signed-off-by: Linnan Li <lilinnan@xiaomi.corp-partner.google.com> (cherry picked from https://partner-android-review.googlesource.com/q/commit:4142c41bedbfd1246ee76ce9ff7036e244276831) Merged-In: I2f0999d4b4e5a55abe81886553843bfa79170167 Change-Id: I2f0999d4b4e5a55abe81886553843bfa79170167
1 parent 1da7821 commit 35bb1fe

1 file changed

Lines changed: 220 additions & 1 deletion

File tree

services/inputflinger/tests/InputDispatcher_test.cpp

Lines changed: 220 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,12 @@ static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
117117
// An arbitrary pid of the gesture monitor window
118118
static constexpr gui::Pid MONITOR_PID{2001};
119119

120+
static constexpr int32_t FLAG_WINDOW_IS_OBSCURED = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
121+
static constexpr int32_t FLAG_WINDOW_IS_PARTIALLY_OBSCURED =
122+
AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
123+
120124
static constexpr int EXPECTED_WALLPAPER_FLAGS =
121-
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
125+
FLAG_WINDOW_IS_OBSCURED | FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
122126

123127
using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
124128

@@ -14684,4 +14688,219 @@ TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
1468414688
mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
1468514689
}
1468614690

14691+
class InputDispatcherObscuredFlagTest : public InputDispatcherTest {
14692+
protected:
14693+
std::shared_ptr<FakeApplicationHandle> mApplication;
14694+
std::shared_ptr<FakeApplicationHandle> mOcclusionApplication;
14695+
sp<FakeWindowHandle> mWindow;
14696+
sp<FakeWindowHandle> mOcclusionWindow;
14697+
14698+
void SetUp() override {
14699+
InputDispatcherTest::SetUp();
14700+
mDispatcher->setMaximumObscuringOpacityForTouch(0.8f);
14701+
mApplication = std::make_shared<FakeApplicationHandle>();
14702+
mOcclusionApplication = std::make_shared<FakeApplicationHandle>();
14703+
mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Window", DISPLAY_ID);
14704+
mWindow->setOwnerInfo(WINDOW_PID, WINDOW_UID);
14705+
14706+
mOcclusionWindow = sp<FakeWindowHandle>::make(mOcclusionApplication, mDispatcher,
14707+
"Occlusion Window", DISPLAY_ID);
14708+
14709+
mOcclusionWindow->setTouchable(false);
14710+
mOcclusionWindow->setTouchOcclusionMode(TouchOcclusionMode::USE_OPACITY);
14711+
mOcclusionWindow->setAlpha(0.7f);
14712+
mOcclusionWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
14713+
}
14714+
};
14715+
14716+
/**
14717+
* Two windows. An untouchable window partially occludes a touchable region below it.
14718+
* Use a finger to touch the bottom window.
14719+
* When the finger touches down in the obscured area, the motion event should always have the
14720+
* FLAG_WINDOW_IS_OBSCURED flag, regardless of where it is moved to. If it starts from a
14721+
* non-obscured area, the motion event should always with a FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag,
14722+
* regardless of where it is moved to.
14723+
*/
14724+
TEST_F(InputDispatcherObscuredFlagTest, TouchObscuredTest) {
14725+
mWindow->setFrame({0, 0, 100, 100});
14726+
mOcclusionWindow->setFrame({0, 0, 100, 50});
14727+
14728+
mDispatcher->onWindowInfosChanged(
14729+
{{*mOcclusionWindow->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
14730+
14731+
// If the finger touch goes down in the region that is obscured.
14732+
// Expect the entire stream to use FLAG_WINDOW_IS_OBSCURED.
14733+
mDispatcher->notifyMotion(
14734+
MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14735+
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(10))
14736+
.build());
14737+
14738+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
14739+
WithFlags(FLAG_WINDOW_IS_OBSCURED),
14740+
WithDisplayId(DISPLAY_ID)));
14741+
14742+
mDispatcher->notifyMotion(
14743+
MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
14744+
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(60))
14745+
.build());
14746+
14747+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
14748+
WithFlags(FLAG_WINDOW_IS_OBSCURED),
14749+
WithDisplayId(DISPLAY_ID)));
14750+
14751+
mDispatcher->notifyMotion(
14752+
MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
14753+
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(110))
14754+
.build());
14755+
14756+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP),
14757+
WithFlags(FLAG_WINDOW_IS_OBSCURED),
14758+
WithDisplayId(DISPLAY_ID)));
14759+
}
14760+
14761+
/**
14762+
* Two windows. An untouchable window partially occludes a touchable region below it.
14763+
* Use a finger to touch the bottom window.
14764+
* When the finger starts from a non-obscured area, the motion event should always have the
14765+
* FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag, regardless of where it is moved to.
14766+
*/
14767+
TEST_F(InputDispatcherObscuredFlagTest, TouchPartiallyObscuredTest) {
14768+
mWindow->setFrame({0, 0, 100, 100});
14769+
mOcclusionWindow->setFrame({0, 0, 100, 50});
14770+
14771+
mDispatcher->onWindowInfosChanged(
14772+
{{*mOcclusionWindow->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
14773+
14774+
// If the finger touch goes down in the region that is not directly obscured by the overlay.
14775+
// Expect the entire stream to use FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
14776+
mDispatcher->notifyMotion(
14777+
MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14778+
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(60))
14779+
.build());
14780+
14781+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
14782+
WithFlags(FLAG_WINDOW_IS_PARTIALLY_OBSCURED),
14783+
WithDisplayId(DISPLAY_ID)));
14784+
14785+
mDispatcher->notifyMotion(
14786+
MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
14787+
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(80))
14788+
.build());
14789+
14790+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
14791+
WithFlags(FLAG_WINDOW_IS_PARTIALLY_OBSCURED),
14792+
WithDisplayId(DISPLAY_ID)));
14793+
14794+
mDispatcher->notifyMotion(
14795+
MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
14796+
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(110))
14797+
.build());
14798+
14799+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP),
14800+
WithFlags(FLAG_WINDOW_IS_PARTIALLY_OBSCURED),
14801+
WithDisplayId(DISPLAY_ID)));
14802+
}
14803+
14804+
/**
14805+
* Two windows. An untouchable window partially occludes a touchable region below it.
14806+
* Use the mouse to hover over the bottom window.
14807+
* When the hover happens over the occluded area, the window below should receive a motion
14808+
* event with the FLAG_WINDOW_IS_OBSCURED flag. When the hover event moves to the non-occluded area,
14809+
* the window below should receive a motion event with the FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag.
14810+
*/
14811+
TEST_F(InputDispatcherObscuredFlagTest, MouseHoverObscuredTest) {
14812+
mWindow->setFrame({0, 0, 100, 100});
14813+
mOcclusionWindow->setFrame({0, 0, 100, 40});
14814+
14815+
mDispatcher->onWindowInfosChanged(
14816+
{{*mOcclusionWindow->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
14817+
14818+
// TODO(b/328160937): The window should receive a motion event with the FLAG_WINDOW_IS_OBSCURED
14819+
// flag.
14820+
mDispatcher->notifyMotion(
14821+
MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14822+
.pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(20))
14823+
.build());
14824+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithFlags(0)));
14825+
14826+
mDispatcher->notifyMotion(
14827+
MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14828+
.pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(30))
14829+
.build());
14830+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
14831+
14832+
// TODO(b/328160937): The window should receive a motion event with the
14833+
// FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag.
14834+
mDispatcher->notifyMotion(
14835+
MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14836+
.pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14837+
.build());
14838+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
14839+
14840+
mDispatcher->notifyMotion(
14841+
MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14842+
.pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(60))
14843+
.build());
14844+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
14845+
14846+
mDispatcher->notifyMotion(
14847+
MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14848+
.pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(110))
14849+
.build());
14850+
14851+
// TODO(b/328160937): The window should receive a HOVER_EXIT with the
14852+
// FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag. The cause of the current issue is that we moved the
14853+
// mouse to a location where there are no windows, so the HOVER_EXIT event cannot be generated.
14854+
mWindow->assertNoEvents();
14855+
}
14856+
14857+
/**
14858+
* Two windows. An untouchable window partially occludes a touchable region below it.
14859+
* Use the stylus to hover over the bottom window.
14860+
* When the hover happens over the occluded area, the window below should receive a motion
14861+
* event with the FLAG_WINDOW_IS_OBSCURED flag. When the hover event moves to the non-occluded area,
14862+
* the window below should receive a motion event with the FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag.
14863+
*/
14864+
TEST_F(InputDispatcherObscuredFlagTest, StylusHoverObscuredTest) {
14865+
mWindow->setFrame({0, 0, 100, 100});
14866+
mOcclusionWindow->setFrame({0, 0, 100, 40});
14867+
14868+
mDispatcher->onWindowInfosChanged(
14869+
{{*mOcclusionWindow->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
14870+
14871+
// TODO(b/328160937): The window should receive a motion event with the FLAG_WINDOW_IS_OBSCURED
14872+
// flag.
14873+
mDispatcher->notifyMotion(
14874+
MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
14875+
.pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(20))
14876+
.build());
14877+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithFlags(0)));
14878+
14879+
mDispatcher->notifyMotion(
14880+
MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
14881+
.pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(30))
14882+
.build());
14883+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
14884+
14885+
// TODO(b/328160937): The window should receive a motion event with the
14886+
// FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag.
14887+
mDispatcher->notifyMotion(
14888+
MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
14889+
.pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
14890+
.build());
14891+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
14892+
14893+
mDispatcher->notifyMotion(
14894+
MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
14895+
.pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(60))
14896+
.build());
14897+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
14898+
14899+
mDispatcher->notifyMotion(
14900+
MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
14901+
.pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(70))
14902+
.build());
14903+
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithFlags(0)));
14904+
}
14905+
1468714906
} // namespace android::inputdispatcher

0 commit comments

Comments
 (0)