blob: e17ee3a5d929a13437aec32cd15cdc8755d28299 [file] [log] [blame]
Prabir Pradhan81e89fe2024-03-20 21:17:09 +00001/*
2 * Copyright 2024 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
17#include "FakeInputDispatcherPolicy.h"
18
19#include <gtest/gtest.h>
20
21namespace android {
22
23// --- FakeInputDispatcherPolicy ---
24
25void FakeInputDispatcherPolicy::assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
26 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
27 ASSERT_EQ(event.getType(), InputEventType::KEY);
28 EXPECT_EQ(event.getDisplayId(), args.displayId);
29
30 const auto& keyEvent = static_cast<const KeyEvent&>(event);
31 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
32 EXPECT_EQ(keyEvent.getAction(), args.action);
33 });
34}
35
36void FakeInputDispatcherPolicy::assertFilterInputEventWasCalled(const NotifyMotionArgs& args,
37 vec2 point) {
38 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
39 ASSERT_EQ(event.getType(), InputEventType::MOTION);
40 EXPECT_EQ(event.getDisplayId(), args.displayId);
41
42 const auto& motionEvent = static_cast<const MotionEvent&>(event);
43 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
44 EXPECT_EQ(motionEvent.getAction(), args.action);
45 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
46 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
47 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
48 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
49 });
50}
51
52void FakeInputDispatcherPolicy::assertFilterInputEventWasNotCalled() {
53 std::scoped_lock lock(mLock);
54 ASSERT_EQ(nullptr, mFilteredEvent);
55}
56
57void FakeInputDispatcherPolicy::assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
58 std::scoped_lock lock(mLock);
59 ASSERT_TRUE(mConfigurationChangedTime) << "Timed out waiting for configuration changed call";
60 ASSERT_EQ(*mConfigurationChangedTime, when);
61 mConfigurationChangedTime = std::nullopt;
62}
63
64void FakeInputDispatcherPolicy::assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
65 std::scoped_lock lock(mLock);
66 ASSERT_TRUE(mLastNotifySwitch);
67 // We do not check id because it is not exposed to the policy
68 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
69 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
70 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
71 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
72 mLastNotifySwitch = std::nullopt;
73}
74
75void FakeInputDispatcherPolicy::assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
76 std::scoped_lock lock(mLock);
77 ASSERT_EQ(touchedToken, mOnPointerDownToken);
78 mOnPointerDownToken.clear();
79}
80
81void FakeInputDispatcherPolicy::assertOnPointerDownWasNotCalled() {
82 std::scoped_lock lock(mLock);
83 ASSERT_TRUE(mOnPointerDownToken == nullptr)
84 << "Expected onPointerDownOutsideFocus to not have been called";
85}
86
87void FakeInputDispatcherPolicy::assertNotifyNoFocusedWindowAnrWasCalled(
88 std::chrono::nanoseconds timeout,
89 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
90 std::unique_lock lock(mLock);
91 android::base::ScopedLockAssertion assumeLocked(mLock);
92 std::shared_ptr<InputApplicationHandle> application;
93 ASSERT_NO_FATAL_FAILURE(
94 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
95 ASSERT_EQ(expectedApplication, application);
96}
97
98void FakeInputDispatcherPolicy::assertNotifyWindowUnresponsiveWasCalled(
99 std::chrono::nanoseconds timeout, const sp<gui::WindowInfoHandle>& window) {
100 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
101 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
102 window->getInfo()->ownerPid);
103}
104
105void FakeInputDispatcherPolicy::assertNotifyWindowUnresponsiveWasCalled(
106 std::chrono::nanoseconds timeout, const sp<IBinder>& expectedToken,
107 std::optional<gui::Pid> expectedPid) {
108 std::unique_lock lock(mLock);
109 android::base::ScopedLockAssertion assumeLocked(mLock);
110 AnrResult result;
111 ASSERT_NO_FATAL_FAILURE(result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
112 ASSERT_EQ(expectedToken, result.token);
113 ASSERT_EQ(expectedPid, result.pid);
114}
115
116sp<IBinder> FakeInputDispatcherPolicy::getUnresponsiveWindowToken(
117 std::chrono::nanoseconds timeout) {
118 std::unique_lock lock(mLock);
119 android::base::ScopedLockAssertion assumeLocked(mLock);
120 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
121 const auto& [token, _] = result;
122 return token;
123}
124
125void FakeInputDispatcherPolicy::assertNotifyWindowResponsiveWasCalled(
126 const sp<IBinder>& expectedToken, std::optional<gui::Pid> expectedPid) {
127 std::unique_lock lock(mLock);
128 android::base::ScopedLockAssertion assumeLocked(mLock);
129 AnrResult result;
130 ASSERT_NO_FATAL_FAILURE(result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
131 ASSERT_EQ(expectedToken, result.token);
132 ASSERT_EQ(expectedPid, result.pid);
133}
134
135sp<IBinder> FakeInputDispatcherPolicy::getResponsiveWindowToken() {
136 std::unique_lock lock(mLock);
137 android::base::ScopedLockAssertion assumeLocked(mLock);
138 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
139 const auto& [token, _] = result;
140 return token;
141}
142
143void FakeInputDispatcherPolicy::assertNotifyAnrWasNotCalled() {
144 std::scoped_lock lock(mLock);
145 ASSERT_TRUE(mAnrApplications.empty());
146 ASSERT_TRUE(mAnrWindows.empty());
147 ASSERT_TRUE(mResponsiveWindows.empty())
148 << "ANR was not called, but please also consume the 'connection is responsive' "
149 "signal";
150}
151
152PointerCaptureRequest FakeInputDispatcherPolicy::assertSetPointerCaptureCalled(
153 const sp<gui::WindowInfoHandle>& window, bool enabled) {
154 std::unique_lock lock(mLock);
155 base::ScopedLockAssertion assumeLocked(mLock);
156
157 if (!mPointerCaptureChangedCondition
158 .wait_for(lock, 100ms, [this, enabled, window]() REQUIRES(mLock) {
159 if (enabled) {
160 return mPointerCaptureRequest->isEnable() &&
161 mPointerCaptureRequest->window == window->getToken();
162 } else {
163 return !mPointerCaptureRequest->isEnable();
164 }
165 })) {
166 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << window->getName() << ", "
167 << enabled << ") to be called.";
168 return {};
169 }
170 auto request = *mPointerCaptureRequest;
171 mPointerCaptureRequest.reset();
172 return request;
173}
174
175void FakeInputDispatcherPolicy::assertSetPointerCaptureNotCalled() {
176 std::unique_lock lock(mLock);
177 base::ScopedLockAssertion assumeLocked(mLock);
178
179 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
180 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
181 "enabled = "
182 << std::to_string(mPointerCaptureRequest->isEnable());
183 }
184 mPointerCaptureRequest.reset();
185}
186
187void FakeInputDispatcherPolicy::assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
188 const sp<IBinder>& targetToken) {
189 dispatcher.waitForIdle();
190 std::scoped_lock lock(mLock);
191 ASSERT_TRUE(mNotifyDropWindowWasCalled);
192 ASSERT_EQ(targetToken, mDropTargetWindowToken);
193 mNotifyDropWindowWasCalled = false;
194}
195
196void FakeInputDispatcherPolicy::assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
197 std::unique_lock lock(mLock);
198 base::ScopedLockAssertion assumeLocked(mLock);
199 std::optional<sp<IBinder>> receivedToken =
200 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
201 mNotifyInputChannelBroken);
202 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
203 ASSERT_EQ(token, *receivedToken);
204}
205
206void FakeInputDispatcherPolicy::setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
207 mInterceptKeyTimeout = timeout;
208}
209
210std::chrono::nanoseconds FakeInputDispatcherPolicy::getKeyWaitingForEventsTimeout() {
211 return 500ms;
212}
213
214void FakeInputDispatcherPolicy::setStaleEventTimeout(std::chrono::nanoseconds timeout) {
215 mStaleEventTimeout = timeout;
216}
217
Josep del Rioc8fdedb2024-05-21 13:32:43 +0000218void FakeInputDispatcherPolicy::setConsumeKeyBeforeDispatching(bool consumeKeyBeforeDispatching) {
219 mConsumeKeyBeforeDispatching = consumeKeyBeforeDispatching;
220}
221
Prabir Pradhan81e89fe2024-03-20 21:17:09 +0000222void FakeInputDispatcherPolicy::assertUserActivityNotPoked() {
223 std::unique_lock lock(mLock);
224 base::ScopedLockAssertion assumeLocked(mLock);
225
226 std::optional<UserActivityPokeEvent> pokeEvent =
227 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
228 mNotifyUserActivity);
229
230 ASSERT_FALSE(pokeEvent) << "Expected user activity not to have been poked";
231}
232
233void FakeInputDispatcherPolicy::assertUserActivityPoked(
234 std::optional<UserActivityPokeEvent> expectedPokeEvent) {
235 std::unique_lock lock(mLock);
236 base::ScopedLockAssertion assumeLocked(mLock);
237
238 std::optional<UserActivityPokeEvent> pokeEvent =
239 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
240 mNotifyUserActivity);
241 ASSERT_TRUE(pokeEvent) << "Expected a user poke event";
242
243 if (expectedPokeEvent) {
244 ASSERT_EQ(expectedPokeEvent, *pokeEvent);
245 }
246}
247
248void FakeInputDispatcherPolicy::assertNotifyDeviceInteractionWasCalled(int32_t deviceId,
249 std::set<gui::Uid> uids) {
250 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
251}
252
253void FakeInputDispatcherPolicy::assertNotifyDeviceInteractionWasNotCalled() {
254 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
255}
256
257void FakeInputDispatcherPolicy::setUnhandledKeyHandler(
258 std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
259 std::scoped_lock lock(mLock);
260 mUnhandledKeyHandler = handler;
261}
262
263void FakeInputDispatcherPolicy::assertUnhandledKeyReported(int32_t keycode) {
264 std::unique_lock lock(mLock);
265 base::ScopedLockAssertion assumeLocked(mLock);
266 std::optional<int32_t> unhandledKeycode =
267 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
268 mNotifyUnhandledKey);
269 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
270 ASSERT_EQ(unhandledKeycode, keycode);
271}
272
273void FakeInputDispatcherPolicy::assertUnhandledKeyNotReported() {
274 std::unique_lock lock(mLock);
275 base::ScopedLockAssertion assumeLocked(mLock);
276 std::optional<int32_t> unhandledKeycode =
277 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
278 mNotifyUnhandledKey);
279 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
280}
281
282template <class T>
283T FakeInputDispatcherPolicy::getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout,
284 std::queue<T>& storage,
285 std::unique_lock<std::mutex>& lock)
286 REQUIRES(mLock) {
287 // If there is an ANR, Dispatcher won't be idle because there are still events
288 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
289 // before checking if ANR was called.
290 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
291 // to provide it some time to act. 100ms seems reasonable.
292 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
293 const std::chrono::time_point start = std::chrono::steady_clock::now();
294 std::optional<T> token =
295 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
296 if (!token.has_value()) {
297 ADD_FAILURE() << "Did not receive the ANR callback";
298 return {};
299 }
300
301 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
302 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
303 // the dispatcher started counting before this function was called
304 if (std::chrono::abs(timeout - waited) > 100ms) {
305 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
306 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
307 << "ms, but waited "
308 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
309 << "ms instead";
310 }
311 return *token;
312}
313
314template <class T>
315std::optional<T> FakeInputDispatcherPolicy::getItemFromStorageLockedInterruptible(
316 std::chrono::nanoseconds timeout, std::queue<T>& storage,
317 std::unique_lock<std::mutex>& lock, std::condition_variable& condition) REQUIRES(mLock) {
318 condition.wait_for(lock, timeout, [&storage]() REQUIRES(mLock) { return !storage.empty(); });
319 if (storage.empty()) {
320 return std::nullopt;
321 }
322 T item = storage.front();
323 storage.pop();
324 return std::make_optional(item);
325}
326
327void FakeInputDispatcherPolicy::notifyConfigurationChanged(nsecs_t when) {
328 std::scoped_lock lock(mLock);
329 mConfigurationChangedTime = when;
330}
331
332void FakeInputDispatcherPolicy::notifyWindowUnresponsive(const sp<IBinder>& connectionToken,
333 std::optional<gui::Pid> pid,
334 const std::string&) {
335 std::scoped_lock lock(mLock);
336 mAnrWindows.push({connectionToken, pid});
337 mNotifyAnr.notify_all();
338}
339
340void FakeInputDispatcherPolicy::notifyWindowResponsive(const sp<IBinder>& connectionToken,
341 std::optional<gui::Pid> pid) {
342 std::scoped_lock lock(mLock);
343 mResponsiveWindows.push({connectionToken, pid});
344 mNotifyAnr.notify_all();
345}
346
347void FakeInputDispatcherPolicy::notifyNoFocusedWindowAnr(
348 const std::shared_ptr<InputApplicationHandle>& applicationHandle) {
349 std::scoped_lock lock(mLock);
350 mAnrApplications.push(applicationHandle);
351 mNotifyAnr.notify_all();
352}
353
354void FakeInputDispatcherPolicy::notifyInputChannelBroken(const sp<IBinder>& connectionToken) {
355 std::scoped_lock lock(mLock);
356 mBrokenInputChannels.push(connectionToken);
357 mNotifyInputChannelBroken.notify_all();
358}
359
360void FakeInputDispatcherPolicy::notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {}
361
362void FakeInputDispatcherPolicy::notifySensorEvent(int32_t deviceId,
363 InputDeviceSensorType sensorType,
364 InputDeviceSensorAccuracy accuracy,
365 nsecs_t timestamp,
366 const std::vector<float>& values) {}
367
368void FakeInputDispatcherPolicy::notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
369 InputDeviceSensorAccuracy accuracy) {}
370
371void FakeInputDispatcherPolicy::notifyVibratorState(int32_t deviceId, bool isOn) {}
372
373bool FakeInputDispatcherPolicy::filterInputEvent(const InputEvent& inputEvent,
374 uint32_t policyFlags) {
375 std::scoped_lock lock(mLock);
376 switch (inputEvent.getType()) {
377 case InputEventType::KEY: {
378 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
379 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
380 break;
381 }
382
383 case InputEventType::MOTION: {
384 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
385 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
386 break;
387 }
388 default: {
389 ADD_FAILURE() << "Should only filter keys or motions";
390 break;
391 }
392 }
393 return true;
394}
395
396void FakeInputDispatcherPolicy::interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) {
397 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
398 // Clear intercept state when we handled the event.
399 mInterceptKeyTimeout = 0ms;
400 }
401}
402
Linnan Li13bf76a2024-05-05 19:18:02 +0800403void FakeInputDispatcherPolicy::interceptMotionBeforeQueueing(ui::LogicalDisplayId, uint32_t,
404 int32_t, nsecs_t, uint32_t&) {}
Prabir Pradhan81e89fe2024-03-20 21:17:09 +0000405
406nsecs_t FakeInputDispatcherPolicy::interceptKeyBeforeDispatching(const sp<IBinder>&,
407 const KeyEvent&, uint32_t) {
Josep del Rioc8fdedb2024-05-21 13:32:43 +0000408 if (mConsumeKeyBeforeDispatching) {
409 return -1;
410 }
Prabir Pradhan81e89fe2024-03-20 21:17:09 +0000411 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
412 // Clear intercept state so we could dispatch the event in next wake.
413 mInterceptKeyTimeout = 0ms;
414 return delay;
415}
416
417std::optional<KeyEvent> FakeInputDispatcherPolicy::dispatchUnhandledKey(const sp<IBinder>&,
418 const KeyEvent& event,
419 uint32_t) {
420 std::scoped_lock lock(mLock);
421 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
422 mNotifyUnhandledKey.notify_all();
423 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
424}
425
426void FakeInputDispatcherPolicy::notifySwitch(nsecs_t when, uint32_t switchValues,
427 uint32_t switchMask, uint32_t policyFlags) {
428 std::scoped_lock lock(mLock);
429 // We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
430 // essentially a passthrough for notifySwitch.
431 mLastNotifySwitch =
432 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
433}
434
435void FakeInputDispatcherPolicy::pokeUserActivity(nsecs_t eventTime, int32_t eventType,
Linnan Li13bf76a2024-05-05 19:18:02 +0800436 ui::LogicalDisplayId displayId) {
Prabir Pradhan81e89fe2024-03-20 21:17:09 +0000437 std::scoped_lock lock(mLock);
438 mNotifyUserActivity.notify_all();
439 mUserActivityPokeEvents.push({eventTime, eventType, displayId});
440}
441
442bool FakeInputDispatcherPolicy::isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) {
443 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
444}
445
446void FakeInputDispatcherPolicy::onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
447 std::scoped_lock lock(mLock);
448 mOnPointerDownToken = newToken;
449}
450
451void FakeInputDispatcherPolicy::setPointerCapture(const PointerCaptureRequest& request) {
452 std::scoped_lock lock(mLock);
453 mPointerCaptureRequest = {request};
454 mPointerCaptureChangedCondition.notify_all();
455}
456
457void FakeInputDispatcherPolicy::notifyDropWindow(const sp<IBinder>& token, float x, float y) {
458 std::scoped_lock lock(mLock);
459 mNotifyDropWindowWasCalled = true;
460 mDropTargetWindowToken = token;
461}
462
463void FakeInputDispatcherPolicy::notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
464 const std::set<gui::Uid>& uids) {
465 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
466}
467
468void FakeInputDispatcherPolicy::assertFilterInputEventWasCalledInternal(
469 const std::function<void(const InputEvent&)>& verify) {
470 std::scoped_lock lock(mLock);
471 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
472 verify(*mFilteredEvent);
473 mFilteredEvent = nullptr;
474}
475
Prabir Pradhan81e89fe2024-03-20 21:17:09 +0000476} // namespace android