blob: 454e531af6b495caff7bf8b3f93ef8095f0d375a [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>
Chris Ye0783e992020-06-02 21:34:49 -070021#include <android/os/IInputFlinger.h>
Chris Ye0783e992020-06-02 21:34:49 -070022
23#include <binder/Binder.h>
24#include <binder/IPCThreadState.h>
25#include <binder/IServiceManager.h>
26#include <binder/Parcel.h>
27#include <binder/ProcessState.h>
28
29#include <input/Input.h>
30#include <input/InputTransport.h>
Chris Ye0783e992020-06-02 21:34:49 -070031
32#include <gtest/gtest.h>
33#include <inttypes.h>
34#include <linux/uinput.h>
35#include <log/log.h>
36#include <ui/Rect.h>
37#include <ui/Region.h>
38#include <chrono>
39#include <thread>
40#include <unordered_map>
41
42#define TAG "InputFlingerServiceTest"
43
chaviw3277faf2021-05-19 16:45:23 -050044using android::gui::FocusRequest;
Chris Ye0783e992020-06-02 21:34:49 -070045using android::os::BnInputFlinger;
Chris Ye0783e992020-06-02 21:34:49 -070046using android::os::IInputFlinger;
Chris Ye0783e992020-06-02 21:34:49 -070047
48using std::chrono_literals::operator""ms;
49using std::chrono_literals::operator""s;
50
51namespace android {
52
Chris Ye0783e992020-06-02 21:34:49 -070053static const String16 kTestServiceName = String16("InputFlingerService");
54static const String16 kQueryServiceName = String16("InputFlingerQueryService");
55
Chris Ye0783e992020-06-02 21:34:49 -070056// --- InputFlingerServiceTest ---
57class InputFlingerServiceTest : public testing::Test {
58public:
59 void SetUp() override;
60 void TearDown() override;
61
62protected:
63 void InitializeInputFlinger();
Chris Ye0783e992020-06-02 21:34:49 -070064
65 sp<IInputFlinger> mService;
66 sp<IInputFlingerQuery> mQuery;
67
68private:
Siarhei Vishniakoud2588272020-07-10 11:15:40 -050069 std::unique_ptr<InputChannel> mServerChannel, mClientChannel;
Chris Ye0783e992020-06-02 21:34:49 -070070 std::mutex mLock;
Chris Ye0783e992020-06-02 21:34:49 -070071};
72
Chris Ye0783e992020-06-02 21:34:49 -070073
74class TestInputManager : public BnInputFlinger {
75protected:
76 virtual ~TestInputManager(){};
77
78public:
79 TestInputManager(){};
Chris Ye0783e992020-06-02 21:34:49 -070080
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -050081 binder::Status getInputChannels(std::vector<::android::InputChannel>* channels);
Chris Ye0783e992020-06-02 21:34:49 -070082
83 status_t dump(int fd, const Vector<String16>& args) override;
84
Garfield Tan15601662020-09-22 15:32:38 -070085 binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;
86 binder::Status removeInputChannel(const sp<IBinder>& connectionToken) override;
Vishnu Naire798b472020-07-23 13:52:21 -070087 binder::Status setFocusedWindow(const FocusRequest&) override;
Chris Ye0783e992020-06-02 21:34:49 -070088
Garfield Tan15601662020-09-22 15:32:38 -070089 void reset();
90
Chris Ye0783e992020-06-02 21:34:49 -070091private:
92 mutable Mutex mLock;
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -050093 std::vector<std::shared_ptr<InputChannel>> mInputChannels;
Chris Ye0783e992020-06-02 21:34:49 -070094};
95
96class TestInputQuery : public BnInputFlingerQuery {
97public:
98 TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){};
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -050099 binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override;
Garfield Tan15601662020-09-22 15:32:38 -0700100 binder::Status resetInputManager() override;
Chris Ye0783e992020-06-02 21:34:49 -0700101
102private:
103 sp<android::TestInputManager> mManager;
104};
105
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500106binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannel>* channels) {
107 return mManager->getInputChannels(channels);
Chris Ye0783e992020-06-02 21:34:49 -0700108}
109
Garfield Tan15601662020-09-22 15:32:38 -0700110binder::Status TestInputQuery::resetInputManager() {
111 mManager->reset();
112 return binder::Status::ok();
113}
114
Garfield Tan15601662020-09-22 15:32:38 -0700115binder::Status TestInputManager::createInputChannel(const std::string& name,
116 InputChannel* outChannel) {
Chris Ye0783e992020-06-02 21:34:49 -0700117 AutoMutex _l(mLock);
Garfield Tan15601662020-09-22 15:32:38 -0700118 std::unique_ptr<InputChannel> serverChannel;
119 std::unique_ptr<InputChannel> clientChannel;
120 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
Chris Ye0783e992020-06-02 21:34:49 -0700121
Garfield Tan15601662020-09-22 15:32:38 -0700122 clientChannel->copyTo(*outChannel);
123
124 mInputChannels.emplace_back(std::move(serverChannel));
Chris Ye0783e992020-06-02 21:34:49 -0700125
126 return binder::Status::ok();
127}
128
Garfield Tan15601662020-09-22 15:32:38 -0700129binder::Status TestInputManager::removeInputChannel(const sp<IBinder>& connectionToken) {
Chris Ye0783e992020-06-02 21:34:49 -0700130 AutoMutex _l(mLock);
Chris Ye0783e992020-06-02 21:34:49 -0700131
132 auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
Siarhei Vishniakouadefc3e2020-09-02 22:28:29 -0500133 [&](std::shared_ptr<InputChannel>& c) {
134 return c->getConnectionToken() == connectionToken;
135 });
Chris Ye0783e992020-06-02 21:34:49 -0700136 if (it != mInputChannels.end()) {
137 mInputChannels.erase(it);
138 }
139
140 return binder::Status::ok();
141}
142
143status_t TestInputManager::dump(int fd, const Vector<String16>& args) {
144 std::string dump;
145
146 dump += " InputFlinger dump\n";
147
148 ::write(fd, dump.c_str(), dump.size());
149 return NO_ERROR;
150}
151
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500152binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannel>* channels) {
153 channels->clear();
154 for (std::shared_ptr<InputChannel>& channel : mInputChannels) {
155 channels->push_back(*channel);
Chris Ye0783e992020-06-02 21:34:49 -0700156 }
157 return binder::Status::ok();
158}
159
Vishnu Naire798b472020-07-23 13:52:21 -0700160binder::Status TestInputManager::setFocusedWindow(const FocusRequest& request) {
Vishnu Naire798b472020-07-23 13:52:21 -0700161 return binder::Status::ok();
162}
163
Garfield Tan15601662020-09-22 15:32:38 -0700164void TestInputManager::reset() {
Garfield Tan15601662020-09-22 15:32:38 -0700165 mInputChannels.clear();
Garfield Tan15601662020-09-22 15:32:38 -0700166}
167
Chris Ye0783e992020-06-02 21:34:49 -0700168void InputFlingerServiceTest::SetUp() {
Chris Ye0783e992020-06-02 21:34:49 -0700169 InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
Chris Ye0783e992020-06-02 21:34:49 -0700170 InitializeInputFlinger();
171}
172
Garfield Tan15601662020-09-22 15:32:38 -0700173void InputFlingerServiceTest::TearDown() {
174 mQuery->resetInputManager();
175}
Chris Ye0783e992020-06-02 21:34:49 -0700176
Chris Ye0783e992020-06-02 21:34:49 -0700177void InputFlingerServiceTest::InitializeInputFlinger() {
178 sp<IBinder> input(defaultServiceManager()->waitForService(kTestServiceName));
179 ASSERT_TRUE(input != nullptr);
180 mService = interface_cast<IInputFlinger>(input);
181
182 input = defaultServiceManager()->waitForService(kQueryServiceName);
183 ASSERT_TRUE(input != nullptr);
184 mQuery = interface_cast<IInputFlingerQuery>(input);
185}
186
Chris Ye0783e992020-06-02 21:34:49 -0700187/**
Garfield Tan15601662020-09-22 15:32:38 -0700188 * Test InputFlinger service interface createInputChannel
Chris Ye0783e992020-06-02 21:34:49 -0700189 */
Garfield Tan15601662020-09-22 15:32:38 -0700190TEST_F(InputFlingerServiceTest, CreateInputChannelReturnsUnblockedFd) {
191 // Test that the unblocked file descriptor flag is kept across processes over binder
192 // transactions.
Chris Ye0783e992020-06-02 21:34:49 -0700193
Garfield Tan15601662020-09-22 15:32:38 -0700194 InputChannel channel;
195 ASSERT_TRUE(mService->createInputChannel("testchannels", &channel).isOk());
196
197 const base::unique_fd& fd = channel.getFd();
198 ASSERT_TRUE(fd.ok());
199
200 const int result = fcntl(fd, F_GETFL);
201 EXPECT_NE(result, -1);
202 EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
203}
204
chaviwbf023a62021-06-07 16:00:06 -0500205TEST_F(InputFlingerServiceTest, CreateInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -0700206 InputChannel channel;
207 ASSERT_TRUE(mService->createInputChannel("testchannels", &channel).isOk());
Chris Ye0783e992020-06-02 21:34:49 -0700208
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500209 std::vector<::android::InputChannel> channels;
210 mQuery->getInputChannels(&channels);
211 ASSERT_EQ(channels.size(), 1UL);
Garfield Tan15601662020-09-22 15:32:38 -0700212 EXPECT_EQ(channels[0].getConnectionToken(), channel.getConnectionToken());
Chris Ye0783e992020-06-02 21:34:49 -0700213
Garfield Tan15601662020-09-22 15:32:38 -0700214 mService->removeInputChannel(channel.getConnectionToken());
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500215 mQuery->getInputChannels(&channels);
216 EXPECT_EQ(channels.size(), 0UL);
Chris Ye0783e992020-06-02 21:34:49 -0700217}
218
219} // namespace android
220
221int main(int argc, char** argv) {
222 pid_t forkPid = fork();
223
224 if (forkPid == 0) {
225 // Server process
226 android::sp<android::TestInputManager> manager = new android::TestInputManager();
227 android::sp<android::TestInputQuery> query = new android::TestInputQuery(manager);
228
229 android::defaultServiceManager()->addService(android::kTestServiceName, manager,
230 false /*allowIsolated*/);
231 android::defaultServiceManager()->addService(android::kQueryServiceName, query,
232 false /*allowIsolated*/);
233 android::ProcessState::self()->startThreadPool();
234 android::IPCThreadState::self()->joinThreadPool();
235 } else {
236 android::ProcessState::self()->startThreadPool();
237 ::testing::InitGoogleTest(&argc, argv);
Chris Yec4669842020-07-14 17:10:09 -0700238 int result = RUN_ALL_TESTS();
239 kill(forkPid, SIGKILL);
240 return result;
Chris Ye0783e992020-06-02 21:34:49 -0700241 }
242 return 0;
243}