1 /*
2 * Copyright (C) 2019, 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 <cstdlib>
18 #include <ctime>
19 #include <iostream>
20 #include <numeric>
21 #include <string>
22 #include <thread>
23
24 #include <sys/epoll.h>
25 #include <sys/eventfd.h>
26 #include <unistd.h>
27
28 #include <android-base/properties.h>
29 #include <android-base/unique_fd.h>
30 #include <android/hardware/tests/lazy/1.1/ILazy.h>
31 #include <android/hardware/tests/lazy_cb/1.0/ILazyCb.h>
32 #include <android/hidl/manager/1.2/IServiceManager.h>
33 #include <cutils/native_handle.h>
34 #include <gtest/gtest.h>
35 #include <hidl-util/FqInstance.h>
36 #include <hidl/HidlSupport.h>
37 #include <hidl/HidlTransportSupport.h>
38 #include <hidl/HidlTransportUtils.h>
39 #include <hwbinder/IPCThreadState.h>
40
41 using ::android::FqInstance;
42 using ::android::sp;
43 using ::android::base::unique_fd;
44 using ::android::hardware::hidl_handle;
45 using ::android::hardware::hidl_string;
46 using ::android::hardware::hidl_vec;
47 using ::android::hardware::IPCThreadState;
48 using ::android::hardware::Return;
49 using ::android::hardware::tests::lazy::V1_1::ILazy;
50 using ::android::hardware::tests::lazy_cb::V1_0::ILazyCb;
51 using ::android::hidl::base::V1_0::IBase;
52 using ::android::hidl::manager::V1_2::IServiceManager;
53
54 static std::vector<FqInstance> gInstances;
55
getHal(const FqInstance & instance)56 sp<IBase> getHal(const FqInstance& instance) {
57 return ::android::hardware::details::getRawServiceInternal(instance.getFqName().string(),
58 instance.getInstance(),
59 true /*retry*/, false /*getStub*/);
60 }
61
62 class HidlLazyTestBase : public ::testing::Test {
63 protected:
64 static constexpr size_t SHUTDOWN_WAIT_TIME = 10;
65 sp<IServiceManager> manager;
66
SetUp()67 void SetUp() override {
68 manager = IServiceManager::getService();
69 ASSERT_NE(manager, nullptr);
70 }
71
isServiceRunning(const FqInstance & instance)72 bool isServiceRunning(const FqInstance& instance) {
73 bool isRunning = false;
74 EXPECT_TRUE(manager->listByInterface(instance.getFqName().string(),
75 [&](const hidl_vec<hidl_string>& instanceNames) {
76 for (const hidl_string& name : instanceNames) {
77 if (name == instance.getInstance()) {
78 isRunning = true;
79 break;
80 }
81 }
82 })
83 .isOk());
84 return isRunning;
85 }
86 };
87
88 class HidlLazyTest : public HidlLazyTestBase {
89 protected:
SetUp()90 void SetUp() override {
91 HidlLazyTestBase::SetUp();
92 for (const auto& instance : gInstances) {
93 ASSERT_FALSE(isServiceRunning(instance))
94 << "Service '" << instance.string()
95 << "' is already running. Please ensure this "
96 << "service is implemented as a lazy HAL, then kill all "
97 << "clients of this service and try again.";
98 }
99 }
100
TearDown()101 void TearDown() override {
102 std::cout << "Waiting " << SHUTDOWN_WAIT_TIME << " seconds before checking that the "
103 << "service has shut down." << std::endl;
104 IPCThreadState::self()->flushCommands();
105 int timeout_multiplier = android::base::GetIntProperty("ro.hw_timeout_multiplier", 1);
106 sleep(SHUTDOWN_WAIT_TIME * timeout_multiplier);
107 for (const auto& instance : gInstances) {
108 ASSERT_FALSE(isServiceRunning(instance))
109 << "Service failed to shutdown " << instance.string();
110 }
111 }
112 };
113
114 class HidlLazyCbTest : public HidlLazyTestBase {
115 protected:
116 static constexpr size_t CALLBACK_SHUTDOWN_WAIT_TIME = 5;
117 };
118
119 static constexpr size_t NUM_IMMEDIATE_GET_UNGETS = 100;
TEST_F(HidlLazyTest,GetUnget)120 TEST_F(HidlLazyTest, GetUnget) {
121 for (size_t i = 0; i < NUM_IMMEDIATE_GET_UNGETS; i++) {
122 IPCThreadState::self()->flushCommands();
123 for (const auto& instance : gInstances) {
124 sp<IBase> hal = getHal(instance);
125 ASSERT_NE(hal.get(), nullptr);
126 EXPECT_TRUE(hal->ping().isOk());
127 }
128 }
129 }
130
waitTimes(size_t numTimes,size_t maxWait)131 static std::vector<size_t> waitTimes(size_t numTimes, size_t maxWait) {
132 std::vector<size_t> times(numTimes);
133 for (size_t i = 0; i < numTimes; i++) {
134 times[i] = (size_t)(rand() % (maxWait + 1));
135 }
136 return times;
137 }
138
testWithTimes(const std::vector<size_t> & waitTimes,const FqInstance & instance)139 static void testWithTimes(const std::vector<size_t>& waitTimes, const FqInstance& instance) {
140 std::cout << "Note runtime expected from sleeps: "
141 << std::accumulate(waitTimes.begin(), waitTimes.end(), 0) << " second(s)."
142 << std::endl;
143
144 for (size_t sleepTime : waitTimes) {
145 IPCThreadState::self()->flushCommands();
146 std::cout << "Thread for " << instance.string() << " waiting " << sleepTime
147 << " while not holding HAL." << std::endl;
148 int timeout_multiplier = android::base::GetIntProperty("ro.hw_timeout_multiplier", 1);
149 sleep(sleepTime * timeout_multiplier);
150 sp<IBase> hal = getHal(instance);
151 ASSERT_NE(hal.get(), nullptr);
152 ASSERT_TRUE(hal->ping().isOk());
153 }
154 }
155
156 static constexpr size_t NUM_TIMES_GET_UNGET = 5;
157 static constexpr size_t MAX_WAITING_DURATION = 10;
158 static constexpr size_t NUM_CONCURRENT_THREADS = 5;
TEST_F(HidlLazyTest,GetWithWaitConcurrent)159 TEST_F(HidlLazyTest, GetWithWaitConcurrent) {
160 std::vector<std::vector<size_t>> threadWaitTimes(NUM_CONCURRENT_THREADS);
161
162 for (size_t i = 0; i < threadWaitTimes.size(); i++) {
163 threadWaitTimes[i] = waitTimes(NUM_TIMES_GET_UNGET, MAX_WAITING_DURATION);
164 }
165
166 std::vector<std::thread> threads(NUM_CONCURRENT_THREADS);
167 for (size_t i = 0; i < threads.size(); i++) {
168 const FqInstance& instance = gInstances[i % gInstances.size()];
169 threads[i] = std::thread(testWithTimes, threadWaitTimes[i], instance);
170 }
171
172 for (auto& thread : threads) {
173 thread.join();
174 }
175 }
176
TEST_F(HidlLazyCbTest,ActiveServicesCallbackTest)177 TEST_F(HidlLazyCbTest, ActiveServicesCallbackTest) {
178 const std::string fqInstanceName = "android.hardware.tests.lazy_cb@1.0::ILazyCb/default";
179 FqInstance fqInstance;
180 ASSERT_TRUE(fqInstance.setTo(fqInstanceName));
181
182 // b/251244025 - this service logic is coupled with this test, but other
183 // things may have started it
184 (void)android::base::SetProperty("ctl.stop", "hidl_lazy_cb_test_server");
185
186 ASSERT_FALSE(isServiceRunning(fqInstance)) << "Lazy service already running.";
187
188 sp<IBase> hal = getHal(fqInstance);
189 ASSERT_NE(hal, nullptr);
190
191 sp<ILazyCb> lazyCb = ILazyCb::castFrom(hal);
192 ASSERT_NE(lazyCb, nullptr);
193 hal = nullptr;
194
195 int efd = eventfd(0, 0);
196 ASSERT_GE(efd, 0) << "Failed to create eventfd";
197 unique_fd uniqueEventFd(efd);
198
199 native_handle_t* h = native_handle_create(/* numFds */ 1, /* numInts */ 0);
200 h->data[0] = efd;
201 hidl_handle handle(h);
202 Return<bool> setEventFdRet = lazyCb->setEventFd(handle);
203 native_handle_delete(h);
204 ASSERT_TRUE(setEventFdRet.isOk());
205 ASSERT_TRUE(setEventFdRet);
206
207 lazyCb = nullptr;
208
209 IPCThreadState::self()->flushCommands();
210
211 std::cout << "Waiting " << SHUTDOWN_WAIT_TIME << " seconds for callback completion "
212 << "notification." << std::endl;
213
214 int epollFd = epoll_create1(EPOLL_CLOEXEC);
215 ASSERT_GE(epollFd, 0) << "Failed to create epoll";
216 unique_fd epollUniqueFd(epollFd);
217
218 const int EPOLL_MAX_EVENTS = 1;
219 struct epoll_event event, events[EPOLL_MAX_EVENTS];
220
221 event.events = EPOLLIN;
222 event.data.fd = efd;
223 int rc = epoll_ctl(epollFd, EPOLL_CTL_ADD, efd, &event);
224 ASSERT_GE(rc, 0) << "Failed to add fd to epoll";
225
226 rc = TEMP_FAILURE_RETRY(
227 epoll_wait(epollFd, events, EPOLL_MAX_EVENTS, SHUTDOWN_WAIT_TIME * 1000));
228 ASSERT_NE(rc, 0) << "Service shutdown timeout";
229 ASSERT_GT(rc, 0) << "Error waiting for service shutdown notification";
230
231 eventfd_t counter;
232 rc = TEMP_FAILURE_RETRY(eventfd_read(uniqueEventFd.get(), &counter));
233 ASSERT_GE(rc, 0) << "Failed to get callback completion notification from service";
234 ASSERT_EQ(counter, 1);
235
236 std::cout << "Waiting " << CALLBACK_SHUTDOWN_WAIT_TIME
237 << " seconds before checking whether the "
238 << "service is still running." << std::endl;
239
240 int timeout_multiplier = android::base::GetIntProperty("ro.hw_timeout_multiplier", 1);
241 sleep(CALLBACK_SHUTDOWN_WAIT_TIME * timeout_multiplier);
242
243 ASSERT_FALSE(isServiceRunning(fqInstance)) << "Service failed to shut down.";
244 }
245
main(int argc,char ** argv)246 int main(int argc, char** argv) {
247 ::testing::InitGoogleTest(&argc, argv);
248
249 srand(time(nullptr));
250
251 std::vector<std::string> fqInstances;
252
253 if (argc == 1) {
254 fqInstances.push_back("android.hardware.tests.lazy@1.0::ILazy/default1");
255 fqInstances.push_back("android.hardware.tests.lazy@1.0::ILazy/default2");
256 } else {
257 for (size_t arg = 1; arg < argc; arg++) {
258 fqInstances.push_back(argv[arg]);
259 }
260 }
261
262 for (const std::string& instance : fqInstances) {
263 FqInstance fqInstance;
264 if (!fqInstance.setTo(instance)) {
265 std::cerr << "Invalid fqinstance: " << instance << std::endl;
266 return 1;
267 }
268 gInstances.push_back(fqInstance);
269 }
270
271 return RUN_ALL_TESTS();
272 }
273