blob: 8d36ba7b70b6e781e079197046bf4fa2d2cdcde6 [file] [log] [blame]
Robert Carr1c4c5592018-09-24 13:18:43 -07001/*
2 * Copyright 2018 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 <gtest/gtest.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <sys/time.h>
21#include <sys/types.h>
22#include <stdio.h>
23#include <poll.h>
24
25#include <memory>
26
Vishnu Nairde19f852018-12-18 16:11:53 -080027#include <android/native_window.h>
28
Robert Carr1c4c5592018-09-24 13:18:43 -070029#include <binder/Binder.h>
30#include <binder/IServiceManager.h>
31#include <binder/Parcel.h>
32#include <binder/ProcessState.h>
33
Vishnu Nairde19f852018-12-18 16:11:53 -080034#include <gui/ISurfaceComposer.h>
35#include <gui/Surface.h>
Robert Carr1c4c5592018-09-24 13:18:43 -070036#include <gui/SurfaceComposerClient.h>
37#include <gui/SurfaceControl.h>
38
39#include <input/InputWindow.h>
40#include <input/IInputFlinger.h>
41#include <input/InputTransport.h>
42#include <input/Input.h>
43
Vishnu Nairde19f852018-12-18 16:11:53 -080044#include <ui/DisplayInfo.h>
Robert Carr1c4c5592018-09-24 13:18:43 -070045#include <ui/Rect.h>
46#include <ui/Region.h>
47
48
49namespace android {
50namespace test {
51
Vishnu Nairde19f852018-12-18 16:11:53 -080052using Transaction = SurfaceComposerClient::Transaction;
53
Robert Carr1c4c5592018-09-24 13:18:43 -070054sp<IInputFlinger> getInputFlinger() {
55 sp<IBinder> input(defaultServiceManager()->getService(
56 String16("inputflinger")));
57 if (input == nullptr) {
58 ALOGE("Failed to link to input service");
59 } else { ALOGE("Linked to input"); }
60 return interface_cast<IInputFlinger>(input);
61}
62
63// We use the top 10 layers as a way to haphazardly place ourselves above anything else.
64static const int LAYER_BASE = INT32_MAX - 10;
65
66class InputSurface {
67public:
Vishnu Nairde19f852018-12-18 16:11:53 -080068 InputSurface(const sp<SurfaceControl> &sc, int width, int height) {
69 mSurfaceControl = sc;
Robert Carr1c4c5592018-09-24 13:18:43 -070070
71 InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
Robert Carr1c4c5592018-09-24 13:18:43 -070072
73 mInputFlinger = getInputFlinger();
74 mInputFlinger->registerInputChannel(mServerChannel);
75
76 populateInputInfo(width, height);
77
78 mInputConsumer = new InputConsumer(mClientChannel);
79 }
80
Vishnu Nairde19f852018-12-18 16:11:53 -080081 static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc,
82 int width, int height) {
83 sp<SurfaceControl> surfaceControl =
84 scc->createSurface(String8("Test Surface"), 0 /* bufHeight */, 0 /* bufWidth */,
85 PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor);
86 return std::make_unique<InputSurface>(surfaceControl, width, height);
87 }
88
89 static std::unique_ptr<InputSurface> makeBufferInputSurface(
90 const sp<SurfaceComposerClient> &scc, int width, int height) {
91 sp<SurfaceControl> surfaceControl =
92 scc->createSurface(String8("Test Buffer Surface"), width, height,
93 PIXEL_FORMAT_RGBA_8888, 0 /* flags */);
94 return std::make_unique<InputSurface>(surfaceControl, width, height);
95 }
96
97 static std::unique_ptr<InputSurface> makeContainerInputSurface(
98 const sp<SurfaceComposerClient> &scc, int width, int height) {
99 sp<SurfaceControl> surfaceControl =
100 scc->createSurface(String8("Test Container Surface"), 0 /* bufHeight */,
101 0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888,
102 ISurfaceComposerClient::eFXSurfaceContainer);
103 return std::make_unique<InputSurface>(surfaceControl, width, height);
104 }
105
Robert Carr1c4c5592018-09-24 13:18:43 -0700106 InputEvent* consumeEvent() {
107 waitForEventAvailable();
108
109 InputEvent *ev;
110 uint32_t seqId;
111 status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev);
112 if (consumed != OK) {
113 return nullptr;
114 }
115 mInputConsumer->sendFinishedSignal(seqId, true);
116 return ev;
117 }
118
119 void expectTap(int x, int y) {
120 InputEvent* ev = consumeEvent();
121 EXPECT_TRUE(ev != nullptr);
122 EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION);
123 MotionEvent* mev = static_cast<MotionEvent*>(ev);
124 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
125 EXPECT_EQ(x, mev->getX(0));
126 EXPECT_EQ(y, mev->getY(0));
127
128 ev = consumeEvent();
129 EXPECT_TRUE(ev != nullptr);
130 EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION);
131 mev = static_cast<MotionEvent*>(ev);
132 EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
133 }
134
135 ~InputSurface() {
136 mInputFlinger->unregisterInputChannel(mServerChannel);
137 }
138
139 void doTransaction(std::function<void(SurfaceComposerClient::Transaction&,
140 const sp<SurfaceControl>&)> transactionBody) {
141 SurfaceComposerClient::Transaction t;
142 transactionBody(t, mSurfaceControl);
143 t.apply(true);
144 }
145
146 void showAt(int x, int y) {
147 SurfaceComposerClient::Transaction t;
148 t.show(mSurfaceControl);
149 t.setInputWindowInfo(mSurfaceControl, mInputInfo);
150 t.setLayer(mSurfaceControl, LAYER_BASE);
151 t.setPosition(mSurfaceControl, x, y);
152 t.setCrop_legacy(mSurfaceControl, Rect(0, 0, 100, 100));
153 t.setAlpha(mSurfaceControl, 1);
154 t.apply(true);
155 }
156
157private:
158 void waitForEventAvailable() {
159 struct pollfd fd;
160
161 fd.fd = mClientChannel->getFd();
162 fd.events = POLLIN;
163 poll(&fd, 1, 3000);
164 }
165
166 void populateInputInfo(int width, int height) {
Siarhei Vishniakou26d3cfb2019-10-15 17:02:32 -0700167 mInputInfo.token = mServerChannel->getConnectionToken();
Robert Carr1c4c5592018-09-24 13:18:43 -0700168 mInputInfo.name = "Test info";
169 mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
170 mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION;
171 mInputInfo.dispatchingTimeout = 100000;
Robert Carre07e1032018-11-26 12:55:53 -0800172 mInputInfo.globalScaleFactor = 1.0;
Robert Carr1c4c5592018-09-24 13:18:43 -0700173 mInputInfo.canReceiveKeys = true;
174 mInputInfo.hasFocus = true;
175 mInputInfo.hasWallpaper = false;
176 mInputInfo.paused = false;
177
178 mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));
179
180 // TODO: Fill in from SF?
181 mInputInfo.ownerPid = 11111;
182 mInputInfo.ownerUid = 11111;
183 mInputInfo.inputFeatures = 0;
184 mInputInfo.displayId = 0;
Robert Carr740167f2018-10-11 19:03:41 -0700185
186 InputApplicationInfo aInfo;
187 aInfo.token = new BBinder();
188 aInfo.name = "Test app info";
189 aInfo.dispatchingTimeout = 100000;
190
191 mInputInfo.applicationInfo = aInfo;
Robert Carr1c4c5592018-09-24 13:18:43 -0700192 }
193public:
194 sp<SurfaceControl> mSurfaceControl;
195 sp<InputChannel> mServerChannel, mClientChannel;
196 sp<IInputFlinger> mInputFlinger;
197
198 InputWindowInfo mInputInfo;
199
200 PreallocatedInputEventFactory mInputEventFactory;
201 InputConsumer* mInputConsumer;
202};
203
204class InputSurfacesTest : public ::testing::Test {
205public:
206 InputSurfacesTest() {
207 ProcessState::self()->startThreadPool();
208 }
209
210 void SetUp() {
211 mComposerClient = new SurfaceComposerClient;
212 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
Vishnu Nairde19f852018-12-18 16:11:53 -0800213
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800214 const auto display = mComposerClient->getInternalDisplayToken();
215 ASSERT_FALSE(display == nullptr);
216
Vishnu Nairde19f852018-12-18 16:11:53 -0800217 DisplayInfo info;
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800218 ASSERT_EQ(NO_ERROR, mComposerClient->getDisplayInfo(display, &info));
Vishnu Nairde19f852018-12-18 16:11:53 -0800219
220 // After a new buffer is queued, SurfaceFlinger is notified and will
221 // latch the new buffer on next vsync. Let's heuristically wait for 3
222 // vsyncs.
223 mBufferPostDelay = int32_t(1e6 / info.fps) * 3;
Robert Carr1c4c5592018-09-24 13:18:43 -0700224 }
225
226 void TearDown() {
227 mComposerClient->dispose();
228 }
229
230 std::unique_ptr<InputSurface> makeSurface(int width, int height) {
Vishnu Nairde19f852018-12-18 16:11:53 -0800231 return InputSurface::makeColorInputSurface(mComposerClient, width, height);
232 }
233
234 void postBuffer(const sp<SurfaceControl> &layer) {
235 // wait for previous transactions (such as setSize) to complete
236 Transaction().apply(true);
237 ANativeWindow_Buffer buffer = {};
238 EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr));
239 ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost());
240 // Request an empty transaction to get applied synchronously to ensure the buffer is
241 // latched.
242 Transaction().apply(true);
243 usleep(mBufferPostDelay);
Robert Carr1c4c5592018-09-24 13:18:43 -0700244 }
245
246 sp<SurfaceComposerClient> mComposerClient;
Vishnu Nairde19f852018-12-18 16:11:53 -0800247 int32_t mBufferPostDelay;
Robert Carr1c4c5592018-09-24 13:18:43 -0700248};
249
250void injectTap(int x, int y) {
251 char *buf1, *buf2;
252 asprintf(&buf1, "%d", x);
253 asprintf(&buf2, "%d", y);
254 if (fork() == 0) {
255 execlp("input", "input", "tap", buf1, buf2, NULL);
256 }
257}
258
259TEST_F(InputSurfacesTest, can_receive_input) {
260 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
261 surface->showAt(100, 100);
262
263 injectTap(101, 101);
264
265 EXPECT_TRUE(surface->consumeEvent() != nullptr);
266}
267
268TEST_F(InputSurfacesTest, input_respects_positioning) {
269 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
270 surface->showAt(100, 100);
271
272 std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
273 surface2->showAt(200, 200);
274
275 injectTap(201, 201);
276 surface2->expectTap(1, 1);
277
278 injectTap(101, 101);
279 surface->expectTap(1, 1);
280
281 surface2->doTransaction([](auto &t, auto &sc) {
282 t.setPosition(sc, 100, 100);
283 });
284 surface->doTransaction([](auto &t, auto &sc) {
285 t.setPosition(sc, 200, 200);
286 });
287
288 injectTap(101, 101);
289 surface2->expectTap(1, 1);
290
291 injectTap(201, 201);
292 surface->expectTap(1, 1);
293}
294
295TEST_F(InputSurfacesTest, input_respects_layering) {
296 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
297 std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
298
299 surface->showAt(10, 10);
300 surface2->showAt(10, 10);
301
302 surface->doTransaction([](auto &t, auto &sc) {
303 t.setLayer(sc, LAYER_BASE + 1);
304 });
305
306 injectTap(11, 11);
307 surface->expectTap(1, 1);
308
309 surface2->doTransaction([](auto &t, auto &sc) {
310 t.setLayer(sc, LAYER_BASE + 1);
311 });
312
313 injectTap(11, 11);
314 surface2->expectTap(1, 1);
315
316 surface2->doTransaction([](auto &t, auto &sc) {
317 t.hide(sc);
318 });
319
320 injectTap(11, 11);
321 surface->expectTap(1, 1);
322}
323
Vishnu Nairde19f852018-12-18 16:11:53 -0800324// Surface Insets are set to offset the client content and draw a border around the client surface
325// (such as shadows in dialogs). Inputs sent to the client are offset such that 0,0 is the start
326// of the client content.
327TEST_F(InputSurfacesTest, input_respects_surface_insets) {
328 std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
329 std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
330 bgSurface->showAt(100, 100);
331
332 fgSurface->mInputInfo.surfaceInset = 5;
333 fgSurface->showAt(100, 100);
334
335 injectTap(106, 106);
336 fgSurface->expectTap(1, 1);
337
338 injectTap(101, 101);
339 bgSurface->expectTap(1, 1);
340}
341
342// Ensure a surface whose insets are cropped, handles the touch offset correctly. ref:b/120413463
343TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) {
344 std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
345 std::unique_ptr<InputSurface> childSurface = makeSurface(100, 100);
346 parentSurface->showAt(100, 100);
347
348 childSurface->mInputInfo.surfaceInset = 10;
349 childSurface->showAt(100, 100);
350
351 childSurface->doTransaction([&](auto &t, auto &sc) {
352 t.setPosition(sc, -5, -5);
353 t.reparent(sc, parentSurface->mSurfaceControl->getHandle());
354 });
355
356 injectTap(106, 106);
357 childSurface->expectTap(1, 1);
358
359 injectTap(101, 101);
360 parentSurface->expectTap(1, 1);
361}
362
Arthur Hung118b1142019-05-08 21:25:59 +0800363// Ensure a surface whose insets are scaled, handles the touch offset correctly.
364TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) {
365 std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
366 std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
367 bgSurface->showAt(100, 100);
368
369 fgSurface->mInputInfo.surfaceInset = 5;
370 fgSurface->showAt(100, 100);
371
372 fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); });
373
374 // expect = touch / scale - inset
375 injectTap(112, 124);
376 fgSurface->expectTap(1, 1);
377
378 injectTap(101, 101);
379 bgSurface->expectTap(1, 1);
380}
381
Ady Abraham282f1d72019-07-24 18:05:56 -0700382TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
383 std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
384 // In case we pass the very big inset without any checking.
385 fgSurface->mInputInfo.surfaceInset = INT32_MAX;
386 fgSurface->showAt(100, 100);
387
388 fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
389
390 // expect no crash for overflow, and inset size to be clamped to surface size
391 injectTap(202, 202);
392 fgSurface->expectTap(1, 1);
393}
394
Vishnu Nairde19f852018-12-18 16:11:53 -0800395// Ensure we ignore transparent region when getting screen bounds when positioning input frame.
396TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
397 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
398 surface->doTransaction([](auto &t, auto &sc) {
399 Region transparentRegion(Rect(0, 0, 10, 10));
400 t.setTransparentRegionHint(sc, transparentRegion);
401 });
402 surface->showAt(100, 100);
403 injectTap(101, 101);
404 surface->expectTap(1, 1);
405}
406
Vishnu Nairf8678ba2019-10-11 18:11:26 -0700407// TODO(b/139494112) update tests once we define expected behavior
408// Ensure we still send input to the surface regardless of surface visibility changes due to the
409// first buffer being submitted or alpha changes.
410// Original bug ref: b/120839715
411TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) {
Vishnu Nairde19f852018-12-18 16:11:53 -0800412 std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
413 std::unique_ptr<InputSurface> bufferSurface =
414 InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
415
416 bgSurface->showAt(10, 10);
417 bufferSurface->showAt(10, 10);
418
419 injectTap(11, 11);
Vishnu Nairf8678ba2019-10-11 18:11:26 -0700420 bufferSurface->expectTap(1, 1);
Vishnu Nairde19f852018-12-18 16:11:53 -0800421
422 postBuffer(bufferSurface->mSurfaceControl);
423 injectTap(11, 11);
424 bufferSurface->expectTap(1, 1);
425}
426
Vishnu Nairf8678ba2019-10-11 18:11:26 -0700427TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) {
Vishnu Nairde19f852018-12-18 16:11:53 -0800428 std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
429 std::unique_ptr<InputSurface> bufferSurface =
430 InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
431 postBuffer(bufferSurface->mSurfaceControl);
432
433 bgSurface->showAt(10, 10);
434 bufferSurface->showAt(10, 10);
435
436 injectTap(11, 11);
437 bufferSurface->expectTap(1, 1);
438
439 bufferSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
440
441 injectTap(11, 11);
Vishnu Nairf8678ba2019-10-11 18:11:26 -0700442 bufferSurface->expectTap(1, 1);
Vishnu Nairde19f852018-12-18 16:11:53 -0800443}
444
Vishnu Nairf8678ba2019-10-11 18:11:26 -0700445TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) {
Vishnu Nairde19f852018-12-18 16:11:53 -0800446 std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
447 std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
448
449 bgSurface->showAt(10, 10);
450 fgSurface->showAt(10, 10);
451
452 injectTap(11, 11);
453 fgSurface->expectTap(1, 1);
454
455 fgSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
456
457 injectTap(11, 11);
Vishnu Nairf8678ba2019-10-11 18:11:26 -0700458 fgSurface->expectTap(1, 1);
Vishnu Nairde19f852018-12-18 16:11:53 -0800459}
460
461TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) {
462 std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
463 std::unique_ptr<InputSurface> containerSurface =
464 InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
465
466 bgSurface->showAt(10, 10);
467 containerSurface->showAt(10, 10);
468
469 injectTap(11, 11);
470 containerSurface->expectTap(1, 1);
471
472 containerSurface->doTransaction([](auto &t, auto &sc) { t.hide(sc); });
473
474 injectTap(11, 11);
475 bgSurface->expectTap(1, 1);
476}
chaviwfbe5d9c2018-12-26 12:23:37 -0800477
Arthur Hungd20b2702019-01-14 18:16:16 +0800478TEST_F(InputSurfacesTest, input_respects_outscreen) {
479 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
480 surface->showAt(-1, -1);
481
482 injectTap(0, 0);
483 surface->expectTap(1, 1);
484}
Robert Carr1c4c5592018-09-24 13:18:43 -0700485}
486}