blob: 86e9c23a7e0ba6ea175c68afc89456f282557bbf [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
27#include <binder/Binder.h>
28#include <binder/IServiceManager.h>
29#include <binder/Parcel.h>
30#include <binder/ProcessState.h>
31
32#include <gui/SurfaceComposerClient.h>
33#include <gui/SurfaceControl.h>
34
35#include <input/InputWindow.h>
36#include <input/IInputFlinger.h>
37#include <input/InputTransport.h>
38#include <input/Input.h>
39
40#include <ui/Rect.h>
41#include <ui/Region.h>
42
43
44namespace android {
45namespace test {
46
47sp<IInputFlinger> getInputFlinger() {
48 sp<IBinder> input(defaultServiceManager()->getService(
49 String16("inputflinger")));
50 if (input == nullptr) {
51 ALOGE("Failed to link to input service");
52 } else { ALOGE("Linked to input"); }
53 return interface_cast<IInputFlinger>(input);
54}
55
56// We use the top 10 layers as a way to haphazardly place ourselves above anything else.
57static const int LAYER_BASE = INT32_MAX - 10;
58
59class InputSurface {
60public:
61 InputSurface(const sp<SurfaceComposerClient>& scc, int width, int height) {
Vishnu Nair88a11f22018-11-28 18:30:57 -080062 mSurfaceControl = scc->createSurface(String8("Test Surface"), 0, 0, PIXEL_FORMAT_RGBA_8888,
63 ISurfaceComposerClient::eFXSurfaceColor);
Robert Carr1c4c5592018-09-24 13:18:43 -070064
65 InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
66 mServerChannel->setToken(new BBinder());
67
68 mInputFlinger = getInputFlinger();
69 mInputFlinger->registerInputChannel(mServerChannel);
70
71 populateInputInfo(width, height);
72
73 mInputConsumer = new InputConsumer(mClientChannel);
74 }
75
76 InputEvent* consumeEvent() {
77 waitForEventAvailable();
78
79 InputEvent *ev;
80 uint32_t seqId;
81 status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev);
82 if (consumed != OK) {
83 return nullptr;
84 }
85 mInputConsumer->sendFinishedSignal(seqId, true);
86 return ev;
87 }
88
89 void expectTap(int x, int y) {
90 InputEvent* ev = consumeEvent();
91 EXPECT_TRUE(ev != nullptr);
92 EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION);
93 MotionEvent* mev = static_cast<MotionEvent*>(ev);
94 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
95 EXPECT_EQ(x, mev->getX(0));
96 EXPECT_EQ(y, mev->getY(0));
97
98 ev = consumeEvent();
99 EXPECT_TRUE(ev != nullptr);
100 EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION);
101 mev = static_cast<MotionEvent*>(ev);
102 EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
103 }
104
105 ~InputSurface() {
106 mInputFlinger->unregisterInputChannel(mServerChannel);
107 }
108
109 void doTransaction(std::function<void(SurfaceComposerClient::Transaction&,
110 const sp<SurfaceControl>&)> transactionBody) {
111 SurfaceComposerClient::Transaction t;
112 transactionBody(t, mSurfaceControl);
113 t.apply(true);
114 }
115
116 void showAt(int x, int y) {
117 SurfaceComposerClient::Transaction t;
118 t.show(mSurfaceControl);
119 t.setInputWindowInfo(mSurfaceControl, mInputInfo);
120 t.setLayer(mSurfaceControl, LAYER_BASE);
121 t.setPosition(mSurfaceControl, x, y);
122 t.setCrop_legacy(mSurfaceControl, Rect(0, 0, 100, 100));
123 t.setAlpha(mSurfaceControl, 1);
124 t.apply(true);
125 }
126
127private:
128 void waitForEventAvailable() {
129 struct pollfd fd;
130
131 fd.fd = mClientChannel->getFd();
132 fd.events = POLLIN;
133 poll(&fd, 1, 3000);
134 }
135
136 void populateInputInfo(int width, int height) {
Robert Carr5c8a0262018-10-03 16:30:44 -0700137 mInputInfo.token = mServerChannel->getToken();
Robert Carr1c4c5592018-09-24 13:18:43 -0700138 mInputInfo.name = "Test info";
139 mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
140 mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION;
141 mInputInfo.dispatchingTimeout = 100000;
Robert Carre07e1032018-11-26 12:55:53 -0800142 mInputInfo.globalScaleFactor = 1.0;
Robert Carr1c4c5592018-09-24 13:18:43 -0700143 mInputInfo.canReceiveKeys = true;
144 mInputInfo.hasFocus = true;
145 mInputInfo.hasWallpaper = false;
146 mInputInfo.paused = false;
147
148 mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));
149
150 // TODO: Fill in from SF?
151 mInputInfo.ownerPid = 11111;
152 mInputInfo.ownerUid = 11111;
153 mInputInfo.inputFeatures = 0;
154 mInputInfo.displayId = 0;
Robert Carr740167f2018-10-11 19:03:41 -0700155
156 InputApplicationInfo aInfo;
157 aInfo.token = new BBinder();
158 aInfo.name = "Test app info";
159 aInfo.dispatchingTimeout = 100000;
160
161 mInputInfo.applicationInfo = aInfo;
Robert Carr1c4c5592018-09-24 13:18:43 -0700162 }
163public:
164 sp<SurfaceControl> mSurfaceControl;
165 sp<InputChannel> mServerChannel, mClientChannel;
166 sp<IInputFlinger> mInputFlinger;
167
168 InputWindowInfo mInputInfo;
169
170 PreallocatedInputEventFactory mInputEventFactory;
171 InputConsumer* mInputConsumer;
172};
173
174class InputSurfacesTest : public ::testing::Test {
175public:
176 InputSurfacesTest() {
177 ProcessState::self()->startThreadPool();
178 }
179
180 void SetUp() {
181 mComposerClient = new SurfaceComposerClient;
182 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
183 }
184
185 void TearDown() {
186 mComposerClient->dispose();
187 }
188
189 std::unique_ptr<InputSurface> makeSurface(int width, int height) {
190 return std::make_unique<InputSurface>(mComposerClient, width, height);
191 }
192
193 sp<SurfaceComposerClient> mComposerClient;
194};
195
196void injectTap(int x, int y) {
197 char *buf1, *buf2;
198 asprintf(&buf1, "%d", x);
199 asprintf(&buf2, "%d", y);
200 if (fork() == 0) {
201 execlp("input", "input", "tap", buf1, buf2, NULL);
202 }
203}
204
205TEST_F(InputSurfacesTest, can_receive_input) {
206 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
207 surface->showAt(100, 100);
208
209 injectTap(101, 101);
210
211 EXPECT_TRUE(surface->consumeEvent() != nullptr);
212}
213
214TEST_F(InputSurfacesTest, input_respects_positioning) {
215 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
216 surface->showAt(100, 100);
217
218 std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
219 surface2->showAt(200, 200);
220
221 injectTap(201, 201);
222 surface2->expectTap(1, 1);
223
224 injectTap(101, 101);
225 surface->expectTap(1, 1);
226
227 surface2->doTransaction([](auto &t, auto &sc) {
228 t.setPosition(sc, 100, 100);
229 });
230 surface->doTransaction([](auto &t, auto &sc) {
231 t.setPosition(sc, 200, 200);
232 });
233
234 injectTap(101, 101);
235 surface2->expectTap(1, 1);
236
237 injectTap(201, 201);
238 surface->expectTap(1, 1);
239}
240
241TEST_F(InputSurfacesTest, input_respects_layering) {
242 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
243 std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
244
245 surface->showAt(10, 10);
246 surface2->showAt(10, 10);
247
248 surface->doTransaction([](auto &t, auto &sc) {
249 t.setLayer(sc, LAYER_BASE + 1);
250 });
251
252 injectTap(11, 11);
253 surface->expectTap(1, 1);
254
255 surface2->doTransaction([](auto &t, auto &sc) {
256 t.setLayer(sc, LAYER_BASE + 1);
257 });
258
259 injectTap(11, 11);
260 surface2->expectTap(1, 1);
261
262 surface2->doTransaction([](auto &t, auto &sc) {
263 t.hide(sc);
264 });
265
266 injectTap(11, 11);
267 surface->expectTap(1, 1);
268}
269
270}
271}