blob: fd3f5627b7be5bd0ec5921f9f3719cd68729138e [file] [log] [blame]
Chris Ye0783e992020-06-02 21:34:49 -07001/*
2 * Copyright (C) 2020 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 <BnInputFlingerQuery.h>
18#include <IInputFlingerQuery.h>
19
20#include <android/os/BnInputFlinger.h>
21#include <android/os/BnSetInputWindowsListener.h>
22#include <android/os/IInputFlinger.h>
23#include <android/os/ISetInputWindowsListener.h>
24
25#include <binder/Binder.h>
26#include <binder/IPCThreadState.h>
27#include <binder/IServiceManager.h>
28#include <binder/Parcel.h>
29#include <binder/ProcessState.h>
30
31#include <input/Input.h>
32#include <input/InputTransport.h>
33#include <input/InputWindow.h>
34
35#include <gtest/gtest.h>
36#include <inttypes.h>
37#include <linux/uinput.h>
38#include <log/log.h>
39#include <ui/Rect.h>
40#include <ui/Region.h>
41#include <chrono>
42#include <thread>
43#include <unordered_map>
44
45#define TAG "InputFlingerServiceTest"
46
47using android::os::BnInputFlinger;
48using android::os::BnSetInputWindowsListener;
49using android::os::IInputFlinger;
50using android::os::ISetInputWindowsListener;
51
52using std::chrono_literals::operator""ms;
53using std::chrono_literals::operator""s;
54
55namespace android {
56
57static const sp<IBinder> TestInfoToken = new BBinder();
58static constexpr int32_t TestInfoId = 1;
59static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo";
60static constexpr int32_t TestInfoLayoutParamsFlags = 0xABCD;
61static constexpr int32_t TestInfoLayoutParamsType = 39;
62static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms;
63static constexpr int32_t TestInfoFrameLeft = 93;
64static constexpr int32_t TestInfoFrameTop = 34;
65static constexpr int32_t TestInfoFrameRight = 16;
66static constexpr int32_t TestInfoFrameBottom = 19;
67static constexpr int32_t TestInfoSurfaceInset = 17;
68static constexpr float TestInfoGlobalScaleFactor = 0.3;
69static constexpr float TestInfoWindowXScale = 0.4;
70static constexpr float TestInfoWindowYScale = 0.5;
71static const Rect TestInfoTouchableRegionRect = {100 /* left */, 150 /* top */, 400 /* right */,
72 450 /* bottom */};
73static const Region TestInfoTouchableRegion(TestInfoTouchableRegionRect);
74static constexpr bool TestInfoVisible = false;
75static constexpr bool TestInfoCanReceiveKeys = false;
76static constexpr bool TestInfoTrustedOverlay = true;
77static constexpr bool TestInfoHasFocus = false;
78static constexpr bool TestInfoHasWallpaper = false;
79static constexpr bool TestInfoPaused = false;
80static constexpr int32_t TestInfoOwnerPid = 19;
81static constexpr int32_t TestInfoOwnerUid = 24;
82static constexpr int32_t TestInfoInputFeatures = 29;
83static constexpr int32_t TestInfoDisplayId = 34;
84static constexpr int32_t TestInfoPortalToDisplayId = 2;
85static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true;
86static const sp<IBinder> TestInfoTouchableRegionCropHandle = new BBinder();
87
88static const std::string TestAppInfoName = "InputFlingerServiceTestInputApplicationInfo";
89static const sp<IBinder> TestAppInfoToken = new BBinder();
90static constexpr std::chrono::duration TestAppInfoDispatchingTimeout = 12345678ms;
91
92static const String16 kTestServiceName = String16("InputFlingerService");
93static const String16 kQueryServiceName = String16("InputFlingerQueryService");
94
95struct SetInputWindowsListener;
96// --- InputFlingerServiceTest ---
97class InputFlingerServiceTest : public testing::Test {
98public:
99 void SetUp() override;
100 void TearDown() override;
101
102protected:
103 void InitializeInputFlinger();
104 void setInputWindowsByInfos(std::vector<InputWindowInfo>& infos);
105
106 void setInputWindowsFinished();
107 void verifyInputWindowInfo(const InputWindowInfo& info) const;
108 InputWindowInfo& getInfo() const { return const_cast<InputWindowInfo&>(mInfo); }
109
110 sp<IInputFlinger> mService;
111 sp<IInputFlingerQuery> mQuery;
112
113private:
114 sp<SetInputWindowsListener> mSetInputWindowsListener;
115 sp<InputChannel> mServerChannel, mClientChannel;
116 InputWindowInfo mInfo;
117 std::mutex mLock;
118 std::condition_variable mSetInputWindowsFinishedCondition;
119};
120
121struct SetInputWindowsListener : BnSetInputWindowsListener {
122 explicit SetInputWindowsListener(std::function<void()> cbFunc) : mCbFunc(cbFunc) {}
123
124 binder::Status onSetInputWindowsFinished() override;
125
126 std::function<void()> mCbFunc;
127};
128
129class TestInputManager : public BnInputFlinger {
130protected:
131 virtual ~TestInputManager(){};
132
133public:
134 TestInputManager(){};
135 void checkFdFlags(const android::base::unique_fd& fd);
136
137 binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles);
138 binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos);
139
140 status_t dump(int fd, const Vector<String16>& args) override;
141
142 binder::Status setInputWindows(
143 const std::vector<InputWindowInfo>& handles,
144 const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
145
146 binder::Status registerInputChannel(const InputChannelInfo& channel) override;
147 binder::Status unregisterInputChannel(const InputChannelInfo& channel) override;
148
149private:
150 mutable Mutex mLock;
151 std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay;
152 std::vector<sp<InputChannel>> mInputChannels;
153};
154
155class TestInputQuery : public BnInputFlingerQuery {
156public:
157 TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){};
158 binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override;
159 binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos) override;
160
161private:
162 sp<android::TestInputManager> mManager;
163};
164
165binder::Status TestInputQuery::getInputWindows(
166 std::vector<::android::InputWindowInfo>* inputHandles) {
167 return mManager->getInputWindows(inputHandles);
168}
169
170binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannelInfo>* infos) {
171 return mManager->getInputChannels(infos);
172}
173
174binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
175 if (mCbFunc != nullptr) {
176 mCbFunc();
177 }
178 return binder::Status::ok();
179}
180
181binder::Status TestInputManager::setInputWindows(
182 const std::vector<InputWindowInfo>& infos,
183 const sp<ISetInputWindowsListener>& setInputWindowsListener) {
184 AutoMutex _l(mLock);
185
186 for (const auto& info : infos) {
187 mHandlesPerDisplay.emplace(info.displayId, std::vector<sp<InputWindowHandle>>());
188 mHandlesPerDisplay[info.displayId].push_back(new InputWindowHandle(info));
189 }
190 if (setInputWindowsListener) {
191 setInputWindowsListener->onSetInputWindowsFinished();
192 }
193 return binder::Status::ok();
194}
195
196void TestInputManager::checkFdFlags(const android::base::unique_fd& fd) {
197 const int result = fcntl(fd, F_GETFL);
198 EXPECT_NE(result, -1);
199 EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
200}
201
202binder::Status TestInputManager::registerInputChannel(const InputChannelInfo& info) {
203 AutoMutex _l(mLock);
204 // check Fd flags
205 checkFdFlags(info.mFd);
206
207 android::base::unique_fd newFd(::dup(info.mFd));
208 sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
209 mInputChannels.push_back(channel);
210
211 return binder::Status::ok();
212}
213
214binder::Status TestInputManager::unregisterInputChannel(const InputChannelInfo& info) {
215 AutoMutex _l(mLock);
216 // check Fd flags
217 checkFdFlags(info.mFd);
218 android::base::unique_fd newFd(::dup(info.mFd));
219 sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
220
221 auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
222 [&](sp<InputChannel>& it) { return *it == *channel; });
223 if (it != mInputChannels.end()) {
224 mInputChannels.erase(it);
225 }
226
227 return binder::Status::ok();
228}
229
230status_t TestInputManager::dump(int fd, const Vector<String16>& args) {
231 std::string dump;
232
233 dump += " InputFlinger dump\n";
234
235 ::write(fd, dump.c_str(), dump.size());
236 return NO_ERROR;
237}
238
239binder::Status TestInputManager::getInputWindows(
240 std::vector<::android::InputWindowInfo>* inputInfos) {
241 for (auto& [displayId, inputHandles] : mHandlesPerDisplay) {
242 for (auto& inputHandle : inputHandles) {
243 inputInfos->push_back(*inputHandle->getInfo());
244 }
245 }
246 return binder::Status::ok();
247}
248
249binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannelInfo>* infos) {
250 infos->clear();
251 for (auto& channel : mInputChannels) {
252 auto chanDup = channel->dup();
253 infos->push_back(std::move(chanDup->getInfo()));
254 }
255 return binder::Status::ok();
256}
257
258void InputFlingerServiceTest::SetUp() {
259 mSetInputWindowsListener = new SetInputWindowsListener([&]() {
260 std::unique_lock<std::mutex> lock(mLock);
261 mSetInputWindowsFinishedCondition.notify_all();
262 });
263 InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
264
265 mInfo.token = TestInfoToken;
266 mInfo.id = TestInfoId;
267 mInfo.name = TestInfoName;
268 mInfo.layoutParamsFlags = TestInfoLayoutParamsFlags;
269 mInfo.layoutParamsType = TestInfoLayoutParamsType;
270 mInfo.dispatchingTimeout = TestInfoDispatchingTimeout;
271 mInfo.frameLeft = TestInfoFrameLeft;
272 mInfo.frameTop = TestInfoFrameTop;
273 mInfo.frameRight = TestInfoFrameRight;
274 mInfo.frameBottom = TestInfoFrameBottom;
275 mInfo.surfaceInset = TestInfoSurfaceInset;
276 mInfo.globalScaleFactor = TestInfoGlobalScaleFactor;
277 mInfo.windowXScale = TestInfoWindowXScale;
278 mInfo.windowYScale = TestInfoWindowYScale;
279 mInfo.touchableRegion = TestInfoTouchableRegion;
280 mInfo.visible = TestInfoVisible;
281 mInfo.canReceiveKeys = TestInfoCanReceiveKeys;
282 mInfo.trustedOverlay = TestInfoTrustedOverlay;
283 mInfo.hasFocus = TestInfoHasFocus;
284 mInfo.hasWallpaper = TestInfoHasWallpaper;
285 mInfo.paused = TestInfoPaused;
286 mInfo.ownerPid = TestInfoOwnerPid;
287 mInfo.ownerUid = TestInfoOwnerUid;
288 mInfo.inputFeatures = TestInfoInputFeatures;
289 mInfo.displayId = TestInfoDisplayId;
290 mInfo.portalToDisplayId = TestInfoPortalToDisplayId;
291 mInfo.replaceTouchableRegionWithCrop = TestInfoReplaceTouchableRegionWithCrop;
292 mInfo.touchableRegionCropHandle = TestInfoTouchableRegionCropHandle;
293
294 mInfo.applicationInfo.name = TestAppInfoName;
295 mInfo.applicationInfo.token = TestAppInfoToken;
296 mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout;
297
298 InitializeInputFlinger();
299}
300
301void InputFlingerServiceTest::TearDown() {}
302
303void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const {
304 EXPECT_EQ(mInfo, info);
305}
306
307void InputFlingerServiceTest::InitializeInputFlinger() {
308 sp<IBinder> input(defaultServiceManager()->waitForService(kTestServiceName));
309 ASSERT_TRUE(input != nullptr);
310 mService = interface_cast<IInputFlinger>(input);
311
312 input = defaultServiceManager()->waitForService(kQueryServiceName);
313 ASSERT_TRUE(input != nullptr);
314 mQuery = interface_cast<IInputFlingerQuery>(input);
315}
316
317void InputFlingerServiceTest::setInputWindowsByInfos(std::vector<InputWindowInfo>& infos) {
318 std::unique_lock<std::mutex> lock(mLock);
319 mService->setInputWindows(infos, mSetInputWindowsListener);
320 // Verify listener call
321 EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout);
322 // Verify input windows from service
323 std::vector<::android::InputWindowInfo> inputHandles;
324 mQuery->getInputWindows(&inputHandles);
325 for (auto& inputInfo : inputHandles) {
326 verifyInputWindowInfo(inputInfo);
327 }
328}
329
330/**
331 * Test InputFlinger service interface SetInputWindows
332 */
333TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) {
334 std::vector<InputWindowInfo> infos = {getInfo()};
335 setInputWindowsByInfos(infos);
336}
337
338/**
339 * Test InputFlinger service interface registerInputChannel
340 */
341TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) {
342 sp<InputChannel> serverChannel, clientChannel;
343
344 InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
345 mService->registerInputChannel(serverChannel->getInfo());
346
347 std::vector<::android::InputChannelInfo> infos(2);
348 mQuery->getInputChannels(&infos);
349 EXPECT_EQ(infos.size(), 1UL);
350
351 auto& info = infos[0];
352 android::base::unique_fd newFd(::dup(info.mFd));
353 sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
354 EXPECT_EQ(*channel, *serverChannel);
355
356 mService->unregisterInputChannel(serverChannel->getInfo());
357 mQuery->getInputChannels(&infos);
358 EXPECT_EQ(infos.size(), 0UL);
359}
360
361/**
362 * Test InputFlinger service interface registerInputChannel with invalid cases
363 */
364TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) {
365 sp<InputChannel> serverChannel, clientChannel;
366 InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
367
368 std::vector<::android::InputChannelInfo> infos(2);
369 mQuery->getInputChannels(&infos);
370 EXPECT_EQ(infos.size(), 0UL);
371
372 mService->registerInputChannel(InputChannelInfo());
373 mService->unregisterInputChannel(clientChannel->getInfo());
374
375 mService->registerInputChannel(serverChannel->getInfo());
376 mService->registerInputChannel(clientChannel->getInfo());
377 mQuery->getInputChannels(&infos);
378 EXPECT_EQ(infos.size(), 2UL);
379
380 mService->unregisterInputChannel(clientChannel->getInfo());
381 mService->unregisterInputChannel(serverChannel->getInfo());
382 mQuery->getInputChannels(&infos);
383 EXPECT_EQ(infos.size(), 0UL);
384}
385
386} // namespace android
387
388int main(int argc, char** argv) {
389 pid_t forkPid = fork();
390
391 if (forkPid == 0) {
392 // Server process
393 android::sp<android::TestInputManager> manager = new android::TestInputManager();
394 android::sp<android::TestInputQuery> query = new android::TestInputQuery(manager);
395
396 android::defaultServiceManager()->addService(android::kTestServiceName, manager,
397 false /*allowIsolated*/);
398 android::defaultServiceManager()->addService(android::kQueryServiceName, query,
399 false /*allowIsolated*/);
400 android::ProcessState::self()->startThreadPool();
401 android::IPCThreadState::self()->joinThreadPool();
402 } else {
403 android::ProcessState::self()->startThreadPool();
404 ::testing::InitGoogleTest(&argc, argv);
405 return RUN_ALL_TESTS();
406 }
407 return 0;
408}