1 /*
2 * Copyright (C) 2024 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 #define LOG_TAG "service_singleton_tests"
18
19 #include <mediautils/ServiceSingleton.h>
20
21 #include "BnServiceSingletonTest.h"
22 #include "aidl/BnServiceSingletonTest.h"
23 #include <audio_utils/RunRemote.h>
24 #include <binder/IPCThreadState.h>
25 #include <binder/ProcessState.h>
26 #include <gtest/gtest.h>
27 #include <utils/Log.h>
28
29 using namespace android;
30
31 /**
32 * Service Singleton Test uses a worker process to spawn new binder services.
33 *
34 * A worker process is required since we cannot fork after registering
35 * with the binder driver.
36 *
37 * Test Process -> Worker_Process -> Service Process(1)
38 * -> Service Process(2)
39 * -> ....
40 */
41
42 // Service implementation.
43 class ServiceSingletonTestCpp : public BnServiceSingletonTest {
44 public:
inc(int32_t * _aidl_return)45 binder::Status inc(int32_t* _aidl_return) final {
46 *_aidl_return = ++mValue;
47 return binder::Status::ok();
48 }
49 std::atomic_int32_t mValue = 0;
50 };
51
52 // The service traits increment static atomic counters, which
53 // validates that the trait callbacks are invoked.
54 static std::atomic_int32_t sNewService = 0;
55 static std::atomic_int32_t sServiceDied = 0;
56
57 template <typename Service>
58 struct TestServiceTraits : public mediautils::DefaultServiceTraits<Service> {
getServiceNameTestServiceTraits59 static constexpr const char* getServiceName() { return ""; }
onNewServiceTestServiceTraits60 static constexpr void onNewService(const mediautils::InterfaceType<Service>&) {
61 ++sNewService;
62 }
onServiceDiedTestServiceTraits63 static constexpr void onServiceDied(const mediautils::InterfaceType<Service>&) {
64 ++sServiceDied;
65 }
66 };
67
68 // Here we have an alternative set of service traits,
69 // used to validate that we can switch traits for the service singleton.
70 static std::atomic_int32_t sNewService2 = 0;
71 static std::atomic_int32_t sServiceDied2 = 0;
72
73 template <typename Service>
74 struct TestServiceTraits2 : public mediautils::DefaultServiceTraits<Service> {
getServiceNameTestServiceTraits275 static constexpr const char* getServiceName() { return ""; }
onNewServiceTestServiceTraits276 static constexpr void onNewService(const mediautils::InterfaceType<Service>&) {
77 ++sNewService2;
78 }
onServiceDiedTestServiceTraits279 static constexpr void onServiceDied(const mediautils::InterfaceType<Service>&) {
80 ++sServiceDied2;
81 }
82 };
83
84 /*
85 * ServiceThreads run in a remote process.
86 *
87 * The WorkerThread is used to launch and kill the ServiceThread in a remote process.
88 */
ServiceThread(audio_utils::RunRemote & runRemote)89 static void ServiceThread(audio_utils::RunRemote& runRemote) {
90 int c = runRemote.getc(); // requires any character to launch
91 auto service = sp<IServiceSingletonTest>::cast(sp<ServiceSingletonTestCpp>::make());
92 mediautils::addService(service);
93 ProcessState::self()->startThreadPool();
94 runRemote.putc(c); // echo character.
95 IPCThreadState::self()->joinThreadPool();
96 }
97
98 /*
99 * The WorkerThread is run in a remote process from the test. It communicates with
100 * the test process through pipes.
101 */
WorkerThread(audio_utils::RunRemote & runRemote)102 static void WorkerThread(audio_utils::RunRemote& runRemote) {
103 std::shared_ptr<audio_utils::RunRemote> remoteService;
104 while (true) {
105 const int c = runRemote.getc();
106 switch (c) {
107 case 'a': // launch a new service.
108 // if the old service isn't destroyed, it will be destroyed here
109 // when the RunRemote is replaced.
110 remoteService = std::make_shared<audio_utils::RunRemote>(ServiceThread);
111 remoteService->run();
112 remoteService->putc('a'); // create service.
113 (void)remoteService->getc(); // ensure it is created.
114 runRemote.putc(c); // echo
115 break;
116 case 'b': // destroys the old service.
117 remoteService.reset(); // this kills the service.
118 runRemote.putc(c); // echo
119 break;
120 default: // respond that we don't know what happened!
121 runRemote.putc('?');
122 break;
123 }
124 }
125 }
126
127 // This is a monolithic test.
TEST(service_singleton_tests,one_and_only)128 TEST(service_singleton_tests, one_and_only) {
129 std::atomic_int32_t listenerServiceCreated = 0;
130 std::atomic_int32_t listenerServiceDied = 0;
131
132 // initialize the service cache with a custom handler.
133 mediautils::initService<
134 IServiceSingletonTest, TestServiceTraits<IServiceSingletonTest>>({});
135 mediautils::initService<
136 aidl::IServiceSingletonTest, TestServiceTraits<aidl::IServiceSingletonTest>>({});
137
138 // start the worker thread that spawns the services.
139 auto remoteWorker = std::make_shared<audio_utils::RunRemote>(WorkerThread);
140 remoteWorker->run();
141
142 // now we are ready for binder.
143 ProcessState::self()->startThreadPool();
144
145 // check that our service isn't preexisting.
146 {
147 auto service = mediautils::checkServicePassThrough<IServiceSingletonTest>();
148 EXPECT_FALSE(service);
149
150 auto service2 = mediautils::checkServicePassThrough<aidl::IServiceSingletonTest>();
151 EXPECT_FALSE(service2);
152 }
153 EXPECT_EQ(0, sNewService);
154 EXPECT_EQ(0, sServiceDied);
155
156 {
157 auto service = mediautils::checkService<IServiceSingletonTest>();
158 EXPECT_FALSE(service);
159
160 auto service2 = mediautils::checkService<aidl::IServiceSingletonTest>();
161 EXPECT_FALSE(service2);
162 }
163 EXPECT_EQ(0, sNewService);
164 EXPECT_EQ(0, sServiceDied);
165
166 // getService will register a notification handler that fetches the
167 // service in the background.
168 {
169 auto service = mediautils::getService<IServiceSingletonTest>();
170 EXPECT_FALSE(service);
171
172 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>();
173 EXPECT_FALSE(service2);
174 }
175 EXPECT_EQ(0, sNewService);
176 EXPECT_EQ(0, sServiceDied);
177
178 // now spawn the service.
179 remoteWorker->putc('a');
180 EXPECT_EQ('a', remoteWorker->getc());
181
182 sleep(1); // In the background, 2 services were fetched.
183
184 EXPECT_EQ(2, sNewService);
185 EXPECT_EQ(0, sServiceDied);
186
187 // we repeat the prior checks, but the service is cached now.
188 {
189 auto service = mediautils::checkServicePassThrough<IServiceSingletonTest>();
190 EXPECT_TRUE(service);
191
192 auto service2 = mediautils::checkServicePassThrough<aidl::IServiceSingletonTest>();
193 EXPECT_TRUE(service2);
194 }
195 EXPECT_EQ(2, sNewService);
196 EXPECT_EQ(0, sServiceDied);
197
198 {
199 auto service = mediautils::checkService<IServiceSingletonTest>();
200 EXPECT_TRUE(service);
201
202 auto service2 = mediautils::checkService<aidl::IServiceSingletonTest>();
203 EXPECT_TRUE(service2);
204 }
205 EXPECT_EQ(2, sNewService);
206 EXPECT_EQ(0, sServiceDied);
207
208 {
209 auto service = mediautils::getService<IServiceSingletonTest>();
210 EXPECT_TRUE(service);
211
212 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>();
213 EXPECT_TRUE(service2);
214 }
215 EXPECT_EQ(2, sNewService);
216 EXPECT_EQ(0, sServiceDied);
217
218 // destroy the service.
219 remoteWorker->putc('b');
220 EXPECT_EQ('b', remoteWorker->getc());
221
222 sleep(1);
223
224 // We expect the died callbacks.
225 EXPECT_EQ(2, sNewService);
226 EXPECT_EQ(2, sServiceDied);
227
228 // we can also manually check whether there is a new service by
229 // requesting service notifications. This is outside of the service singleton
230 // traits.
231 auto handle1 = mediautils::requestServiceNotification<IServiceSingletonTest>(
232 [&](const sp<IServiceSingletonTest>&) { ++listenerServiceCreated; });
233 auto handle2 = mediautils::requestServiceNotification<aidl::IServiceSingletonTest>(
234 [&](const std::shared_ptr<aidl::IServiceSingletonTest>&) {
235 ++listenerServiceCreated; });
236
237 // Spawn the service again.
238 remoteWorker->putc('a');
239 EXPECT_EQ('a', remoteWorker->getc());
240
241 sleep(1); // In the background, 2 services were fetched.
242
243 EXPECT_EQ(4, sNewService);
244 EXPECT_EQ(2, sServiceDied);
245
246 EXPECT_EQ(2, listenerServiceCreated); // our listener picked up the service creation.
247
248 std::shared_ptr<void> handle3, handle4;
249 std::shared_ptr<aidl::IServiceSingletonTest> keepAlive; // NDK Workaround!
250 {
251 auto service = mediautils::getService<IServiceSingletonTest>();
252 EXPECT_TRUE(service);
253
254 // mediautils::getService<> is a cached service.
255 // pointer equality is preserved for subsequent requests.
256 auto service_equal = mediautils::getService<IServiceSingletonTest>();
257 EXPECT_EQ(service, service_equal);
258 EXPECT_TRUE(mediautils::isSameInterface(service, service_equal));
259
260 // we can create an alias to the service by requesting it outside of the cache.
261 // this is a different pointer, but same underlying binder object.
262 auto service_equivalent =
263 mediautils::checkServicePassThrough<IServiceSingletonTest>();
264 EXPECT_NE(service, service_equivalent);
265 EXPECT_TRUE(mediautils::isSameInterface(service, service_equivalent));
266
267 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>();
268 EXPECT_TRUE(service2);
269
270 // mediautils::getService<> is a cached service.
271 // pointer equality is preserved for subsequent requests.
272 auto service2_equal = mediautils::getService<aidl::IServiceSingletonTest>();
273 EXPECT_EQ(service2, service2_equal);
274 EXPECT_TRUE(mediautils::isSameInterface(service2, service2_equal));
275
276 // we can create an alias to the service by requesting it outside of the cache.
277 // this is a different pointer, but same underlying binder object.
278 auto service2_equivalent =
279 mediautils::checkServicePassThrough<aidl::IServiceSingletonTest>();
280 EXPECT_NE(service2, service2_equivalent);
281 EXPECT_TRUE(mediautils::isSameInterface(service2, service2_equivalent));
282
283 keepAlive = service2;
284
285 // we can also request our own death notifications (outside of the service traits).
286 handle3 = mediautils::requestDeathNotification(service, [&] { ++listenerServiceDied; });
287 EXPECT_TRUE(handle3);
288 handle4 = mediautils::requestDeathNotification(service2, [&] { ++listenerServiceDied; });
289 EXPECT_TRUE(handle4);
290 }
291
292 EXPECT_EQ(4, sNewService);
293 EXPECT_EQ(2, sServiceDied);
294
295 // destroy the service.
296
297 remoteWorker->putc('b');
298 EXPECT_EQ('b', remoteWorker->getc());
299
300 sleep(1);
301
302 // We expect the died callbacks.
303 EXPECT_EQ(4, sNewService);
304 EXPECT_EQ(4, sServiceDied);
305
306 EXPECT_EQ(2, listenerServiceCreated);
307 EXPECT_EQ(2, listenerServiceDied); // NDK Workaround - without keepAlive, this is 1.
308 // the death notification is invalidated without a
309 // pointer to the binder object.
310
311 keepAlive.reset();
312
313 // Cancel the singleton cache.
314 mediautils::skipService<IServiceSingletonTest>();
315 mediautils::skipService<aidl::IServiceSingletonTest>();
316
317 // Spawn the service again.
318 remoteWorker->putc('a');
319 EXPECT_EQ('a', remoteWorker->getc());
320
321 sleep(1);
322
323 // We expect no change from the service traits (service not cached).
324 EXPECT_EQ(4, sNewService);
325 EXPECT_EQ(4, sServiceDied);
326 EXPECT_EQ(4, listenerServiceCreated); // our listener picks it up.
327
328 {
329 // in default mode (kNull) a null is returned when the service is skipped and
330 // wait time is ignored.
331
332 const auto ref1 = std::chrono::steady_clock::now();
333 auto service = mediautils::getService<IServiceSingletonTest>(std::chrono::seconds(2));
334 EXPECT_FALSE(service);
335 const auto ref2 = std::chrono::steady_clock::now();
336 EXPECT_LT(ref2 - ref1, std::chrono::seconds(1));
337
338 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>(
339 std::chrono::seconds(2));
340 EXPECT_FALSE(service2);
341 const auto ref3 = std::chrono::steady_clock::now();
342 EXPECT_LT(ref3 - ref2, std::chrono::seconds(1));
343 }
344
345 // Cancel the singleton cache but use wait mode.
346 mediautils::skipService<IServiceSingletonTest>(mediautils::SkipMode::kWait);
347 mediautils::skipService<aidl::IServiceSingletonTest>(mediautils::SkipMode::kWait);
348
349 {
350 // in wait mode, the timeouts are respected
351 const auto ref1 = std::chrono::steady_clock::now();
352 auto service = mediautils::getService<IServiceSingletonTest>(std::chrono::seconds(1));
353 EXPECT_FALSE(service);
354 const auto ref2 = std::chrono::steady_clock::now();
355 EXPECT_GT(ref2 - ref1, std::chrono::seconds(1));
356
357 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>(
358 std::chrono::seconds(1));
359 EXPECT_FALSE(service2);
360 const auto ref3 = std::chrono::steady_clock::now();
361 EXPECT_GT(ref3 - ref2, std::chrono::seconds(1));
362 }
363
364 // remove service
365 remoteWorker->putc('b');
366 EXPECT_EQ('b', remoteWorker->getc());
367
368 sleep(1);
369
370 // We expect no change from the service traits (service not cached).
371 EXPECT_EQ(4, sNewService);
372 EXPECT_EQ(4, sServiceDied);
373 EXPECT_EQ(4, listenerServiceCreated);
374 EXPECT_EQ(2, listenerServiceDied); // binder died is associated with the actual handle.
375
376 // replace the service traits.
377 {
378 auto previous = mediautils::initService<
379 IServiceSingletonTest, TestServiceTraits2<IServiceSingletonTest>>({});
380 auto previous2 = mediautils::initService<
381 aidl::IServiceSingletonTest, TestServiceTraits2<aidl::IServiceSingletonTest>>({});
382
383 EXPECT_FALSE(previous);
384 EXPECT_FALSE(previous2);
385 }
386
387 // We expect no change with old counters.
388 EXPECT_EQ(4, sNewService);
389 EXPECT_EQ(4, sServiceDied);
390 EXPECT_EQ(0, sNewService2);
391 EXPECT_EQ(0, sServiceDied2);
392
393 {
394 auto service = mediautils::getService<IServiceSingletonTest>();
395 EXPECT_FALSE(service);
396
397 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>();
398 EXPECT_FALSE(service2);
399 }
400
401 EXPECT_EQ(4, sNewService);
402 EXPECT_EQ(4, sServiceDied);
403 EXPECT_EQ(0, sNewService2);
404 EXPECT_EQ(0, sServiceDied2);
405
406 // Spawn the service again.
407 remoteWorker->putc('a');
408 EXPECT_EQ('a', remoteWorker->getc());
409
410 sleep(1);
411
412 EXPECT_EQ(4, sNewService); // old counters do not change.
413 EXPECT_EQ(4, sServiceDied);
414 EXPECT_EQ(2, sNewService2); // new counters change
415 EXPECT_EQ(0, sServiceDied2);
416
417 EXPECT_EQ(6, listenerServiceCreated); // listener associated with service name picks up info.
418
419 // get service pointers that will be made stale later.
420 auto stale_service = mediautils::getService<IServiceSingletonTest>();
421 EXPECT_TRUE(stale_service); // not stale yet.
422
423 auto stale_service2 = mediautils::getService<aidl::IServiceSingletonTest>();
424 EXPECT_TRUE(stale_service2); // not stale yet.
425
426 // Release the service.
427 remoteWorker->putc('b');
428 EXPECT_EQ('b', remoteWorker->getc());
429
430 sleep(1);
431
432 EXPECT_EQ(4, sNewService); // old counters do not change.
433 EXPECT_EQ(4, sServiceDied);
434 EXPECT_EQ(2, sNewService2); // new counters change
435 EXPECT_EQ(2, sServiceDied2);
436
437 // The service handles are now stale, verify that we can't register a death notification.
438 {
439 std::atomic_int32_t postDied = 0;
440 // we cannot register death notification so handles are null.
441 auto handle1 = mediautils::requestDeathNotification(stale_service, [&] { ++postDied; });
442 EXPECT_FALSE(handle1);
443 auto handle2= mediautils::requestDeathNotification(stale_service2, [&] { ++postDied; });
444 EXPECT_FALSE(handle2);
445 EXPECT_EQ(0, postDied); // no callbacks issued.
446 }
447 }
448