blob: 27db8f5534534854a00654f8868106bb90f52c1d [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 Vishniakou9c858ac2020-01-23 14:20:11 -0600228 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
229 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
230 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 Vishniakou9c858ac2020-01-23 14:20:11 -0600237 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
238 AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
239 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 Vishniakou9c858ac2020-01-23 14:20:11 -0600263 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
264 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
265 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
266 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700267 /*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 Vishniakou9c858ac2020-01-23 14:20:11 -0600274 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700275 AMOTION_EVENT_ACTION_POINTER_DOWN |
276 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600277 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
278 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
279 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700280 /*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 Vishniakou9c858ac2020-01-23 14:20:11 -0600286 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700287 AMOTION_EVENT_ACTION_POINTER_DOWN |
288 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600289 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
290 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
291 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700292 /*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 Vishniakou9c858ac2020-01-23 14:20:11 -0600299 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700300 AMOTION_EVENT_ACTION_POINTER_UP |
301 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600302 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
303 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
304 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700305 /*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 Vishniakou9c858ac2020-01-23 14:20:11 -0600311 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700312 AMOTION_EVENT_ACTION_POINTER_UP |
313 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600314 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
315 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
316 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700317 /*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.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600324 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
325 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
326 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
327 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700328 /*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
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600334 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
335 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
336 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
337 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700338 /*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;
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600346 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
347 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
348 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
349 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700350 /*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;
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600357 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
358 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
359 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
360 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700361 /*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;
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600370 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
371 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
372 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
373 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700374 /*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 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100485 case AINPUT_EVENT_TYPE_FOCUS: {
486 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
487 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800488 default: {
489 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
490 }
491 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800492 }
493
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100494 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
495 InputEvent* event = consume();
496 ASSERT_NE(nullptr, event) << mName.c_str()
497 << ": consumer should have returned non-NULL event.";
498 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
499 << "Got " << inputEventTypeToString(event->getType())
500 << " event instead of FOCUS event";
501
502 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
503 << mName.c_str() << ": event displayId should always be NONE.";
504
505 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
506 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
507 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
508 }
509
chaviwd1c23182019-12-20 18:44:56 -0800510 void assertNoEvents() {
511 InputEvent* event = consume();
512 ASSERT_EQ(nullptr, event)
513 << mName.c_str()
514 << ": should not have received any events, so consume() should return NULL";
515 }
516
517 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
518
519protected:
520 std::unique_ptr<InputConsumer> mConsumer;
521 PreallocatedInputEventFactory mEventFactory;
522
523 std::string mName;
524};
525
526class FakeWindowHandle : public InputWindowHandle {
527public:
528 static const int32_t WIDTH = 600;
529 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800530
531 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
532 const sp<InputDispatcher>& dispatcher, const std::string name,
533 int32_t displayId, sp<IBinder> token = nullptr)
534 : mName(name) {
535 if (token == nullptr) {
536 sp<InputChannel> serverChannel, clientChannel;
537 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
538 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
539 dispatcher->registerInputChannel(serverChannel);
540 token = serverChannel->getConnectionToken();
541 }
542
543 inputApplicationHandle->updateInfo();
544 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
545
546 mInfo.token = token;
chaviwaf87b3e2019-10-01 16:59:28 -0700547 mInfo.id = 0;
chaviwd1c23182019-12-20 18:44:56 -0800548 mInfo.name = name;
549 mInfo.layoutParamsFlags = 0;
550 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
551 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
552 mInfo.frameLeft = 0;
553 mInfo.frameTop = 0;
554 mInfo.frameRight = WIDTH;
555 mInfo.frameBottom = HEIGHT;
556 mInfo.globalScaleFactor = 1.0;
557 mInfo.touchableRegion.clear();
558 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
559 mInfo.visible = true;
560 mInfo.canReceiveKeys = true;
561 mInfo.hasFocus = false;
562 mInfo.hasWallpaper = false;
563 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800564 mInfo.ownerPid = INJECTOR_PID;
565 mInfo.ownerUid = INJECTOR_UID;
566 mInfo.inputFeatures = 0;
567 mInfo.displayId = displayId;
568 }
569
570 virtual bool updateInfo() { return true; }
571
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100572 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800573
574 void setFrame(const Rect& frame) {
575 mInfo.frameLeft = frame.left;
576 mInfo.frameTop = frame.top;
577 mInfo.frameRight = frame.right;
578 mInfo.frameBottom = frame.bottom;
579 mInfo.touchableRegion.clear();
580 mInfo.addTouchableRegion(frame);
581 }
582
583 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
584
chaviwaf87b3e2019-10-01 16:59:28 -0700585 void setId(int32_t id) { mInfo.id = id; }
586
587 void setWindowScale(float xScale, float yScale) {
588 mInfo.windowXScale = xScale;
589 mInfo.windowYScale = yScale;
590 }
591
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800592 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
593 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
594 expectedFlags);
595 }
596
Svet Ganov5d3bc372020-01-26 23:11:07 -0800597 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
598 int32_t expectedFlags = 0) {
599 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
600 expectedFlags);
601 }
602
603 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
604 int32_t expectedFlags = 0) {
605 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
606 expectedFlags);
607 }
608
609 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
610 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800611 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
612 expectedFlags);
613 }
614
Svet Ganov5d3bc372020-01-26 23:11:07 -0800615 void consumeMotionPointerDown(int32_t pointerIdx,
616 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
617 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
618 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
619 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
620 }
621
622 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
623 int32_t expectedFlags = 0) {
624 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
625 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
626 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
627 }
628
629 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
630 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000631 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
632 expectedFlags);
633 }
634
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100635 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
636 ASSERT_NE(mInputReceiver, nullptr)
637 << "Cannot consume events from a window with no receiver";
638 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
639 }
640
chaviwd1c23182019-12-20 18:44:56 -0800641 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
642 int32_t expectedFlags) {
643 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
644 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
645 expectedFlags);
646 }
647
chaviwaf87b3e2019-10-01 16:59:28 -0700648 InputEvent* consume() {
649 if (mInputReceiver == nullptr) {
650 return nullptr;
651 }
652 return mInputReceiver->consume();
653 }
654
Arthur Hungb92218b2018-08-14 12:00:21 +0800655 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800656 ASSERT_NE(mInputReceiver, nullptr)
657 << "Call 'assertNoEvents' on a window with an InputReceiver";
658 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800659 }
660
chaviwaf87b3e2019-10-01 16:59:28 -0700661 sp<IBinder> getToken() { return mInfo.token; }
662
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100663 const std::string& getName() { return mName; }
664
chaviwd1c23182019-12-20 18:44:56 -0800665private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100666 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800667 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800668};
669
Tiger Huang721e26f2018-07-24 22:26:19 +0800670static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
671 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800672 KeyEvent event;
673 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
674
675 // Define a valid key down event.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600676 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, INVALID_HMAC,
677 AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
678 /* repeatCount */ 0, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800679
680 // Inject event until dispatch out.
681 return dispatcher->injectInputEvent(
682 &event,
683 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
684 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
685}
686
Garfield Tan00f511d2019-06-12 16:55:40 -0700687static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
688 int32_t source, int32_t displayId, int32_t x, int32_t y,
689 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
690 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800691 MotionEvent event;
692 PointerProperties pointerProperties[1];
693 PointerCoords pointerCoords[1];
694
695 pointerProperties[0].clear();
696 pointerProperties[0].id = 0;
697 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
698
699 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700700 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
701 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800702
703 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
704 // Define a valid motion down event.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600705 event.initialize(DEVICE_ID, source, displayId, INVALID_HMAC, action, /* actionButton */ 0,
706 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700707 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600708 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
709 /* xPrecision */ 0, /* yPrecision */ 0, xCursorPosition, yCursorPosition,
710 currentTime, currentTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700711 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800712
713 // Inject event until dispatch out.
714 return dispatcher->injectInputEvent(
715 &event,
716 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
717 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
718}
719
Garfield Tan00f511d2019-06-12 16:55:40 -0700720static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
721 int32_t displayId, int32_t x = 100, int32_t y = 200) {
722 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
723}
724
Michael Wright3a240c42019-12-10 20:53:41 +0000725static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
726 int32_t displayId, int32_t x = 100, int32_t y = 200) {
727 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y);
728}
729
Jackal Guof9696682018-10-05 12:23:23 +0800730static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
731 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
732 // Define a valid key event.
733 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
734 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
735 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
736
737 return args;
738}
739
chaviwd1c23182019-12-20 18:44:56 -0800740static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
741 const std::vector<PointF>& points) {
742 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700743 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
744 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
745 }
746
chaviwd1c23182019-12-20 18:44:56 -0800747 PointerProperties pointerProperties[pointerCount];
748 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800749
chaviwd1c23182019-12-20 18:44:56 -0800750 for (size_t i = 0; i < pointerCount; i++) {
751 pointerProperties[i].clear();
752 pointerProperties[i].id = i;
753 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800754
chaviwd1c23182019-12-20 18:44:56 -0800755 pointerCoords[i].clear();
756 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
757 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
758 }
Jackal Guof9696682018-10-05 12:23:23 +0800759
760 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
761 // Define a valid motion event.
762 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700763 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
764 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800765 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
766 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700767 AMOTION_EVENT_INVALID_CURSOR_POSITION,
768 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800769
770 return args;
771}
772
chaviwd1c23182019-12-20 18:44:56 -0800773static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
774 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
775}
776
Arthur Hungb92218b2018-08-14 12:00:21 +0800777TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
778 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800779 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
780 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800781
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800782 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800783 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
784 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800785 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
786
787 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800788 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800789}
790
791// The foreground window should receive the first touch down event.
792TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
793 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800794 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
795 ADISPLAY_ID_DEFAULT);
796 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
797 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800798
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800799 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800800 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
801 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800802 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
803
804 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800805 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800806 windowSecond->assertNoEvents();
807}
808
809TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
810 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800811 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
812 ADISPLAY_ID_DEFAULT);
813 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
814 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800815
Arthur Hung7ab76b12019-01-09 19:17:20 +0800816 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800817 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800818
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100819 // Display should have only one focused window
820 windowSecond->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800821 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100822
823 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +0800824 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
825 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
826
827 // Focused window should receive event.
828 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800829 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +0800830}
831
Arthur Hung7ab76b12019-01-09 19:17:20 +0800832TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
833 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
834 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
835 ADISPLAY_ID_DEFAULT);
836 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
837 ADISPLAY_ID_DEFAULT);
838
839 // Set focused application.
840 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
841
842 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100843 windowTop->setFocus(true);
844 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800845
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800846 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100847 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800848 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
849 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
850
851 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800852 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800853 windowSecond->assertNoEvents();
854}
855
Arthur Hung3b413f22018-10-26 18:05:34 +0800856TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
857 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
858
859 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
860 ADISPLAY_ID_DEFAULT);
861 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
862 ADISPLAY_ID_DEFAULT);
863
Arthur Hung832bc4a2019-01-28 11:43:17 +0800864 // Set focused application.
865 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800866
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100867 windowTop->setFocus(true);
868 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +0800869 // Release channel for window is no longer valid.
870 windowTop->releaseChannel();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800871 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100872 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +0800873
Arthur Hung832bc4a2019-01-28 11:43:17 +0800874 // Test inject a key down, should dispatch to a valid window.
875 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
876 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800877
878 // Top window is invalid, so it should not receive any input event.
879 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800880 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800881}
882
Garfield Tan00f511d2019-06-12 16:55:40 -0700883TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
884 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
885
886 sp<FakeWindowHandle> windowLeft =
887 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
888 windowLeft->setFrame(Rect(0, 0, 600, 800));
889 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
890 sp<FakeWindowHandle> windowRight =
891 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
892 windowRight->setFrame(Rect(600, 0, 1200, 800));
893 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
894
895 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
896
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800897 mDispatcher->setInputWindows({windowLeft, windowRight}, ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700898
899 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
900 // left window. This event should be dispatched to the left window.
901 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
902 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
903 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800904 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700905 windowRight->assertNoEvents();
906}
907
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800908TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
909 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
910 sp<FakeWindowHandle> window =
911 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100912 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800913
914 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100915 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800916
917 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
918 mDispatcher->notifyKey(&keyArgs);
919
920 // Window should receive key down event.
921 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
922
923 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
924 // on the app side.
925 NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
926 mDispatcher->notifyDeviceReset(&args);
927 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
928 AKEY_EVENT_FLAG_CANCELED);
929}
930
931TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
932 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
933 sp<FakeWindowHandle> window =
934 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
935
936 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
937
938 NotifyMotionArgs motionArgs =
939 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
940 ADISPLAY_ID_DEFAULT);
941 mDispatcher->notifyMotion(&motionArgs);
942
943 // Window should receive motion down event.
944 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
945
946 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
947 // on the app side.
948 NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
949 mDispatcher->notifyDeviceReset(&args);
950 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
951 0 /*expectedFlags*/);
952}
953
Svet Ganov5d3bc372020-01-26 23:11:07 -0800954TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
955 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
956
957 // Create a couple of windows
958 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
959 "First Window", ADISPLAY_ID_DEFAULT);
960 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
961 "Second Window", ADISPLAY_ID_DEFAULT);
962
963 // Add the windows to the dispatcher
964 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
965
966 // Send down to the first window
967 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
968 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
969 mDispatcher->notifyMotion(&downMotionArgs);
970 // Only the first window should get the down event
971 firstWindow->consumeMotionDown();
972 secondWindow->assertNoEvents();
973
974 // Transfer touch focus to the second window
975 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
976 // The first window gets cancel and the second gets down
977 firstWindow->consumeMotionCancel();
978 secondWindow->consumeMotionDown();
979
980 // Send up event to the second window
981 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
982 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
983 mDispatcher->notifyMotion(&upMotionArgs);
984 // The first window gets no events and the second gets up
985 firstWindow->assertNoEvents();
986 secondWindow->consumeMotionUp();
987}
988
989TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
990 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
991
992 PointF touchPoint = {10, 10};
993
994 // Create a couple of windows
995 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
996 "First Window", ADISPLAY_ID_DEFAULT);
997 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
998 "Second Window", ADISPLAY_ID_DEFAULT);
999
1000 // Add the windows to the dispatcher
1001 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1002
1003 // Send down to the first window
1004 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1005 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1006 mDispatcher->notifyMotion(&downMotionArgs);
1007 // Only the first window should get the down event
1008 firstWindow->consumeMotionDown();
1009 secondWindow->assertNoEvents();
1010
1011 // Send pointer down to the first window
1012 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1013 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1014 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1015 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1016 // Only the first window should get the pointer down event
1017 firstWindow->consumeMotionPointerDown(1);
1018 secondWindow->assertNoEvents();
1019
1020 // Transfer touch focus to the second window
1021 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1022 // The first window gets cancel and the second gets down and pointer down
1023 firstWindow->consumeMotionCancel();
1024 secondWindow->consumeMotionDown();
1025 secondWindow->consumeMotionPointerDown(1);
1026
1027 // Send pointer up to the second window
1028 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1029 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1030 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1031 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1032 // The first window gets nothing and the second gets pointer up
1033 firstWindow->assertNoEvents();
1034 secondWindow->consumeMotionPointerUp(1);
1035
1036 // Send up event to the second window
1037 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1038 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1039 mDispatcher->notifyMotion(&upMotionArgs);
1040 // The first window gets nothing and the second gets up
1041 firstWindow->assertNoEvents();
1042 secondWindow->consumeMotionUp();
1043}
1044
1045TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1046 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1047
1048 // Create a non touch modal window that supports split touch
1049 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1050 "First Window", ADISPLAY_ID_DEFAULT);
1051 firstWindow->setFrame(Rect(0, 0, 600, 400));
1052 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1053 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1054
1055 // Create a non touch modal window that supports split touch
1056 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1057 "Second Window", ADISPLAY_ID_DEFAULT);
1058 secondWindow->setFrame(Rect(0, 400, 600, 800));
1059 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1060 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1061
1062 // Add the windows to the dispatcher
1063 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1064
1065 PointF pointInFirst = {300, 200};
1066 PointF pointInSecond = {300, 600};
1067
1068 // Send down to the first window
1069 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1070 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1071 mDispatcher->notifyMotion(&firstDownMotionArgs);
1072 // Only the first window should get the down event
1073 firstWindow->consumeMotionDown();
1074 secondWindow->assertNoEvents();
1075
1076 // Send down to the second window
1077 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1078 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1079 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1080 mDispatcher->notifyMotion(&secondDownMotionArgs);
1081 // The first window gets a move and the second a down
1082 firstWindow->consumeMotionMove();
1083 secondWindow->consumeMotionDown();
1084
1085 // Transfer touch focus to the second window
1086 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1087 // The first window gets cancel and the new gets pointer down (it already saw down)
1088 firstWindow->consumeMotionCancel();
1089 secondWindow->consumeMotionPointerDown(1);
1090
1091 // Send pointer up to the second window
1092 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1093 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1094 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1095 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1096 // The first window gets nothing and the second gets pointer up
1097 firstWindow->assertNoEvents();
1098 secondWindow->consumeMotionPointerUp(1);
1099
1100 // Send up event to the second window
1101 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1102 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1103 mDispatcher->notifyMotion(&upMotionArgs);
1104 // The first window gets nothing and the second gets up
1105 firstWindow->assertNoEvents();
1106 secondWindow->consumeMotionUp();
1107}
1108
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001109TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1110 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1111 sp<FakeWindowHandle> window =
1112 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1113
1114 window->setFocus(true);
1115 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1116
1117 window->consumeFocusEvent(true);
1118
1119 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1120 mDispatcher->notifyKey(&keyArgs);
1121
1122 // Window should receive key down event.
1123 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1124}
1125
1126TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1127 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1128 sp<FakeWindowHandle> window =
1129 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1130
1131 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1132
1133 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1134 mDispatcher->notifyKey(&keyArgs);
1135 mDispatcher->waitForIdle();
1136
1137 window->assertNoEvents();
1138}
1139
1140// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1141TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1142 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1143 sp<FakeWindowHandle> window =
1144 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1145
1146 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1147
1148 // Send key
1149 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1150 mDispatcher->notifyKey(&keyArgs);
1151 // Send motion
1152 NotifyMotionArgs motionArgs =
1153 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1154 ADISPLAY_ID_DEFAULT);
1155 mDispatcher->notifyMotion(&motionArgs);
1156
1157 // Window should receive only the motion event
1158 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1159 window->assertNoEvents(); // Key event or focus event will not be received
1160}
1161
chaviwd1c23182019-12-20 18:44:56 -08001162class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001163public:
1164 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001165 int32_t displayId, bool isGestureMonitor = false) {
1166 sp<InputChannel> serverChannel, clientChannel;
1167 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1168 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1169 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001170 }
1171
chaviwd1c23182019-12-20 18:44:56 -08001172 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1173
1174 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1175 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1176 expectedDisplayId, expectedFlags);
1177 }
1178
1179 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1180 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1181 expectedDisplayId, expectedFlags);
1182 }
1183
1184 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1185 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1186 expectedDisplayId, expectedFlags);
1187 }
1188
1189 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1190
1191private:
1192 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001193};
1194
1195// Tests for gesture monitors
1196TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1197 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1198 sp<FakeWindowHandle> window =
1199 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1200 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1201
chaviwd1c23182019-12-20 18:44:56 -08001202 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1203 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001204
1205 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1206 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1207 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1208 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001209 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001210}
1211
1212TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1213 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1214 sp<FakeWindowHandle> window =
1215 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1216
1217 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001218 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001219
1220 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001221 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001222
chaviwd1c23182019-12-20 18:44:56 -08001223 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1224 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001225
1226 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1227 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1228 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001229 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001230}
1231
1232TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1233 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1234 sp<FakeWindowHandle> window =
1235 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1236 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1237
chaviwd1c23182019-12-20 18:44:56 -08001238 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1239 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001240
1241 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1242 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1243 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1244 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001245 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001246
1247 window->releaseChannel();
1248
chaviwd1c23182019-12-20 18:44:56 -08001249 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001250
1251 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1252 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1253 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001254 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001255}
1256
chaviw81e2bb92019-12-18 15:03:51 -08001257TEST_F(InputDispatcherTest, TestMoveEvent) {
1258 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1259 sp<FakeWindowHandle> window =
1260 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1261
1262 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1263
1264 NotifyMotionArgs motionArgs =
1265 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1266 ADISPLAY_ID_DEFAULT);
1267
1268 mDispatcher->notifyMotion(&motionArgs);
1269 // Window should receive motion down event.
1270 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1271
1272 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
1273 motionArgs.sequenceNum += 1;
1274 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1275 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1276 motionArgs.pointerCoords[0].getX() - 10);
1277
1278 mDispatcher->notifyMotion(&motionArgs);
1279 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1280 0 /*expectedFlags*/);
1281}
1282
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001283/**
1284 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1285 * the device default right away. In the test scenario, we check both the default value,
1286 * and the action of enabling / disabling.
1287 */
1288TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1289 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1290 sp<FakeWindowHandle> window =
1291 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1292
1293 // Set focused application.
1294 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1295 window->setFocus(true);
1296
1297 SCOPED_TRACE("Check default value of touch mode");
1298 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1299 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1300
1301 SCOPED_TRACE("Remove the window to trigger focus loss");
1302 window->setFocus(false);
1303 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1304 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1305
1306 SCOPED_TRACE("Disable touch mode");
1307 mDispatcher->setInTouchMode(false);
1308 window->setFocus(true);
1309 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1310 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1311
1312 SCOPED_TRACE("Remove the window to trigger focus loss");
1313 window->setFocus(false);
1314 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1315 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1316
1317 SCOPED_TRACE("Enable touch mode again");
1318 mDispatcher->setInTouchMode(true);
1319 window->setFocus(true);
1320 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1321 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1322
1323 window->assertNoEvents();
1324}
1325
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001326/* Test InputDispatcher for MultiDisplay */
1327class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1328public:
1329 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001330 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001331 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001332
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001333 application1 = new FakeApplicationHandle();
1334 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1335 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001336
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001337 // Set focus window for primary display, but focused display would be second one.
1338 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001339 windowInPrimary->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001340 mDispatcher->setInputWindows({windowInPrimary}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001341 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001342
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001343 application2 = new FakeApplicationHandle();
1344 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1345 SECOND_DISPLAY_ID);
1346 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001347 // Set focus display to second one.
1348 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1349 // Set focus window for second display.
1350 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001351 windowInSecondary->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001352 mDispatcher->setInputWindows({windowInSecondary}, SECOND_DISPLAY_ID);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001353 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001354 }
1355
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001356 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001357 InputDispatcherTest::TearDown();
1358
1359 application1.clear();
1360 windowInPrimary.clear();
1361 application2.clear();
1362 windowInSecondary.clear();
1363 }
1364
1365protected:
1366 sp<FakeApplicationHandle> application1;
1367 sp<FakeWindowHandle> windowInPrimary;
1368 sp<FakeApplicationHandle> application2;
1369 sp<FakeWindowHandle> windowInSecondary;
1370};
1371
1372TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1373 // Test touch down on primary display.
1374 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1375 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001376 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001377 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001378 windowInSecondary->assertNoEvents();
1379
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001380 // Test touch down on second display.
1381 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1382 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001383 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1384 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001385 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001386}
1387
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001388TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001389 // Test inject a key down with display id specified.
1390 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1391 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001392 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001393 windowInSecondary->assertNoEvents();
1394
1395 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001396 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1397 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1398 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001399 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001400
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001401 // Remove all windows in secondary display.
1402 mDispatcher->setInputWindows({}, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001403
1404 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001405 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1406 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001407
1408 // Test inject a key down, should timeout because of no target window.
1409 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1410 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1411 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001412 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001413 windowInSecondary->assertNoEvents();
1414}
1415
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001416// Test per-display input monitors for motion event.
1417TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001418 FakeMonitorReceiver monitorInPrimary =
1419 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1420 FakeMonitorReceiver monitorInSecondary =
1421 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001422
1423 // Test touch down on primary display.
1424 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1425 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1426 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001427 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001428 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001429 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001430 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001431
1432 // Test touch down on second display.
1433 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1434 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1435 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1436 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001437 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001438 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001439 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001440
1441 // Test inject a non-pointer motion event.
1442 // If specific a display, it will dispatch to the focused window of particular display,
1443 // or it will dispatch to the focused window of focused display.
1444 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1445 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1446 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1447 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001448 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001449 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001450 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001451}
1452
1453// Test per-display input monitors for key event.
1454TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1455 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001456 FakeMonitorReceiver monitorInPrimary =
1457 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1458 FakeMonitorReceiver monitorInSecondary =
1459 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001460
1461 // Test inject a key down.
1462 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1463 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1464 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001465 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001466 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001467 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001468}
1469
Jackal Guof9696682018-10-05 12:23:23 +08001470class InputFilterTest : public InputDispatcherTest {
1471protected:
1472 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1473
1474 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1475 NotifyMotionArgs motionArgs;
1476
1477 motionArgs = generateMotionArgs(
1478 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1479 mDispatcher->notifyMotion(&motionArgs);
1480 motionArgs = generateMotionArgs(
1481 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1482 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001483 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001484 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001485 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001486 } else {
1487 mFakePolicy->assertFilterInputEventWasNotCalled();
1488 }
1489 }
1490
1491 void testNotifyKey(bool expectToBeFiltered) {
1492 NotifyKeyArgs keyArgs;
1493
1494 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1495 mDispatcher->notifyKey(&keyArgs);
1496 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1497 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001498 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001499
1500 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001501 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001502 } else {
1503 mFakePolicy->assertFilterInputEventWasNotCalled();
1504 }
1505 }
1506};
1507
1508// Test InputFilter for MotionEvent
1509TEST_F(InputFilterTest, MotionEvent_InputFilter) {
1510 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
1511 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1512 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1513
1514 // Enable InputFilter
1515 mDispatcher->setInputFilterEnabled(true);
1516 // Test touch on both primary and second display, and check if both events are filtered.
1517 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
1518 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
1519
1520 // Disable InputFilter
1521 mDispatcher->setInputFilterEnabled(false);
1522 // Test touch on both primary and second display, and check if both events aren't filtered.
1523 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1524 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1525}
1526
1527// Test InputFilter for KeyEvent
1528TEST_F(InputFilterTest, KeyEvent_InputFilter) {
1529 // Since the InputFilter is disabled by default, check if key event aren't filtered.
1530 testNotifyKey(/*expectToBeFiltered*/ false);
1531
1532 // Enable InputFilter
1533 mDispatcher->setInputFilterEnabled(true);
1534 // Send a key event, and check if it is filtered.
1535 testNotifyKey(/*expectToBeFiltered*/ true);
1536
1537 // Disable InputFilter
1538 mDispatcher->setInputFilterEnabled(false);
1539 // Send a key event, and check if it isn't filtered.
1540 testNotifyKey(/*expectToBeFiltered*/ false);
1541}
1542
chaviwfd6d3512019-03-25 13:23:49 -07001543class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001544 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07001545 InputDispatcherTest::SetUp();
1546
1547 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1548 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
1549 ADISPLAY_ID_DEFAULT);
1550 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1551 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1552 // window.
1553 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1554
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001555 mFocusedWindow =
1556 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1557 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
1558 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1559 mFocusedWindowTouchPoint = 60;
chaviwfd6d3512019-03-25 13:23:49 -07001560
1561 // Set focused application.
1562 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001563 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07001564
1565 // Expect one focus window exist in display.
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001566 mDispatcher->setInputWindows({mUnfocusedWindow, mFocusedWindow}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001567 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07001568 }
1569
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001570 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07001571 InputDispatcherTest::TearDown();
1572
1573 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001574 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07001575 }
1576
1577protected:
1578 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001579 sp<FakeWindowHandle> mFocusedWindow;
1580 int32_t mFocusedWindowTouchPoint;
chaviwfd6d3512019-03-25 13:23:49 -07001581};
1582
1583// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1584// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1585// the onPointerDownOutsideFocus callback.
1586TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
1587 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1588 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
1589 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001590
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001591 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07001592 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1593}
1594
1595// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1596// DOWN on the window that doesn't have focus. Ensure no window received the
1597// onPointerDownOutsideFocus callback.
1598TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
1599 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1600 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
1601 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001602
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001603 ASSERT_TRUE(mDispatcher->waitForIdle());
1604 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001605}
1606
1607// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1608// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1609TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1610 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1611 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001612
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001613 ASSERT_TRUE(mDispatcher->waitForIdle());
1614 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001615}
1616
1617// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1618// DOWN on the window that already has focus. Ensure no window received the
1619// onPointerDownOutsideFocus callback.
1620TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1621 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001622 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1623 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1624 mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
chaviwfd6d3512019-03-25 13:23:49 -07001625 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001626
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001627 ASSERT_TRUE(mDispatcher->waitForIdle());
1628 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001629}
1630
chaviwaf87b3e2019-10-01 16:59:28 -07001631// These tests ensures we can send touch events to a single client when there are multiple input
1632// windows that point to the same client token.
1633class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
1634 virtual void SetUp() override {
1635 InputDispatcherTest::SetUp();
1636
1637 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1638 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
1639 ADISPLAY_ID_DEFAULT);
1640 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
1641 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
1642 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1643 InputWindowInfo::FLAG_SPLIT_TOUCH);
1644 mWindow1->setId(0);
1645 mWindow1->setFrame(Rect(0, 0, 100, 100));
1646
1647 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
1648 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
1649 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1650 InputWindowInfo::FLAG_SPLIT_TOUCH);
1651 mWindow2->setId(1);
1652 mWindow2->setFrame(Rect(100, 100, 200, 200));
1653
1654 mDispatcher->setInputWindows({mWindow1, mWindow2}, ADISPLAY_ID_DEFAULT);
1655 }
1656
1657protected:
1658 sp<FakeWindowHandle> mWindow1;
1659 sp<FakeWindowHandle> mWindow2;
1660
1661 // Helper function to convert the point from screen coordinates into the window's space
1662 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
1663 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
1664 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
1665 return {x, y};
1666 }
1667
1668 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
1669 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001670 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07001671 InputEvent* event = window->consume();
1672
1673 ASSERT_NE(nullptr, event) << name.c_str()
1674 << ": consumer should have returned non-NULL event.";
1675
1676 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
1677 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
1678 << " event, got " << inputEventTypeToString(event->getType()) << " event";
1679
1680 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
1681 EXPECT_EQ(expectedAction, motionEvent.getAction());
1682
1683 for (size_t i = 0; i < points.size(); i++) {
1684 float expectedX = points[i].x;
1685 float expectedY = points[i].y;
1686
1687 EXPECT_EQ(expectedX, motionEvent.getX(i))
1688 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
1689 << ", got " << motionEvent.getX(i);
1690 EXPECT_EQ(expectedY, motionEvent.getY(i))
1691 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
1692 << ", got " << motionEvent.getY(i);
1693 }
1694 }
1695};
1696
1697TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
1698 // Touch Window 1
1699 PointF touchedPoint = {10, 10};
1700 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
1701
1702 NotifyMotionArgs motionArgs =
1703 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1704 ADISPLAY_ID_DEFAULT, {touchedPoint});
1705 mDispatcher->notifyMotion(&motionArgs);
1706 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1707
1708 // Release touch on Window 1
1709 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1710 ADISPLAY_ID_DEFAULT, {touchedPoint});
1711 mDispatcher->notifyMotion(&motionArgs);
1712 // consume the UP event
1713 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
1714
1715 // Touch Window 2
1716 touchedPoint = {150, 150};
1717 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
1718
1719 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1720 ADISPLAY_ID_DEFAULT, {touchedPoint});
1721 mDispatcher->notifyMotion(&motionArgs);
1722
1723 // Consuming from window1 since it's the window that has the InputReceiver
1724 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1725}
1726
1727TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
1728 mWindow2->setWindowScale(0.5f, 0.5f);
1729
1730 // Touch Window 1
1731 PointF touchedPoint = {10, 10};
1732 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
1733
1734 NotifyMotionArgs motionArgs =
1735 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1736 ADISPLAY_ID_DEFAULT, {touchedPoint});
1737 mDispatcher->notifyMotion(&motionArgs);
1738 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1739
1740 // Release touch on Window 1
1741 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1742 ADISPLAY_ID_DEFAULT, {touchedPoint});
1743 mDispatcher->notifyMotion(&motionArgs);
1744 // consume the UP event
1745 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
1746
1747 // Touch Window 2
1748 touchedPoint = {150, 150};
1749 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
1750
1751 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1752 ADISPLAY_ID_DEFAULT, {touchedPoint});
1753 mDispatcher->notifyMotion(&motionArgs);
1754
1755 // Consuming from window1 since it's the window that has the InputReceiver
1756 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1757}
1758
Chavi Weingarten65f98b82020-01-16 18:56:50 +00001759TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
1760 mWindow2->setWindowScale(0.5f, 0.5f);
1761
1762 // Touch Window 1
1763 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1764 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1765
1766 NotifyMotionArgs motionArgs =
1767 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1768 ADISPLAY_ID_DEFAULT, touchedPoints);
1769 mDispatcher->notifyMotion(&motionArgs);
1770 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1771
1772 // Touch Window 2
1773 int32_t actionPointerDown =
1774 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1775 touchedPoints.emplace_back(PointF{150, 150});
1776 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1777
1778 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1779 ADISPLAY_ID_DEFAULT, touchedPoints);
1780 mDispatcher->notifyMotion(&motionArgs);
1781
1782 // Consuming from window1 since it's the window that has the InputReceiver
1783 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1784}
1785
1786TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
1787 mWindow2->setWindowScale(0.5f, 0.5f);
1788
1789 // Touch Window 1
1790 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1791 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1792
1793 NotifyMotionArgs motionArgs =
1794 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1795 ADISPLAY_ID_DEFAULT, touchedPoints);
1796 mDispatcher->notifyMotion(&motionArgs);
1797 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1798
1799 // Touch Window 2
1800 int32_t actionPointerDown =
1801 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1802 touchedPoints.emplace_back(PointF{150, 150});
1803 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1804
1805 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1806 ADISPLAY_ID_DEFAULT, touchedPoints);
1807 mDispatcher->notifyMotion(&motionArgs);
1808
1809 // Consuming from window1 since it's the window that has the InputReceiver
1810 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1811
1812 // Move both windows
1813 touchedPoints = {{20, 20}, {175, 175}};
1814 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
1815 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
1816
1817 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1818 ADISPLAY_ID_DEFAULT, touchedPoints);
1819 mDispatcher->notifyMotion(&motionArgs);
1820
1821 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
1822}
1823
1824TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
1825 mWindow1->setWindowScale(0.5f, 0.5f);
1826
1827 // Touch Window 1
1828 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1829 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1830
1831 NotifyMotionArgs motionArgs =
1832 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1833 ADISPLAY_ID_DEFAULT, touchedPoints);
1834 mDispatcher->notifyMotion(&motionArgs);
1835 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1836
1837 // Touch Window 2
1838 int32_t actionPointerDown =
1839 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1840 touchedPoints.emplace_back(PointF{150, 150});
1841 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1842
1843 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1844 ADISPLAY_ID_DEFAULT, touchedPoints);
1845 mDispatcher->notifyMotion(&motionArgs);
1846
1847 // Consuming from window1 since it's the window that has the InputReceiver
1848 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1849
1850 // Move both windows
1851 touchedPoints = {{20, 20}, {175, 175}};
1852 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
1853 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
1854
1855 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1856 ADISPLAY_ID_DEFAULT, touchedPoints);
1857 mDispatcher->notifyMotion(&motionArgs);
1858
1859 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
1860}
1861
Garfield Tane84e6f92019-08-29 17:28:41 -07001862} // namespace android::inputdispatcher