blob: 206e260e37a126a379bf710a531ae426e7f7b4b8 [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;
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500116 std::unique_ptr<InputChannel> mServerChannel, mClientChannel;
Chris Ye0783e992020-06-02 21:34:49 -0700117 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);
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500139 binder::Status getInputChannels(std::vector<::android::InputChannel>* channels);
Chris Ye0783e992020-06-02 21:34:49 -0700140
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
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500147 binder::Status registerInputChannel(const InputChannel& channel) override;
148 binder::Status unregisterInputChannel(const InputChannel& channel) override;
Chris Ye0783e992020-06-02 21:34:49 -0700149
150private:
151 mutable Mutex mLock;
152 std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay;
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500153 std::vector<std::shared_ptr<InputChannel>> mInputChannels;
Chris Ye0783e992020-06-02 21:34:49 -0700154};
155
156class TestInputQuery : public BnInputFlingerQuery {
157public:
158 TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){};
159 binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override;
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500160 binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override;
Chris Ye0783e992020-06-02 21:34:49 -0700161
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
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500171binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannel>* channels) {
172 return mManager->getInputChannels(channels);
Chris Ye0783e992020-06-02 21:34:49 -0700173}
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
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500203binder::Status TestInputManager::registerInputChannel(const InputChannel& channel) {
Chris Ye0783e992020-06-02 21:34:49 -0700204 AutoMutex _l(mLock);
205 // check Fd flags
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500206 checkFdFlags(channel.getFd());
Chris Ye0783e992020-06-02 21:34:49 -0700207
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500208 mInputChannels.push_back(channel.dup());
Chris Ye0783e992020-06-02 21:34:49 -0700209
210 return binder::Status::ok();
211}
212
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500213binder::Status TestInputManager::unregisterInputChannel(const InputChannel& channel) {
Chris Ye0783e992020-06-02 21:34:49 -0700214 AutoMutex _l(mLock);
215 // check Fd flags
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500216 checkFdFlags(channel.getFd());
Chris Ye0783e992020-06-02 21:34:49 -0700217
218 auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500219 [&](std::shared_ptr<InputChannel>& c) { return *c == channel; });
Chris Ye0783e992020-06-02 21:34:49 -0700220 if (it != mInputChannels.end()) {
221 mInputChannels.erase(it);
222 }
223
224 return binder::Status::ok();
225}
226
227status_t TestInputManager::dump(int fd, const Vector<String16>& args) {
228 std::string dump;
229
230 dump += " InputFlinger dump\n";
231
232 ::write(fd, dump.c_str(), dump.size());
233 return NO_ERROR;
234}
235
236binder::Status TestInputManager::getInputWindows(
237 std::vector<::android::InputWindowInfo>* inputInfos) {
238 for (auto& [displayId, inputHandles] : mHandlesPerDisplay) {
239 for (auto& inputHandle : inputHandles) {
240 inputInfos->push_back(*inputHandle->getInfo());
241 }
242 }
243 return binder::Status::ok();
244}
245
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500246binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannel>* channels) {
247 channels->clear();
248 for (std::shared_ptr<InputChannel>& channel : mInputChannels) {
249 channels->push_back(*channel);
Chris Ye0783e992020-06-02 21:34:49 -0700250 }
251 return binder::Status::ok();
252}
253
254void InputFlingerServiceTest::SetUp() {
255 mSetInputWindowsListener = new SetInputWindowsListener([&]() {
256 std::unique_lock<std::mutex> lock(mLock);
257 mSetInputWindowsFinishedCondition.notify_all();
258 });
259 InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
260
261 mInfo.token = TestInfoToken;
262 mInfo.id = TestInfoId;
263 mInfo.name = TestInfoName;
Michael Wright44753b12020-07-08 13:48:11 +0100264 mInfo.flags = TestInfoFlags;
265 mInfo.type = TestInfoType;
Chris Ye0783e992020-06-02 21:34:49 -0700266 mInfo.dispatchingTimeout = TestInfoDispatchingTimeout;
267 mInfo.frameLeft = TestInfoFrameLeft;
268 mInfo.frameTop = TestInfoFrameTop;
269 mInfo.frameRight = TestInfoFrameRight;
270 mInfo.frameBottom = TestInfoFrameBottom;
271 mInfo.surfaceInset = TestInfoSurfaceInset;
272 mInfo.globalScaleFactor = TestInfoGlobalScaleFactor;
273 mInfo.windowXScale = TestInfoWindowXScale;
274 mInfo.windowYScale = TestInfoWindowYScale;
275 mInfo.touchableRegion = TestInfoTouchableRegion;
276 mInfo.visible = TestInfoVisible;
277 mInfo.canReceiveKeys = TestInfoCanReceiveKeys;
278 mInfo.trustedOverlay = TestInfoTrustedOverlay;
279 mInfo.hasFocus = TestInfoHasFocus;
280 mInfo.hasWallpaper = TestInfoHasWallpaper;
281 mInfo.paused = TestInfoPaused;
282 mInfo.ownerPid = TestInfoOwnerPid;
283 mInfo.ownerUid = TestInfoOwnerUid;
284 mInfo.inputFeatures = TestInfoInputFeatures;
285 mInfo.displayId = TestInfoDisplayId;
286 mInfo.portalToDisplayId = TestInfoPortalToDisplayId;
287 mInfo.replaceTouchableRegionWithCrop = TestInfoReplaceTouchableRegionWithCrop;
288 mInfo.touchableRegionCropHandle = TestInfoTouchableRegionCropHandle;
289
290 mInfo.applicationInfo.name = TestAppInfoName;
291 mInfo.applicationInfo.token = TestAppInfoToken;
292 mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout;
293
294 InitializeInputFlinger();
295}
296
297void InputFlingerServiceTest::TearDown() {}
298
299void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const {
300 EXPECT_EQ(mInfo, info);
301}
302
303void InputFlingerServiceTest::InitializeInputFlinger() {
304 sp<IBinder> input(defaultServiceManager()->waitForService(kTestServiceName));
305 ASSERT_TRUE(input != nullptr);
306 mService = interface_cast<IInputFlinger>(input);
307
308 input = defaultServiceManager()->waitForService(kQueryServiceName);
309 ASSERT_TRUE(input != nullptr);
310 mQuery = interface_cast<IInputFlingerQuery>(input);
311}
312
313void InputFlingerServiceTest::setInputWindowsByInfos(std::vector<InputWindowInfo>& infos) {
314 std::unique_lock<std::mutex> lock(mLock);
315 mService->setInputWindows(infos, mSetInputWindowsListener);
316 // Verify listener call
317 EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout);
Chris Ye0783e992020-06-02 21:34:49 -0700318}
319
320/**
321 * Test InputFlinger service interface SetInputWindows
322 */
323TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) {
324 std::vector<InputWindowInfo> infos = {getInfo()};
325 setInputWindowsByInfos(infos);
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500326
327 // Verify input windows from service
328 std::vector<::android::InputWindowInfo> windowInfos;
329 mQuery->getInputWindows(&windowInfos);
330 for (const ::android::InputWindowInfo& windowInfo : windowInfos) {
331 verifyInputWindowInfo(windowInfo);
332 }
Chris Ye0783e992020-06-02 21:34:49 -0700333}
334
335/**
336 * Test InputFlinger service interface registerInputChannel
337 */
338TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) {
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500339 std::unique_ptr<InputChannel> serverChannel, clientChannel;
Chris Ye0783e992020-06-02 21:34:49 -0700340
341 InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500342 mService->registerInputChannel(*serverChannel);
Chris Ye0783e992020-06-02 21:34:49 -0700343
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500344 std::vector<::android::InputChannel> channels;
345 mQuery->getInputChannels(&channels);
346 ASSERT_EQ(channels.size(), 1UL);
347 EXPECT_EQ(channels[0], *serverChannel);
Chris Ye0783e992020-06-02 21:34:49 -0700348
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500349 mService->unregisterInputChannel(*serverChannel);
350 mQuery->getInputChannels(&channels);
351 EXPECT_EQ(channels.size(), 0UL);
Chris Ye0783e992020-06-02 21:34:49 -0700352}
353
354/**
355 * Test InputFlinger service interface registerInputChannel with invalid cases
356 */
357TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) {
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500358 std::unique_ptr<InputChannel> serverChannel, clientChannel;
Chris Ye0783e992020-06-02 21:34:49 -0700359 InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
360
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500361 std::vector<::android::InputChannel> channels;
362 mQuery->getInputChannels(&channels);
363 EXPECT_EQ(channels.size(), 0UL);
Chris Ye0783e992020-06-02 21:34:49 -0700364
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500365 mService->registerInputChannel(InputChannel());
366 mService->unregisterInputChannel(*clientChannel);
Chris Ye0783e992020-06-02 21:34:49 -0700367
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500368 mService->registerInputChannel(*serverChannel);
369 mService->registerInputChannel(*clientChannel);
370 mQuery->getInputChannels(&channels);
371 EXPECT_EQ(channels.size(), 2UL);
Chris Ye0783e992020-06-02 21:34:49 -0700372
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500373 mService->unregisterInputChannel(*clientChannel);
374 mService->unregisterInputChannel(*serverChannel);
375 mQuery->getInputChannels(&channels);
376 EXPECT_EQ(channels.size(), 0UL);
Chris Ye0783e992020-06-02 21:34:49 -0700377}
378
379} // namespace android
380
381int main(int argc, char** argv) {
382 pid_t forkPid = fork();
383
384 if (forkPid == 0) {
385 // Server process
386 android::sp<android::TestInputManager> manager = new android::TestInputManager();
387 android::sp<android::TestInputQuery> query = new android::TestInputQuery(manager);
388
389 android::defaultServiceManager()->addService(android::kTestServiceName, manager,
390 false /*allowIsolated*/);
391 android::defaultServiceManager()->addService(android::kQueryServiceName, query,
392 false /*allowIsolated*/);
393 android::ProcessState::self()->startThreadPool();
394 android::IPCThreadState::self()->joinThreadPool();
395 } else {
396 android::ProcessState::self()->startThreadPool();
397 ::testing::InitGoogleTest(&argc, argv);
Chris Yec4669842020-07-14 17:10:09 -0700398 int result = RUN_ALL_TESTS();
399 kill(forkPid, SIGKILL);
400 return result;
Chris Ye0783e992020-06-02 21:34:49 -0700401 }
402 return 0;
403}