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