1 /*
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/IInputFlinger.h>
22
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>
31
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
44 using android::gui::FocusRequest;
45 using android::os::BnInputFlinger;
46 using android::os::IInputFlinger;
47
48 using std::chrono_literals::operator""ms;
49 using std::chrono_literals::operator""s;
50
51 namespace android {
52
53 static const String16 kTestServiceName = String16("InputFlingerService");
54 static const String16 kQueryServiceName = String16("InputFlingerQueryService");
55
56 // --- InputFlingerServiceTest ---
57 class InputFlingerServiceTest : public testing::Test {
58 public:
59 void SetUp() override;
60 void TearDown() override;
61
62 protected:
63 void InitializeInputFlinger();
64
65 sp<IInputFlinger> mService;
66 sp<IInputFlingerQuery> mQuery;
67
68 private:
69 std::unique_ptr<InputChannel> mServerChannel, mClientChannel;
70 std::mutex mLock;
71 };
72
73
74 class TestInputManager : public BnInputFlinger {
75 protected:
~TestInputManager()76 virtual ~TestInputManager(){};
77
78 public:
TestInputManager()79 TestInputManager(){};
80
81 binder::Status getInputChannels(std::vector<::android::InputChannel>* channels);
82
83 status_t dump(int fd, const Vector<String16>& args) override;
84
85 binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;
86 binder::Status removeInputChannel(const sp<IBinder>& connectionToken) override;
87 binder::Status setFocusedWindow(const FocusRequest&) override;
88
89 void reset();
90
91 private:
92 mutable Mutex mLock;
93 std::vector<std::shared_ptr<InputChannel>> mInputChannels;
94 };
95
96 class TestInputQuery : public BnInputFlingerQuery {
97 public:
TestInputQuery(sp<android::TestInputManager> manager)98 TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){};
99 binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override;
100 binder::Status resetInputManager() override;
101
102 private:
103 sp<android::TestInputManager> mManager;
104 };
105
getInputChannels(std::vector<::android::InputChannel> * channels)106 binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannel>* channels) {
107 return mManager->getInputChannels(channels);
108 }
109
resetInputManager()110 binder::Status TestInputQuery::resetInputManager() {
111 mManager->reset();
112 return binder::Status::ok();
113 }
114
createInputChannel(const std::string & name,InputChannel * outChannel)115 binder::Status TestInputManager::createInputChannel(const std::string& name,
116 InputChannel* outChannel) {
117 AutoMutex _l(mLock);
118 std::unique_ptr<InputChannel> serverChannel;
119 std::unique_ptr<InputChannel> clientChannel;
120 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
121
122 clientChannel->copyTo(*outChannel);
123
124 mInputChannels.emplace_back(std::move(serverChannel));
125
126 return binder::Status::ok();
127 }
128
removeInputChannel(const sp<IBinder> & connectionToken)129 binder::Status TestInputManager::removeInputChannel(const sp<IBinder>& connectionToken) {
130 AutoMutex _l(mLock);
131
132 auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
133 [&](std::shared_ptr<InputChannel>& c) {
134 return c->getConnectionToken() == connectionToken;
135 });
136 if (it != mInputChannels.end()) {
137 mInputChannels.erase(it);
138 }
139
140 return binder::Status::ok();
141 }
142
dump(int fd,const Vector<String16> & args)143 status_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
getInputChannels(std::vector<::android::InputChannel> * channels)152 binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannel>* channels) {
153 channels->clear();
154 for (std::shared_ptr<InputChannel>& channel : mInputChannels) {
155 channels->push_back(*channel);
156 }
157 return binder::Status::ok();
158 }
159
setFocusedWindow(const FocusRequest & request)160 binder::Status TestInputManager::setFocusedWindow(const FocusRequest& request) {
161 return binder::Status::ok();
162 }
163
reset()164 void TestInputManager::reset() {
165 mInputChannels.clear();
166 }
167
SetUp()168 void InputFlingerServiceTest::SetUp() {
169 InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
170 InitializeInputFlinger();
171 }
172
TearDown()173 void InputFlingerServiceTest::TearDown() {
174 mQuery->resetInputManager();
175 }
176
InitializeInputFlinger()177 void 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
187 /**
188 * Test InputFlinger service interface createInputChannel
189 */
TEST_F(InputFlingerServiceTest,CreateInputChannelReturnsUnblockedFd)190 TEST_F(InputFlingerServiceTest, CreateInputChannelReturnsUnblockedFd) {
191 // Test that the unblocked file descriptor flag is kept across processes over binder
192 // transactions.
193
194 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
TEST_F(InputFlingerServiceTest,CreateInputChannel)205 TEST_F(InputFlingerServiceTest, CreateInputChannel) {
206 InputChannel channel;
207 ASSERT_TRUE(mService->createInputChannel("testchannels", &channel).isOk());
208
209 std::vector<::android::InputChannel> channels;
210 mQuery->getInputChannels(&channels);
211 ASSERT_EQ(channels.size(), 1UL);
212 EXPECT_EQ(channels[0].getConnectionToken(), channel.getConnectionToken());
213
214 mService->removeInputChannel(channel.getConnectionToken());
215 mQuery->getInputChannels(&channels);
216 EXPECT_EQ(channels.size(), 0UL);
217 }
218
219 } // namespace android
220
main(int argc,char ** argv)221 int 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);
238 int result = RUN_ALL_TESTS();
239 kill(forkPid, SIGKILL);
240 return result;
241 }
242 return 0;
243 }
244