• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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