blob: b4d7608770841aebbc9f796d721b52fd242debf1 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Robert Carr803535b2018-08-02 16:38:15 -070019#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080020#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070021
Michael Wrightd02c5b62014-02-10 15:10:22 -080022#include <gtest/gtest.h>
23#include <linux/input.h>
chaviwd1c23182019-12-20 18:44:56 -080024#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080025
Garfield Tane84e6f92019-08-29 17:28:41 -070026namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080027
28// An arbitrary time value.
29static const nsecs_t ARBITRARY_TIME = 1234;
30
31// An arbitrary device id.
32static const int32_t DEVICE_ID = 1;
33
Jeff Brownf086ddb2014-02-11 14:28:48 -080034// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080035static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080036
Michael Wrightd02c5b62014-02-10 15:10:22 -080037// An arbitrary injector pid / uid pair that has permission to inject events.
38static const int32_t INJECTOR_PID = 999;
39static const int32_t INJECTOR_UID = 1001;
40
chaviwd1c23182019-12-20 18:44:56 -080041struct PointF {
42 float x;
43 float y;
44};
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
46// --- FakeInputDispatcherPolicy ---
47
48class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
49 InputDispatcherConfiguration mConfig;
50
51protected:
52 virtual ~FakeInputDispatcherPolicy() {
53 }
54
55public:
56 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080057 }
58
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080059 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080060 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
61 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080062 }
63
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080064 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080065 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
66 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080067 }
68
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080069 void assertFilterInputEventWasNotCalled() { ASSERT_EQ(nullptr, mFilteredEvent); }
Michael Wrightd02c5b62014-02-10 15:10:22 -080070
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080071 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
72 ASSERT_TRUE(mConfigurationChangedTime)
73 << "Timed out waiting for configuration changed call";
74 ASSERT_EQ(*mConfigurationChangedTime, when);
75 mConfigurationChangedTime = std::nullopt;
76 }
77
78 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
79 ASSERT_TRUE(mLastNotifySwitch);
80 // We do not check sequenceNum because it is not exposed to the policy
81 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
82 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
83 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
84 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
85 mLastNotifySwitch = std::nullopt;
86 }
87
chaviwfd6d3512019-03-25 13:23:49 -070088 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080089 ASSERT_EQ(touchedToken, mOnPointerDownToken);
90 mOnPointerDownToken.clear();
91 }
92
93 void assertOnPointerDownWasNotCalled() {
94 ASSERT_TRUE(mOnPointerDownToken == nullptr)
95 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -070096 }
97
Michael Wrightd02c5b62014-02-10 15:10:22 -080098private:
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080099 std::unique_ptr<InputEvent> mFilteredEvent;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800100 std::optional<nsecs_t> mConfigurationChangedTime;
chaviwfd6d3512019-03-25 13:23:49 -0700101 sp<IBinder> mOnPointerDownToken;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800102 std::optional<NotifySwitchArgs> mLastNotifySwitch;
Jackal Guof9696682018-10-05 12:23:23 +0800103
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800104 virtual void notifyConfigurationChanged(nsecs_t when) override {
105 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800106 }
107
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100108 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -0700109 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800110 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800111 return 0;
112 }
113
Robert Carr803535b2018-08-02 16:38:15 -0700114 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800115 }
116
chaviw0c06c6e2019-01-09 13:27:07 -0800117 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700118 }
119
Michael Wrightd02c5b62014-02-10 15:10:22 -0800120 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
121 *outConfig = mConfig;
122 }
123
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800124 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Jackal Guof9696682018-10-05 12:23:23 +0800125 switch (inputEvent->getType()) {
126 case AINPUT_EVENT_TYPE_KEY: {
127 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800128 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800129 break;
130 }
131
132 case AINPUT_EVENT_TYPE_MOTION: {
133 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800134 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800135 break;
136 }
137 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800138 return true;
139 }
140
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100141 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800142 }
143
Charles Chen3611f1f2019-01-29 17:26:18 +0800144 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800145 }
146
Robert Carr803535b2018-08-02 16:38:15 -0700147 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100148 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800149 return 0;
150 }
151
Robert Carr803535b2018-08-02 16:38:15 -0700152 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100153 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154 return false;
155 }
156
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800157 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
158 uint32_t policyFlags) override {
159 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
160 * essentially a passthrough for notifySwitch.
161 */
162 mLastNotifySwitch =
163 NotifySwitchArgs(1 /*sequenceNum*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800164 }
165
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100166 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800167 }
168
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100169 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800170 return false;
171 }
Jackal Guof9696682018-10-05 12:23:23 +0800172
chaviwfd6d3512019-03-25 13:23:49 -0700173 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
174 mOnPointerDownToken = newToken;
175 }
176
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800177 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
178 int32_t displayId) {
179 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
180 ASSERT_EQ(mFilteredEvent->getType(), type);
181
182 if (type == AINPUT_EVENT_TYPE_KEY) {
183 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
184 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
185 EXPECT_EQ(keyEvent.getAction(), action);
186 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
187 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
188 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
189 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
190 EXPECT_EQ(motionEvent.getAction(), action);
191 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
192 } else {
193 FAIL() << "Unknown type: " << type;
194 }
195
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800196 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800197 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800198};
199
200
201// --- InputDispatcherTest ---
202
203class InputDispatcherTest : public testing::Test {
204protected:
205 sp<FakeInputDispatcherPolicy> mFakePolicy;
206 sp<InputDispatcher> mDispatcher;
207
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700208 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209 mFakePolicy = new FakeInputDispatcherPolicy();
210 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800211 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
212 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700213 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800214 }
215
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700216 virtual void TearDown() override {
217 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800218 mFakePolicy.clear();
219 mDispatcher.clear();
220 }
221};
222
223
224TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
225 KeyEvent event;
226
227 // Rejects undefined key actions.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100228 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800229 /*action*/ -1, 0,
230 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800231 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800232 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800233 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
234 << "Should reject key events with undefined action.";
235
236 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100237 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800238 AKEY_EVENT_ACTION_MULTIPLE, 0,
239 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800240 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800241 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800242 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
243 << "Should reject key events with ACTION_MULTIPLE.";
244}
245
246TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
247 MotionEvent event;
248 PointerProperties pointerProperties[MAX_POINTERS + 1];
249 PointerCoords pointerCoords[MAX_POINTERS + 1];
250 for (int i = 0; i <= MAX_POINTERS; i++) {
251 pointerProperties[i].clear();
252 pointerProperties[i].id = i;
253 pointerCoords[i].clear();
254 }
255
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800256 // Some constants commonly used below
257 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
258 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
259 constexpr int32_t metaState = AMETA_NONE;
260 constexpr MotionClassification classification = MotionClassification::NONE;
261
Michael Wrightd02c5b62014-02-10 15:10:22 -0800262 // Rejects undefined motion actions.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800263 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700264 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
265 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
266 ARBITRARY_TIME, ARBITRARY_TIME,
267 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800268 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800269 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800270 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
271 << "Should reject motion events with undefined action.";
272
273 // Rejects pointer down with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800274 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700275 AMOTION_EVENT_ACTION_POINTER_DOWN |
276 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
277 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
278 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
279 ARBITRARY_TIME, ARBITRARY_TIME,
280 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800281 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800282 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800283 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
284 << "Should reject motion events with pointer down index too large.";
285
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800286 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700287 AMOTION_EVENT_ACTION_POINTER_DOWN |
288 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
289 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
290 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
291 ARBITRARY_TIME, ARBITRARY_TIME,
292 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800293 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800294 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800295 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
296 << "Should reject motion events with pointer down index too small.";
297
298 // Rejects pointer up with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800299 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700300 AMOTION_EVENT_ACTION_POINTER_UP |
301 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
302 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
303 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
304 ARBITRARY_TIME, ARBITRARY_TIME,
305 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800306 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800307 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
309 << "Should reject motion events with pointer up index too large.";
310
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800311 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700312 AMOTION_EVENT_ACTION_POINTER_UP |
313 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
314 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
315 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
316 ARBITRARY_TIME, ARBITRARY_TIME,
317 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800318 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800319 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800320 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
321 << "Should reject motion events with pointer up index too small.";
322
323 // Rejects motion events with invalid number of pointers.
Garfield Tan00f511d2019-06-12 16:55:40 -0700324 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
325 metaState, 0, classification, 0, 0, 0, 0,
326 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
327 ARBITRARY_TIME, ARBITRARY_TIME,
328 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800329 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800330 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800331 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
332 << "Should reject motion events with 0 pointers.";
333
Garfield Tan00f511d2019-06-12 16:55:40 -0700334 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
335 metaState, 0, classification, 0, 0, 0, 0,
336 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
337 ARBITRARY_TIME, ARBITRARY_TIME,
338 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800339 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800340 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800341 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
342 << "Should reject motion events with more than MAX_POINTERS pointers.";
343
344 // Rejects motion events with invalid pointer ids.
345 pointerProperties[0].id = -1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700346 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
347 metaState, 0, classification, 0, 0, 0, 0,
348 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
349 ARBITRARY_TIME, ARBITRARY_TIME,
350 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800351 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800352 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800353 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
354 << "Should reject motion events with pointer ids less than 0.";
355
356 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700357 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
358 metaState, 0, classification, 0, 0, 0, 0,
359 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
360 ARBITRARY_TIME, ARBITRARY_TIME,
361 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800362 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800363 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800364 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
365 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
366
367 // Rejects motion events with duplicate pointer ids.
368 pointerProperties[0].id = 1;
369 pointerProperties[1].id = 1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700370 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
371 metaState, 0, classification, 0, 0, 0, 0,
372 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
373 ARBITRARY_TIME, ARBITRARY_TIME,
374 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800375 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800376 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800377 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
378 << "Should reject motion events with duplicate pointer ids.";
379}
380
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800381/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
382
383TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
384 constexpr nsecs_t eventTime = 20;
385 NotifyConfigurationChangedArgs args(10 /*sequenceNum*/, eventTime);
386 mDispatcher->notifyConfigurationChanged(&args);
387 ASSERT_TRUE(mDispatcher->waitForIdle());
388
389 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
390}
391
392TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
393 NotifySwitchArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, 0 /*policyFlags*/,
394 1 /*switchValues*/, 2 /*switchMask*/);
395 mDispatcher->notifySwitch(&args);
396
397 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
398 args.policyFlags |= POLICY_FLAG_TRUSTED;
399 mFakePolicy->assertNotifySwitchWasCalled(args);
400}
401
Arthur Hungb92218b2018-08-14 12:00:21 +0800402// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800403static constexpr int32_t INJECT_EVENT_TIMEOUT = 500;
404static constexpr int32_t DISPATCHING_TIMEOUT = 100;
Arthur Hungb92218b2018-08-14 12:00:21 +0800405
406class FakeApplicationHandle : public InputApplicationHandle {
407public:
408 FakeApplicationHandle() {}
409 virtual ~FakeApplicationHandle() {}
410
411 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800412 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800413 return true;
414 }
415};
416
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800417class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800418public:
chaviwd1c23182019-12-20 18:44:56 -0800419 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
420 : mName(name) {
421 mConsumer = std::make_unique<InputConsumer>(clientChannel);
422 }
423
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800424 InputEvent* consume() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800425 uint32_t consumeSeq;
426 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800427
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800428 std::chrono::time_point start = std::chrono::steady_clock::now();
429 status_t status = WOULD_BLOCK;
430 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800431 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800432 &event);
433 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
434 if (elapsed > 100ms) {
435 break;
436 }
437 }
438
439 if (status == WOULD_BLOCK) {
440 // Just means there's no event available.
441 return nullptr;
442 }
443
444 if (status != OK) {
445 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
446 return nullptr;
447 }
448 if (event == nullptr) {
449 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
450 return nullptr;
451 }
452
chaviwd1c23182019-12-20 18:44:56 -0800453 status = mConsumer->sendFinishedSignal(consumeSeq, true);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800454 if (status != OK) {
455 ADD_FAILURE() << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
456 }
457 return event;
458 }
459
460 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
461 int32_t expectedFlags) {
462 InputEvent* event = consume();
463
464 ASSERT_NE(nullptr, event) << mName.c_str()
465 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800466 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800467 << mName.c_str() << "expected " << inputEventTypeToString(expectedEventType)
468 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800469
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800470 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800471
Tiger Huang8664f8c2018-10-11 19:14:35 +0800472 switch (expectedEventType) {
473 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800474 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
475 EXPECT_EQ(expectedAction, keyEvent.getAction());
476 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800477 break;
478 }
479 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800480 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
481 EXPECT_EQ(expectedAction, motionEvent.getAction());
482 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800483 break;
484 }
485 default: {
486 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
487 }
488 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800489 }
490
chaviwd1c23182019-12-20 18:44:56 -0800491 void assertNoEvents() {
492 InputEvent* event = consume();
493 ASSERT_EQ(nullptr, event)
494 << mName.c_str()
495 << ": should not have received any events, so consume() should return NULL";
496 }
497
498 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
499
500protected:
501 std::unique_ptr<InputConsumer> mConsumer;
502 PreallocatedInputEventFactory mEventFactory;
503
504 std::string mName;
505};
506
507class FakeWindowHandle : public InputWindowHandle {
508public:
509 static const int32_t WIDTH = 600;
510 static const int32_t HEIGHT = 800;
511 const std::string mName;
512
513 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
514 const sp<InputDispatcher>& dispatcher, const std::string name,
515 int32_t displayId, sp<IBinder> token = nullptr)
516 : mName(name) {
517 if (token == nullptr) {
518 sp<InputChannel> serverChannel, clientChannel;
519 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
520 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
521 dispatcher->registerInputChannel(serverChannel);
522 token = serverChannel->getConnectionToken();
523 }
524
525 inputApplicationHandle->updateInfo();
526 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
527
528 mInfo.token = token;
529 mInfo.name = name;
530 mInfo.layoutParamsFlags = 0;
531 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
532 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
533 mInfo.frameLeft = 0;
534 mInfo.frameTop = 0;
535 mInfo.frameRight = WIDTH;
536 mInfo.frameBottom = HEIGHT;
537 mInfo.globalScaleFactor = 1.0;
538 mInfo.touchableRegion.clear();
539 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
540 mInfo.visible = true;
541 mInfo.canReceiveKeys = true;
542 mInfo.hasFocus = false;
543 mInfo.hasWallpaper = false;
544 mInfo.paused = false;
545 mInfo.layer = 0;
546 mInfo.ownerPid = INJECTOR_PID;
547 mInfo.ownerUid = INJECTOR_UID;
548 mInfo.inputFeatures = 0;
549 mInfo.displayId = displayId;
550 }
551
552 virtual bool updateInfo() { return true; }
553
554 void setFocus() { mInfo.hasFocus = true; }
555
556 void setFrame(const Rect& frame) {
557 mInfo.frameLeft = frame.left;
558 mInfo.frameTop = frame.top;
559 mInfo.frameRight = frame.right;
560 mInfo.frameBottom = frame.bottom;
561 mInfo.touchableRegion.clear();
562 mInfo.addTouchableRegion(frame);
563 }
564
565 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
566
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800567 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
568 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
569 expectedFlags);
570 }
571
572 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
573 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
574 expectedFlags);
575 }
576
Michael Wright3a240c42019-12-10 20:53:41 +0000577 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
578 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
579 expectedFlags);
580 }
581
chaviwd1c23182019-12-20 18:44:56 -0800582 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
583 int32_t expectedFlags) {
584 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
585 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
586 expectedFlags);
587 }
588
Arthur Hungb92218b2018-08-14 12:00:21 +0800589 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800590 ASSERT_NE(mInputReceiver, nullptr)
591 << "Call 'assertNoEvents' on a window with an InputReceiver";
592 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800593 }
594
chaviwd1c23182019-12-20 18:44:56 -0800595private:
596 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800597};
598
Tiger Huang721e26f2018-07-24 22:26:19 +0800599static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
600 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800601 KeyEvent event;
602 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
603
604 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800605 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800606 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
607 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
608
609 // Inject event until dispatch out.
610 return dispatcher->injectInputEvent(
611 &event,
612 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
613 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
614}
615
Garfield Tan00f511d2019-06-12 16:55:40 -0700616static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
617 int32_t source, int32_t displayId, int32_t x, int32_t y,
618 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
619 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800620 MotionEvent event;
621 PointerProperties pointerProperties[1];
622 PointerCoords pointerCoords[1];
623
624 pointerProperties[0].clear();
625 pointerProperties[0].id = 0;
626 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
627
628 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700629 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
630 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800631
632 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
633 // Define a valid motion down event.
Garfield Tan00f511d2019-06-12 16:55:40 -0700634 event.initialize(DEVICE_ID, source, displayId, action, /* actionButton */ 0, /* flags */ 0,
635 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
636 /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
637 /* yPrecision */ 0, xCursorPosition, yCursorPosition, currentTime, currentTime,
638 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800639
640 // Inject event until dispatch out.
641 return dispatcher->injectInputEvent(
642 &event,
643 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
644 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
645}
646
Garfield Tan00f511d2019-06-12 16:55:40 -0700647static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
648 int32_t displayId, int32_t x = 100, int32_t y = 200) {
649 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
650}
651
Michael Wright3a240c42019-12-10 20:53:41 +0000652static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
653 int32_t displayId, int32_t x = 100, int32_t y = 200) {
654 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y);
655}
656
Jackal Guof9696682018-10-05 12:23:23 +0800657static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
658 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
659 // Define a valid key event.
660 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
661 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
662 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
663
664 return args;
665}
666
chaviwd1c23182019-12-20 18:44:56 -0800667static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
668 const std::vector<PointF>& points) {
669 size_t pointerCount = points.size();
670 PointerProperties pointerProperties[pointerCount];
671 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800672
chaviwd1c23182019-12-20 18:44:56 -0800673 for (size_t i = 0; i < pointerCount; i++) {
674 pointerProperties[i].clear();
675 pointerProperties[i].id = i;
676 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800677
chaviwd1c23182019-12-20 18:44:56 -0800678 pointerCoords[i].clear();
679 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
680 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
681 }
Jackal Guof9696682018-10-05 12:23:23 +0800682
683 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
684 // Define a valid motion event.
685 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700686 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
687 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800688 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
689 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700690 AMOTION_EVENT_INVALID_CURSOR_POSITION,
691 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800692
693 return args;
694}
695
chaviwd1c23182019-12-20 18:44:56 -0800696static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
697 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
698}
699
Arthur Hungb92218b2018-08-14 12:00:21 +0800700TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
701 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800702 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
703 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800704
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800705 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800706 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
707 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800708 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
709
710 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800711 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800712}
713
714// The foreground window should receive the first touch down event.
715TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
716 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800717 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
718 ADISPLAY_ID_DEFAULT);
719 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
720 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800721
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800722 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800723 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
724 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800725 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
726
727 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800728 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800729 windowSecond->assertNoEvents();
730}
731
732TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
733 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800734 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
735 ADISPLAY_ID_DEFAULT);
736 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
737 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800738
Arthur Hung7ab76b12019-01-09 19:17:20 +0800739 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800740 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800741
742 // Expect one focus window exist in display.
743 windowSecond->setFocus();
Arthur Hungb92218b2018-08-14 12:00:21 +0800744
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800745 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800746 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
747 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
748
749 // Focused window should receive event.
750 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800751 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +0800752}
753
Arthur Hung7ab76b12019-01-09 19:17:20 +0800754TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
755 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
756 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
757 ADISPLAY_ID_DEFAULT);
758 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
759 ADISPLAY_ID_DEFAULT);
760
761 // Set focused application.
762 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
763
764 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
765 windowTop->setFocus();
766 windowSecond->setFocus();
Arthur Hung7ab76b12019-01-09 19:17:20 +0800767
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800768 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800769 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
770 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
771
772 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800773 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800774 windowSecond->assertNoEvents();
775}
776
Arthur Hung3b413f22018-10-26 18:05:34 +0800777TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
778 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
779
780 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
781 ADISPLAY_ID_DEFAULT);
782 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
783 ADISPLAY_ID_DEFAULT);
784
Arthur Hung832bc4a2019-01-28 11:43:17 +0800785 // Set focused application.
786 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800787
Arthur Hung832bc4a2019-01-28 11:43:17 +0800788 windowTop->setFocus();
789 windowSecond->setFocus();
Arthur Hung3b413f22018-10-26 18:05:34 +0800790 // Release channel for window is no longer valid.
791 windowTop->releaseChannel();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800792 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Arthur Hung3b413f22018-10-26 18:05:34 +0800793
Arthur Hung832bc4a2019-01-28 11:43:17 +0800794 // Test inject a key down, should dispatch to a valid window.
795 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
796 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800797
798 // Top window is invalid, so it should not receive any input event.
799 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800800 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800801}
802
Garfield Tan00f511d2019-06-12 16:55:40 -0700803TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
804 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
805
806 sp<FakeWindowHandle> windowLeft =
807 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
808 windowLeft->setFrame(Rect(0, 0, 600, 800));
809 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
810 sp<FakeWindowHandle> windowRight =
811 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
812 windowRight->setFrame(Rect(600, 0, 1200, 800));
813 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
814
815 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
816
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800817 mDispatcher->setInputWindows({windowLeft, windowRight}, ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700818
819 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
820 // left window. This event should be dispatched to the left window.
821 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
822 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
823 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800824 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700825 windowRight->assertNoEvents();
826}
827
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800828TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
829 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
830 sp<FakeWindowHandle> window =
831 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
832 window->setFocus();
833
834 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
835
836 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
837 mDispatcher->notifyKey(&keyArgs);
838
839 // Window should receive key down event.
840 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
841
842 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
843 // on the app side.
844 NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
845 mDispatcher->notifyDeviceReset(&args);
846 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
847 AKEY_EVENT_FLAG_CANCELED);
848}
849
850TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
851 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
852 sp<FakeWindowHandle> window =
853 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
854
855 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
856
857 NotifyMotionArgs motionArgs =
858 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
859 ADISPLAY_ID_DEFAULT);
860 mDispatcher->notifyMotion(&motionArgs);
861
862 // Window should receive motion down event.
863 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
864
865 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
866 // on the app side.
867 NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
868 mDispatcher->notifyDeviceReset(&args);
869 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
870 0 /*expectedFlags*/);
871}
872
chaviwd1c23182019-12-20 18:44:56 -0800873class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +0000874public:
875 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -0800876 int32_t displayId, bool isGestureMonitor = false) {
877 sp<InputChannel> serverChannel, clientChannel;
878 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
879 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
880 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +0000881 }
882
chaviwd1c23182019-12-20 18:44:56 -0800883 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
884
885 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
886 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
887 expectedDisplayId, expectedFlags);
888 }
889
890 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
891 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
892 expectedDisplayId, expectedFlags);
893 }
894
895 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
896 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
897 expectedDisplayId, expectedFlags);
898 }
899
900 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
901
902private:
903 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +0000904};
905
906// Tests for gesture monitors
907TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
908 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
909 sp<FakeWindowHandle> window =
910 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
911 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
912
chaviwd1c23182019-12-20 18:44:56 -0800913 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
914 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +0000915
916 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
917 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
918 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
919 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -0800920 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +0000921}
922
923TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
924 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
925 sp<FakeWindowHandle> window =
926 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
927
928 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
929 window->setFocus();
930
931 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
932
chaviwd1c23182019-12-20 18:44:56 -0800933 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
934 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +0000935
936 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
937 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
938 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -0800939 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +0000940}
941
942TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
943 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
944 sp<FakeWindowHandle> window =
945 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
946 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
947
chaviwd1c23182019-12-20 18:44:56 -0800948 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
949 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +0000950
951 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
952 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
953 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
954 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -0800955 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +0000956
957 window->releaseChannel();
958
chaviwd1c23182019-12-20 18:44:56 -0800959 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +0000960
961 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
962 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
963 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -0800964 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +0000965}
966
chaviw81e2bb92019-12-18 15:03:51 -0800967TEST_F(InputDispatcherTest, TestMoveEvent) {
968 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
969 sp<FakeWindowHandle> window =
970 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
971
972 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
973
974 NotifyMotionArgs motionArgs =
975 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
976 ADISPLAY_ID_DEFAULT);
977
978 mDispatcher->notifyMotion(&motionArgs);
979 // Window should receive motion down event.
980 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
981
982 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
983 motionArgs.sequenceNum += 1;
984 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
985 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
986 motionArgs.pointerCoords[0].getX() - 10);
987
988 mDispatcher->notifyMotion(&motionArgs);
989 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
990 0 /*expectedFlags*/);
991}
992
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800993/* Test InputDispatcher for MultiDisplay */
994class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
995public:
996 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700997 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800998 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800999
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001000 application1 = new FakeApplicationHandle();
1001 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1002 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001003
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001004 // Set focus window for primary display, but focused display would be second one.
1005 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
1006 windowInPrimary->setFocus();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001007 mDispatcher->setInputWindows({windowInPrimary}, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001008
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001009 application2 = new FakeApplicationHandle();
1010 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1011 SECOND_DISPLAY_ID);
1012 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001013 // Set focus display to second one.
1014 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1015 // Set focus window for second display.
1016 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
1017 windowInSecondary->setFocus();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001018 mDispatcher->setInputWindows({windowInSecondary}, SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001019 }
1020
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001021 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001022 InputDispatcherTest::TearDown();
1023
1024 application1.clear();
1025 windowInPrimary.clear();
1026 application2.clear();
1027 windowInSecondary.clear();
1028 }
1029
1030protected:
1031 sp<FakeApplicationHandle> application1;
1032 sp<FakeWindowHandle> windowInPrimary;
1033 sp<FakeApplicationHandle> application2;
1034 sp<FakeWindowHandle> windowInSecondary;
1035};
1036
1037TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1038 // Test touch down on primary display.
1039 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1040 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001041 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001042 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001043 windowInSecondary->assertNoEvents();
1044
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001045 // Test touch down on second display.
1046 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1047 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001048 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1049 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001050 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001051}
1052
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001053TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001054 // Test inject a key down with display id specified.
1055 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1056 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001057 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001058 windowInSecondary->assertNoEvents();
1059
1060 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001061 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1062 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1063 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001064 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001065
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001066 // Remove all windows in secondary display.
1067 mDispatcher->setInputWindows({}, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001068
1069 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001070 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1071 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001072
1073 // Test inject a key down, should timeout because of no target window.
1074 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1075 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1076 windowInPrimary->assertNoEvents();
1077 windowInSecondary->assertNoEvents();
1078}
1079
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001080// Test per-display input monitors for motion event.
1081TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001082 FakeMonitorReceiver monitorInPrimary =
1083 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1084 FakeMonitorReceiver monitorInSecondary =
1085 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001086
1087 // Test touch down on primary display.
1088 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1089 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1090 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001091 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001092 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001093 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001094 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001095
1096 // Test touch down on second display.
1097 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1098 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1099 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1100 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001101 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001102 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001103 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001104
1105 // Test inject a non-pointer motion event.
1106 // If specific a display, it will dispatch to the focused window of particular display,
1107 // or it will dispatch to the focused window of focused display.
1108 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1109 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1110 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1111 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001112 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001113 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001114 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001115}
1116
1117// Test per-display input monitors for key event.
1118TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1119 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001120 FakeMonitorReceiver monitorInPrimary =
1121 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1122 FakeMonitorReceiver monitorInSecondary =
1123 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001124
1125 // Test inject a key down.
1126 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1127 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1128 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001129 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001130 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001131 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001132}
1133
Jackal Guof9696682018-10-05 12:23:23 +08001134class InputFilterTest : public InputDispatcherTest {
1135protected:
1136 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1137
1138 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1139 NotifyMotionArgs motionArgs;
1140
1141 motionArgs = generateMotionArgs(
1142 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1143 mDispatcher->notifyMotion(&motionArgs);
1144 motionArgs = generateMotionArgs(
1145 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1146 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001147 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001148 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001149 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001150 } else {
1151 mFakePolicy->assertFilterInputEventWasNotCalled();
1152 }
1153 }
1154
1155 void testNotifyKey(bool expectToBeFiltered) {
1156 NotifyKeyArgs keyArgs;
1157
1158 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1159 mDispatcher->notifyKey(&keyArgs);
1160 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1161 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001162 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001163
1164 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001165 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001166 } else {
1167 mFakePolicy->assertFilterInputEventWasNotCalled();
1168 }
1169 }
1170};
1171
1172// Test InputFilter for MotionEvent
1173TEST_F(InputFilterTest, MotionEvent_InputFilter) {
1174 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
1175 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1176 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1177
1178 // Enable InputFilter
1179 mDispatcher->setInputFilterEnabled(true);
1180 // Test touch on both primary and second display, and check if both events are filtered.
1181 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
1182 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
1183
1184 // Disable InputFilter
1185 mDispatcher->setInputFilterEnabled(false);
1186 // Test touch on both primary and second display, and check if both events aren't filtered.
1187 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1188 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1189}
1190
1191// Test InputFilter for KeyEvent
1192TEST_F(InputFilterTest, KeyEvent_InputFilter) {
1193 // Since the InputFilter is disabled by default, check if key event aren't filtered.
1194 testNotifyKey(/*expectToBeFiltered*/ false);
1195
1196 // Enable InputFilter
1197 mDispatcher->setInputFilterEnabled(true);
1198 // Send a key event, and check if it is filtered.
1199 testNotifyKey(/*expectToBeFiltered*/ true);
1200
1201 // Disable InputFilter
1202 mDispatcher->setInputFilterEnabled(false);
1203 // Send a key event, and check if it isn't filtered.
1204 testNotifyKey(/*expectToBeFiltered*/ false);
1205}
1206
chaviwfd6d3512019-03-25 13:23:49 -07001207class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001208 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07001209 InputDispatcherTest::SetUp();
1210
1211 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1212 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
1213 ADISPLAY_ID_DEFAULT);
1214 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1215 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1216 // window.
1217 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1218
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001219 mFocusedWindow =
1220 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1221 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
1222 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1223 mFocusedWindowTouchPoint = 60;
chaviwfd6d3512019-03-25 13:23:49 -07001224
1225 // Set focused application.
1226 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001227 mFocusedWindow->setFocus();
chaviwfd6d3512019-03-25 13:23:49 -07001228
1229 // Expect one focus window exist in display.
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001230 mDispatcher->setInputWindows({mUnfocusedWindow, mFocusedWindow}, ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07001231 }
1232
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001233 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07001234 InputDispatcherTest::TearDown();
1235
1236 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001237 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07001238 }
1239
1240protected:
1241 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001242 sp<FakeWindowHandle> mFocusedWindow;
1243 int32_t mFocusedWindowTouchPoint;
chaviwfd6d3512019-03-25 13:23:49 -07001244};
1245
1246// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1247// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1248// the onPointerDownOutsideFocus callback.
1249TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
1250 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1251 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
1252 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001253
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001254 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07001255 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1256}
1257
1258// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1259// DOWN on the window that doesn't have focus. Ensure no window received the
1260// onPointerDownOutsideFocus callback.
1261TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
1262 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1263 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
1264 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001265
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001266 ASSERT_TRUE(mDispatcher->waitForIdle());
1267 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001268}
1269
1270// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1271// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1272TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1273 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1274 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001275
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001276 ASSERT_TRUE(mDispatcher->waitForIdle());
1277 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001278}
1279
1280// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1281// DOWN on the window that already has focus. Ensure no window received the
1282// onPointerDownOutsideFocus callback.
1283TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1284 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001285 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1286 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1287 mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
chaviwfd6d3512019-03-25 13:23:49 -07001288 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001289
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001290 ASSERT_TRUE(mDispatcher->waitForIdle());
1291 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001292}
1293
Garfield Tane84e6f92019-08-29 17:28:41 -07001294} // namespace android::inputdispatcher