summaryrefslogtreecommitdiff
path: root/services/inputflinger/tests/InputDispatcher_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/inputflinger/tests/InputDispatcher_test.cpp')
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp552
1 files changed, 452 insertions, 100 deletions
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 0f446532ca..eca6ebc1f5 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -29,9 +29,12 @@
#include <vector>
using android::base::StringPrintf;
+using android::gui::FocusRequest;
+using android::gui::TouchOcclusionMode;
+using android::gui::WindowInfo;
+using android::gui::WindowInfoHandle;
using android::os::InputEventInjectionResult;
using android::os::InputEventInjectionSync;
-using android::os::TouchOcclusionMode;
using namespace android::flag_operators;
namespace android::inputdispatcher {
@@ -43,7 +46,8 @@ static const nsecs_t ARBITRARY_TIME = 1234;
static const int32_t DEVICE_ID = 1;
// An arbitrary display id.
-static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
+static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
+static constexpr int32_t SECOND_DISPLAY_ID = 1;
// An arbitrary injector pid / uid pair that has permission to inject events.
static const int32_t INJECTOR_PID = 999;
@@ -473,8 +477,8 @@ protected:
}
}
- void setFocusedWindow(const sp<InputWindowHandle>& window,
- const sp<InputWindowHandle>& focusedWindow = nullptr) {
+ void setFocusedWindow(const sp<WindowInfoHandle>& window,
+ const sp<WindowInfoHandle>& focusedWindow = nullptr) {
FocusRequest request;
request.token = window->getToken();
request.windowName = window->getName();
@@ -531,8 +535,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
/*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
+ INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -545,9 +549,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
(1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
- pointerCoords);
+ ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
InputEventInjectionSync::NONE, 0ms, 0))
@@ -558,9 +562,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
(~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
- pointerCoords);
+ ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
InputEventInjectionSync::NONE, 0ms, 0))
@@ -572,9 +576,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
(1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
- pointerCoords);
+ ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
InputEventInjectionSync::NONE, 0ms, 0))
@@ -585,9 +589,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
(~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
- pointerCoords);
+ ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
InputEventInjectionSync::NONE, 0ms, 0))
@@ -597,8 +601,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
+ INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -608,8 +612,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
+ INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -621,8 +625,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
+ INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -633,8 +637,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
+ INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -647,8 +651,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
- AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
+ INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -899,7 +903,7 @@ protected:
std::string mName;
};
-class FakeWindowHandle : public InputWindowHandle {
+class FakeWindowHandle : public WindowInfoHandle {
public:
static const int32_t WIDTH = 600;
static const int32_t HEIGHT = 800;
@@ -921,7 +925,7 @@ public:
mInfo.token = *token;
mInfo.id = sId++;
mInfo.name = name;
- mInfo.type = InputWindowInfo::Type::APPLICATION;
+ mInfo.type = WindowInfo::Type::APPLICATION;
mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
mInfo.alpha = 1.0;
mInfo.frameLeft = 0;
@@ -941,7 +945,14 @@ public:
mInfo.displayId = displayId;
}
- virtual bool updateInfo() { return true; }
+ sp<FakeWindowHandle> clone(
+ const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
+ const sp<InputDispatcher>& dispatcher, int32_t displayId) {
+ sp<FakeWindowHandle> handle =
+ new FakeWindowHandle(inputApplicationHandle, dispatcher, mInfo.name + "(Mirror)",
+ displayId, mInfo.token);
+ return handle;
+ }
void setFocusable(bool focusable) { mInfo.focusable = focusable; }
@@ -955,9 +966,7 @@ public:
void setAlpha(float alpha) { mInfo.alpha = alpha; }
- void setTouchOcclusionMode(android::os::TouchOcclusionMode mode) {
- mInfo.touchOcclusionMode = mode;
- }
+ void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
@@ -971,11 +980,11 @@ public:
mInfo.addTouchableRegion(frame);
}
- void addFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags |= flags; }
+ void addFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags |= flags; }
- void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
+ void setFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags = flags; }
- void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
+ void setInputFeatures(WindowInfo::Feature features) { mInfo.inputFeatures = features; }
void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
@@ -1109,7 +1118,7 @@ public:
void assertNoEvents() {
if (mInputReceiver == nullptr &&
- mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
+ mInfo.inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL)) {
return; // Can't receive events if the window does not have input channel
}
ASSERT_NE(nullptr, mInputReceiver)
@@ -1274,8 +1283,9 @@ public:
mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
mButtonState, MotionClassification::NONE, identityTransform,
/* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
- mRawYCursorPosition, mDisplayWidth, mDisplayHeight, mEventTime, mEventTime,
- mPointers.size(), pointerProperties.data(), pointerCoords.data());
+ mRawYCursorPosition, mDisplayOrientation, mDisplayWidth, mDisplayHeight,
+ mEventTime, mEventTime, mPointers.size(), pointerProperties.data(),
+ pointerCoords.data());
return event;
}
@@ -1290,8 +1300,9 @@ private:
int32_t mFlags{0};
float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
- int32_t mDisplayWidth{AMOTION_EVENT_INVALID_DISPLAY_SIZE};
- int32_t mDisplayHeight{AMOTION_EVENT_INVALID_DISPLAY_SIZE};
+ uint32_t mDisplayOrientation{ui::Transform::ROT_0};
+ int32_t mDisplayWidth{INVALID_DISPLAY_SIZE};
+ int32_t mDisplayHeight{INVALID_DISPLAY_SIZE};
std::vector<PointerBuilder> mPointers;
};
@@ -1418,7 +1429,7 @@ TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFrame(Rect(0, 0, 100, 100));
- window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -1441,7 +1452,7 @@ TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFrame(Rect(0, 0, 100, 100));
- window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -1477,11 +1488,11 @@ TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
sp<FakeWindowHandle> windowLeft =
new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
windowLeft->setFrame(Rect(0, 0, 600, 800));
- windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
sp<FakeWindowHandle> windowRight =
new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
windowRight->setFrame(Rect(600, 0, 1200, 800));
- windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -1588,7 +1599,7 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
window->setFrame(Rect(0, 0, 1200, 800));
- window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -1670,11 +1681,11 @@ TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
sp<FakeWindowHandle> windowLeft =
new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
windowLeft->setFrame(Rect(0, 0, 600, 800));
- windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
sp<FakeWindowHandle> windowRight =
new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
windowRight->setFrame(Rect(600, 0, 1200, 800));
- windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -1868,15 +1879,13 @@ TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
sp<FakeWindowHandle> firstWindow =
new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
firstWindow->setFrame(Rect(0, 0, 600, 400));
- firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
// Create a non touch modal window that supports split touch
sp<FakeWindowHandle> secondWindow =
new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
secondWindow->setFrame(Rect(0, 400, 600, 800));
- secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
// Add the windows to the dispatcher
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
@@ -1942,15 +1951,13 @@ TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
sp<FakeWindowHandle> firstWindow =
new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
firstWindow->setFrame(Rect(0, 0, 600, 400));
- firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
// Create a non touch modal window that supports split touch
sp<FakeWindowHandle> secondWindow =
new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
secondWindow->setFrame(Rect(0, 400, 600, 800));
- secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
// Add the windows to the dispatcher
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
@@ -2007,6 +2014,134 @@ TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
secondWindow->assertNoEvents();
}
+// This case will create two windows and one mirrored window on the default display and mirror
+// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
+// the windows info of second display before default display.
+TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> firstWindowInPrimary =
+ new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
+ firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
+ firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+ sp<FakeWindowHandle> secondWindowInPrimary =
+ new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
+ secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
+ secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ sp<FakeWindowHandle> mirrorWindowInPrimary =
+ firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
+ mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
+ mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ sp<FakeWindowHandle> firstWindowInSecondary =
+ firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
+ firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
+ firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ sp<FakeWindowHandle> secondWindowInSecondary =
+ secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
+ secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
+ secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ // Update window info, let it find window handle of second display first.
+ mDispatcher->setInputWindows(
+ {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
+ {ADISPLAY_ID_DEFAULT,
+ {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {50, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ // Window should receive motion event.
+ firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+
+ // Transfer touch focus
+ ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
+ secondWindowInPrimary->getToken()));
+ // The first window gets cancel.
+ firstWindowInPrimary->consumeMotionCancel();
+ secondWindowInPrimary->consumeMotionDown();
+
+ 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";
+ firstWindowInPrimary->assertNoEvents();
+ secondWindowInPrimary->consumeMotionMove();
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {150, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ firstWindowInPrimary->assertNoEvents();
+ secondWindowInPrimary->consumeMotionUp();
+}
+
+// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
+// 'transferTouch' api.
+TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> firstWindowInPrimary =
+ new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
+ firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
+ firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+ sp<FakeWindowHandle> secondWindowInPrimary =
+ new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
+ secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
+ secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ sp<FakeWindowHandle> mirrorWindowInPrimary =
+ firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
+ mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
+ mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ sp<FakeWindowHandle> firstWindowInSecondary =
+ firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
+ firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
+ firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ sp<FakeWindowHandle> secondWindowInSecondary =
+ secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
+ secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
+ secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ // Update window info, let it find window handle of second display first.
+ mDispatcher->setInputWindows(
+ {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
+ {ADISPLAY_ID_DEFAULT,
+ {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
+
+ // Touch on second display.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ // Window should receive motion event.
+ firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
+
+ // Transfer touch focus
+ ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken()));
+
+ // The first window gets cancel.
+ firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
+ secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ SECOND_DISPLAY_ID, {150, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ firstWindowInPrimary->assertNoEvents();
+ secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ firstWindowInPrimary->assertNoEvents();
+ secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
+}
+
TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
@@ -2068,15 +2203,13 @@ TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
sp<FakeWindowHandle> firstWindow =
new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
firstWindow->setFrame(Rect(0, 0, 600, 400));
- firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
// Create second non touch modal window that supports split touch
sp<FakeWindowHandle> secondWindow =
new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
secondWindow->setFrame(Rect(0, 400, 600, 800));
- secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
// Add the windows to the dispatcher
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
@@ -2171,6 +2304,18 @@ public:
expectedDisplayId, expectedFlags);
}
+ void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+ mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
+ expectedDisplayId, expectedFlags);
+ }
+
+ void consumeMotionPointerDown(int32_t pointerIdx) {
+ int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
+ (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
+ 0 /*expectedFlags*/);
+ }
+
MotionEvent* consumeMotion() {
InputEvent* event = mInputReceiver->consume();
if (!event) {
@@ -2317,6 +2462,91 @@ TEST_F(InputDispatcherTest, TestMoveEvent) {
0 /*expectedFlags*/);
}
+TEST_F(InputDispatcherTest, GestureMonitor_SplitIfNoWindowTouched) {
+ FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
+ true /*isGestureMonitor*/);
+
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ // Create a non touch modal window that supports split touch
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
+ window->setFrame(Rect(0, 0, 100, 100));
+ window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ // First finger down, no window touched.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {100, 200}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ window->assertNoEvents();
+
+ // Second finger down on window, the window should receive touch down.
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
+ (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(100)
+ .y(200))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ monitor.consumeMotionPointerDown(1 /* pointerIndex */);
+}
+
+TEST_F(InputDispatcherTest, GestureMonitor_NoSplitAfterPilfer) {
+ FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
+ true /*isGestureMonitor*/);
+
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ // Create a non touch modal window that supports split touch
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
+ window->setFrame(Rect(0, 0, 100, 100));
+ window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ // First finger down, no window touched.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {100, 200}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ window->assertNoEvents();
+
+ // Gesture monitor pilfer the pointers.
+ mDispatcher->pilferPointers(monitor.getToken());
+
+ // Second finger down on window, the window should not receive touch down.
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
+ (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(100)
+ .y(200))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ window->assertNoEvents();
+ monitor.consumeMotionPointerDown(1 /* pointerIndex */);
+}
+
/**
* Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
* the device default right away. In the test scenario, we check both the default value,
@@ -2440,7 +2670,7 @@ TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
}
-TEST_F(InputDispatcherTest, NonPointerMotionEvent_NotTransformed) {
+TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickAndTouchpadNotTransformed) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
@@ -2460,20 +2690,19 @@ TEST_F(InputDispatcherTest, NonPointerMotionEvent_NotTransformed) {
// Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
window->consumeFocusEvent(true);
- constexpr const std::array nonPointerSources = {AINPUT_SOURCE_TRACKBALL,
- AINPUT_SOURCE_MOUSE_RELATIVE,
- AINPUT_SOURCE_JOYSTICK};
- for (const int source : nonPointerSources) {
- // Notify motion with a non-pointer source.
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, source, ADISPLAY_ID_DEFAULT);
+ constexpr const std::array nonTransformedSources = {std::pair(AINPUT_SOURCE_TOUCHPAD,
+ AMOTION_EVENT_ACTION_DOWN),
+ std::pair(AINPUT_SOURCE_JOYSTICK,
+ AMOTION_EVENT_ACTION_MOVE)};
+ for (const auto& [source, action] : nonTransformedSources) {
+ const NotifyMotionArgs motionArgs = generateMotionArgs(action, source, ADISPLAY_ID_DEFAULT);
mDispatcher->notifyMotion(&motionArgs);
MotionEvent* event = window->consumeMotion();
ASSERT_NE(event, nullptr);
const MotionEvent& motionEvent = *event;
- EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, motionEvent.getAction());
+ EXPECT_EQ(action, motionEvent.getAction());
EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
float expectedX = motionArgs.pointerCoords[0].getX();
@@ -2745,8 +2974,7 @@ TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
sp<FakeWindowHandle> slipperyExitWindow =
new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
- slipperyExitWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SLIPPERY);
+ slipperyExitWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SLIPPERY);
// Make sure this one overlaps the bottom window
slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
// Change the owner uid/pid of the window so that it is considered to be occluding the bottom
@@ -2921,7 +3149,6 @@ TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEvent
/* Test InputDispatcher for MultiDisplay */
class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
public:
- static constexpr int32_t SECOND_DISPLAY_ID = 1;
virtual void SetUp() override {
InputDispatcherTest::SetUp();
@@ -3084,8 +3311,6 @@ TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay)
class InputFilterTest : public InputDispatcherTest {
protected:
- static constexpr int32_t SECOND_DISPLAY_ID = 1;
-
void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
NotifyMotionArgs motionArgs;
@@ -3219,9 +3444,9 @@ protected:
DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
- 0 /*AMOTION_EVENT_INVALID_DISPLAY_SIZE*/,
- 0 /*AMOTION_EVENT_INVALID_DISPLAY_SIZE*/, eventTime, eventTime,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
+ 0 /*INVALID_DISPLAY_SIZE*/, 0 /*INVALID_DISPLAY_SIZE*/, eventTime,
+ eventTime,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
@@ -3279,12 +3504,12 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
// Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
// window.
- mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
mFocusedWindow =
new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
- mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
// Set focused application.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -3393,14 +3618,12 @@ class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
ADISPLAY_ID_DEFAULT);
// Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
// We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
- mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ mWindow1->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
mWindow1->setFrame(Rect(0, 0, 100, 100));
mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
ADISPLAY_ID_DEFAULT, mWindow1->getToken());
- mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ mWindow2->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
mWindow2->setFrame(Rect(100, 100, 200, 200));
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
@@ -3411,7 +3634,7 @@ protected:
sp<FakeWindowHandle> mWindow2;
// Helper function to convert the point from screen coordinates into the window's space
- static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
+ static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
vec2 vals = windowInfo->transform.transform(point.x, point.y);
return {vals.x, vals.y};
}
@@ -3599,7 +3822,7 @@ class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
mWindow->setFocusable(true);
// Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
// window.
- mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
// Set focused application.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
@@ -4000,16 +4223,15 @@ class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
// Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
// window.
// Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
- mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL |
+ WindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
+ WindowInfo::Flag::SPLIT_TOUCH);
mFocusedWindow =
new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
mFocusedWindow->setDispatchingTimeout(30ms);
mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
- mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
- InputWindowInfo::Flag::SPLIT_TOUCH);
+ mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
// Set focused application.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
@@ -4377,7 +4599,7 @@ class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
"Window without input channel", ADISPLAY_ID_DEFAULT,
std::make_optional<sp<IBinder>>(nullptr) /*token*/);
- mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
+ mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
// It's perfectly valid for this window to not have an associated input channel
@@ -4419,7 +4641,7 @@ TEST_F(InputDispatcherMultiWindowOcclusionTests,
"Window with input channel and NO_INPUT_CHANNEL",
ADISPLAY_ID_DEFAULT);
- mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
+ mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
@@ -4740,10 +4962,10 @@ protected:
mTouchWindow.clear();
}
- sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name,
- os::TouchOcclusionMode mode, float alpha = 1.0f) {
+ sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
+ float alpha = 1.0f) {
sp<FakeWindowHandle> window = getWindow(uid, name);
- window->setFlags(InputWindowInfo::Flag::NOT_TOUCHABLE);
+ window->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
window->setTouchOcclusionMode(mode);
window->setAlpha(alpha);
return window;
@@ -4857,7 +5079,7 @@ TEST_F(InputDispatcherUntrustedTouchesTest,
WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
const sp<FakeWindowHandle>& w =
getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
- w->addFlags(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
+ w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
touch();
@@ -4868,7 +5090,7 @@ TEST_F(InputDispatcherUntrustedTouchesTest,
TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
const sp<FakeWindowHandle>& w =
getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
- w->addFlags(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
+ w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
touch();
@@ -5122,11 +5344,11 @@ protected:
mApp = std::make_shared<FakeApplicationHandle>();
mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
mWindow->setFrame(Rect(0, 0, 100, 100));
- mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
mSecondWindow->setFrame(Rect(100, 0, 200, 100));
- mSecondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ mSecondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
@@ -5334,4 +5556,134 @@ TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
mSecondWindow->assertNoEvents();
}
+class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
+
+TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+ window->setInputFeatures(WindowInfo::Feature::DROP_INPUT);
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+ window->setFocusable(true);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+ setFocusedWindow(window);
+ window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
+
+ // With the flag set, window should not get any input
+ NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(&keyArgs);
+ window->assertNoEvents();
+
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+ window->assertNoEvents();
+
+ // With the flag cleared, the window should get input
+ window->setInputFeatures({});
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(&keyArgs);
+ window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+
+ motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ window->assertNoEvents();
+}
+
+TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
+ std::shared_ptr<FakeApplicationHandle> obscuringApplication =
+ std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> obscuringWindow =
+ new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
+ ADISPLAY_ID_DEFAULT);
+ obscuringWindow->setFrame(Rect(0, 0, 50, 50));
+ obscuringWindow->setOwnerInfo(111, 111);
+ obscuringWindow->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+ window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
+ window->setOwnerInfo(222, 222);
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+ window->setFocusable(true);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
+ setFocusedWindow(window);
+ window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
+
+ // With the flag set, window should not get any input
+ NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(&keyArgs);
+ window->assertNoEvents();
+
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+ window->assertNoEvents();
+
+ // With the flag cleared, the window should get input
+ window->setInputFeatures({});
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
+
+ keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(&keyArgs);
+ window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+
+ motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
+ window->assertNoEvents();
+}
+
+TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
+ std::shared_ptr<FakeApplicationHandle> obscuringApplication =
+ std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> obscuringWindow =
+ new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
+ ADISPLAY_ID_DEFAULT);
+ obscuringWindow->setFrame(Rect(0, 0, 50, 50));
+ obscuringWindow->setOwnerInfo(111, 111);
+ obscuringWindow->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+ window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
+ window->setOwnerInfo(222, 222);
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+ window->setFocusable(true);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
+ setFocusedWindow(window);
+ window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
+
+ // With the flag set, window should not get any input
+ NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(&keyArgs);
+ window->assertNoEvents();
+
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+ window->assertNoEvents();
+
+ // When the window is no longer obscured because it went on top, it should get input
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
+
+ keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(&keyArgs);
+ window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+
+ motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ window->assertNoEvents();
+}
+
} // namespace android::inputdispatcher