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