blob: fe25130bd82e95a964e0cbdea1891b2ee369e076 [file] [log] [blame]
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001/*
2 * Copyright 2023 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#pragma once
18
19#include <android-base/logging.h>
20#include "../dispatcher/InputDispatcher.h"
21
22using android::base::Result;
23using android::gui::Pid;
24using android::gui::TouchOcclusionMode;
25using android::gui::Uid;
26using android::gui::WindowInfo;
27using android::gui::WindowInfoHandle;
28
29namespace android {
30namespace inputdispatcher {
31
32namespace {
33
34// The default pid and uid for windows created by the test.
35constexpr gui::Pid WINDOW_PID{999};
36constexpr gui::Uid WINDOW_UID{1001};
37
38static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 100ms;
39
40} // namespace
41
42class FakeInputReceiver {
43public:
44 std::unique_ptr<InputEvent> consumeEvent(std::chrono::milliseconds timeout) {
45 uint32_t consumeSeq = 0;
46 std::unique_ptr<InputEvent> event;
47
48 std::chrono::time_point start = std::chrono::steady_clock::now();
49 status_t result = WOULD_BLOCK;
50 while (result == WOULD_BLOCK) {
51 InputEvent* rawEventPtr = nullptr;
52 result = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
53 &rawEventPtr);
54 event = std::unique_ptr<InputEvent>(rawEventPtr);
55 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
56 if (elapsed > timeout) {
57 if (timeout != 0ms) {
58 LOG(ERROR) << "Waited too long for consumer to produce an event, giving up";
59 }
60 break;
61 }
62 }
63 // Events produced by this factory are owned pointers.
64 if (result != OK) {
65 if (timeout == 0ms) {
66 // This is likely expected. No need to log.
67 } else {
68 LOG(ERROR) << "Received result = " << result << " from consume";
69 }
70 return nullptr;
71 }
72 result = mConsumer.sendFinishedSignal(consumeSeq, true);
73 if (result != OK) {
74 LOG(ERROR) << "Received result = " << result << " from sendFinishedSignal";
75 }
76 return event;
77 }
78
79 explicit FakeInputReceiver(std::unique_ptr<InputChannel> channel, const std::string name)
80 : mConsumer(std::move(channel)) {}
81
82 virtual ~FakeInputReceiver() {}
83
84private:
85 std::unique_ptr<InputChannel> mClientChannel;
86 InputConsumer mConsumer;
87 DynamicInputEventFactory mEventFactory;
88};
89
90class FakeWindowHandle : public WindowInfoHandle {
91public:
92 static const int32_t WIDTH = 600;
93 static const int32_t HEIGHT = 800;
94
95 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
96 InputDispatcher& dispatcher, const std::string name, int32_t displayId)
97 : mName(name) {
98 Result<std::unique_ptr<InputChannel>> channel = dispatcher.createInputChannel(name);
99 mInfo.token = (*channel)->getConnectionToken();
100 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
101
102 inputApplicationHandle->updateInfo();
103 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
104
105 mInfo.id = sId++;
106 mInfo.name = name;
107 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
108 mInfo.alpha = 1.0;
109 mInfo.frame.left = 0;
110 mInfo.frame.top = 0;
111 mInfo.frame.right = WIDTH;
112 mInfo.frame.bottom = HEIGHT;
113 mInfo.transform.set(0, 0);
114 mInfo.globalScaleFactor = 1.0;
115 mInfo.touchableRegion.clear();
116 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
117 mInfo.ownerPid = WINDOW_PID;
118 mInfo.ownerUid = WINDOW_UID;
119 mInfo.displayId = displayId;
120 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
121 }
122
123 sp<FakeWindowHandle> clone(int32_t displayId) {
124 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
125 handle->mInfo = mInfo;
126 handle->mInfo.displayId = displayId;
127 handle->mInfo.id = sId++;
128 handle->mInputReceiver = mInputReceiver;
129 return handle;
130 }
131
132 void setTouchable(bool touchable) {
133 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
134 }
135
136 void setFocusable(bool focusable) {
137 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
138 }
139
140 void setVisible(bool visible) {
141 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
142 }
143
144 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
145 mInfo.dispatchingTimeout = timeout;
146 }
147
148 void setPaused(bool paused) {
149 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
150 }
151
152 void setPreventSplitting(bool preventSplitting) {
153 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
154 }
155
156 void setSlippery(bool slippery) {
157 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
158 }
159
160 void setWatchOutsideTouch(bool watchOutside) {
161 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
162 }
163
164 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
165
166 void setInterceptsStylus(bool interceptsStylus) {
167 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
168 }
169
170 void setDropInput(bool dropInput) {
171 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
172 }
173
174 void setDropInputIfObscured(bool dropInputIfObscured) {
175 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
176 }
177
178 void setNoInputChannel(bool noInputChannel) {
179 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
180 }
181
182 void setDisableUserActivity(bool disableUserActivity) {
183 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
184 }
185
186 void setAlpha(float alpha) { mInfo.alpha = alpha; }
187
188 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
189
190 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
191
192 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
193 mInfo.frame.left = frame.left;
194 mInfo.frame.top = frame.top;
195 mInfo.frame.right = frame.right;
196 mInfo.frame.bottom = frame.bottom;
197 mInfo.touchableRegion.clear();
198 mInfo.addTouchableRegion(frame);
199
200 const Rect logicalDisplayFrame = displayTransform.transform(frame);
201 ui::Transform translate;
202 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
203 mInfo.transform = translate * displayTransform;
204 }
205
206 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
207
208 void setIsWallpaper(bool isWallpaper) {
209 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
210 }
211
212 void setDupTouchToWallpaper(bool hasWallpaper) {
213 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
214 }
215
216 void setTrustedOverlay(bool trustedOverlay) {
217 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
218 }
219
220 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
221 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
222 }
223
224 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
225
226 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
227
228 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout) {
229 if (mInputReceiver == nullptr) {
230 return nullptr;
231 }
232 return mInputReceiver->consumeEvent(timeout);
233 }
234
235 void consumeMotion() {
236 std::unique_ptr<InputEvent> event = consume(100ms);
237
238 if (event == nullptr) {
239 LOG(FATAL) << mName << ": expected a MotionEvent, but didn't get one.";
240 return;
241 }
242
243 if (event->getType() != InputEventType::MOTION) {
244 LOG(FATAL) << mName << " expected a MotionEvent, got " << *event;
245 return;
246 }
247 }
248
249 sp<IBinder> getToken() { return mInfo.token; }
250
251 const std::string& getName() { return mName; }
252
253 void setOwnerInfo(Pid ownerPid, Uid ownerUid) {
254 mInfo.ownerPid = ownerPid;
255 mInfo.ownerUid = ownerUid;
256 }
257
258 Pid getPid() const { return mInfo.ownerPid; }
259
260 void destroyReceiver() { mInputReceiver = nullptr; }
261
262private:
263 FakeWindowHandle(std::string name) : mName(name){};
264 const std::string mName;
265 std::shared_ptr<FakeInputReceiver> mInputReceiver;
266 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
267 friend class sp<FakeWindowHandle>;
268};
269
270std::atomic<int32_t> FakeWindowHandle::sId{1};
271
272} // namespace inputdispatcher
273
274} // namespace android