blob: 2f165c4131660546098865773d9b8dfd07d61626 [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) {
138 mInputInfo.inputChannel = mServerChannel;
139 mInputInfo.name = "Test info";
140 mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
141 mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION;
142 mInputInfo.dispatchingTimeout = 100000;
143 mInputInfo.scaleFactor = 1.0;
144 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;
156 }
157public:
158 sp<SurfaceControl> mSurfaceControl;
159 sp<InputChannel> mServerChannel, mClientChannel;
160 sp<IInputFlinger> mInputFlinger;
161
162 InputWindowInfo mInputInfo;
163
164 PreallocatedInputEventFactory mInputEventFactory;
165 InputConsumer* mInputConsumer;
166};
167
168class InputSurfacesTest : public ::testing::Test {
169public:
170 InputSurfacesTest() {
171 ProcessState::self()->startThreadPool();
172 }
173
174 void SetUp() {
175 mComposerClient = new SurfaceComposerClient;
176 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
177 }
178
179 void TearDown() {
180 mComposerClient->dispose();
181 }
182
183 std::unique_ptr<InputSurface> makeSurface(int width, int height) {
184 return std::make_unique<InputSurface>(mComposerClient, width, height);
185 }
186
187 sp<SurfaceComposerClient> mComposerClient;
188};
189
190void injectTap(int x, int y) {
191 char *buf1, *buf2;
192 asprintf(&buf1, "%d", x);
193 asprintf(&buf2, "%d", y);
194 if (fork() == 0) {
195 execlp("input", "input", "tap", buf1, buf2, NULL);
196 }
197}
198
199TEST_F(InputSurfacesTest, can_receive_input) {
200 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
201 surface->showAt(100, 100);
202
203 injectTap(101, 101);
204
205 EXPECT_TRUE(surface->consumeEvent() != nullptr);
206}
207
208TEST_F(InputSurfacesTest, input_respects_positioning) {
209 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
210 surface->showAt(100, 100);
211
212 std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
213 surface2->showAt(200, 200);
214
215 injectTap(201, 201);
216 surface2->expectTap(1, 1);
217
218 injectTap(101, 101);
219 surface->expectTap(1, 1);
220
221 surface2->doTransaction([](auto &t, auto &sc) {
222 t.setPosition(sc, 100, 100);
223 });
224 surface->doTransaction([](auto &t, auto &sc) {
225 t.setPosition(sc, 200, 200);
226 });
227
228 injectTap(101, 101);
229 surface2->expectTap(1, 1);
230
231 injectTap(201, 201);
232 surface->expectTap(1, 1);
233}
234
235TEST_F(InputSurfacesTest, input_respects_layering) {
236 std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
237 std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
238
239 surface->showAt(10, 10);
240 surface2->showAt(10, 10);
241
242 surface->doTransaction([](auto &t, auto &sc) {
243 t.setLayer(sc, LAYER_BASE + 1);
244 });
245
246 injectTap(11, 11);
247 surface->expectTap(1, 1);
248
249 surface2->doTransaction([](auto &t, auto &sc) {
250 t.setLayer(sc, LAYER_BASE + 1);
251 });
252
253 injectTap(11, 11);
254 surface2->expectTap(1, 1);
255
256 surface2->doTransaction([](auto &t, auto &sc) {
257 t.hide(sc);
258 });
259
260 injectTap(11, 11);
261 surface->expectTap(1, 1);
262}
263
264}
265}