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 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>();
255 EXPECT_TRUE(service2);
256
257 keepAlive = service2;
258
259 // we can also request our own death notifications (outside of the service traits).
260 handle3 = mediautils::requestDeathNotification(service, [&] { ++listenerServiceDied; });
261 EXPECT_TRUE(handle3);
262 handle4 = mediautils::requestDeathNotification(service2, [&] { ++listenerServiceDied; });
263 EXPECT_TRUE(handle4);
264 }
265
266 EXPECT_EQ(4, sNewService);
267 EXPECT_EQ(2, sServiceDied);
268
269 // destroy the service.
270
271 remoteWorker->putc('b');
272 EXPECT_EQ('b', remoteWorker->getc());
273
274 sleep(1);
275
276 // We expect the died callbacks.
277 EXPECT_EQ(4, sNewService);
278 EXPECT_EQ(4, sServiceDied);
279
280 EXPECT_EQ(2, listenerServiceCreated);
281 EXPECT_EQ(2, listenerServiceDied); // NDK Workaround - without keepAlive, this is 1.
282 // the death notification is invalidated without a
283 // pointer to the binder object.
284
285 keepAlive.reset();
286
287 // Cancel the singleton cache.
288 mediautils::skipService<IServiceSingletonTest>();
289 mediautils::skipService<aidl::IServiceSingletonTest>();
290
291 // Spawn the service again.
292 remoteWorker->putc('a');
293 EXPECT_EQ('a', remoteWorker->getc());
294
295 sleep(1);
296
297 // We expect no change from the service traits (service not cached).
298 EXPECT_EQ(4, sNewService);
299 EXPECT_EQ(4, sServiceDied);
300 EXPECT_EQ(4, listenerServiceCreated); // our listener picks it up.
301
302 {
303 // in default mode (kNull) a null is returned when the service is skipped and
304 // wait time is ignored.
305
306 const auto ref1 = std::chrono::steady_clock::now();
307 auto service = mediautils::getService<IServiceSingletonTest>(std::chrono::seconds(2));
308 EXPECT_FALSE(service);
309 const auto ref2 = std::chrono::steady_clock::now();
310 EXPECT_LT(ref2 - ref1, std::chrono::seconds(1));
311
312 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>(
313 std::chrono::seconds(2));
314 EXPECT_FALSE(service2);
315 const auto ref3 = std::chrono::steady_clock::now();
316 EXPECT_LT(ref3 - ref2, std::chrono::seconds(1));
317 }
318
319 // Cancel the singleton cache but use wait mode.
320 mediautils::skipService<IServiceSingletonTest>(mediautils::SkipMode::kWait);
321 mediautils::skipService<aidl::IServiceSingletonTest>(mediautils::SkipMode::kWait);
322
323 {
324 // in wait mode, the timeouts are respected
325 const auto ref1 = std::chrono::steady_clock::now();
326 auto service = mediautils::getService<IServiceSingletonTest>(std::chrono::seconds(1));
327 EXPECT_FALSE(service);
328 const auto ref2 = std::chrono::steady_clock::now();
329 EXPECT_GT(ref2 - ref1, std::chrono::seconds(1));
330
331 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>(
332 std::chrono::seconds(1));
333 EXPECT_FALSE(service2);
334 const auto ref3 = std::chrono::steady_clock::now();
335 EXPECT_GT(ref3 - ref2, std::chrono::seconds(1));
336 }
337
338 // remove service
339 remoteWorker->putc('b');
340 EXPECT_EQ('b', remoteWorker->getc());
341
342 sleep(1);
343
344 // We expect no change from the service traits (service not cached).
345 EXPECT_EQ(4, sNewService);
346 EXPECT_EQ(4, sServiceDied);
347 EXPECT_EQ(4, listenerServiceCreated);
348 EXPECT_EQ(2, listenerServiceDied); // binder died is associated with the actual handle.
349
350 // replace the service traits.
351 {
352 auto previous = mediautils::initService<
353 IServiceSingletonTest, TestServiceTraits2<IServiceSingletonTest>>({});
354 auto previous2 = mediautils::initService<
355 aidl::IServiceSingletonTest, TestServiceTraits2<aidl::IServiceSingletonTest>>({});
356
357 EXPECT_FALSE(previous);
358 EXPECT_FALSE(previous2);
359 }
360
361 // We expect no change with old counters.
362 EXPECT_EQ(4, sNewService);
363 EXPECT_EQ(4, sServiceDied);
364 EXPECT_EQ(0, sNewService2);
365 EXPECT_EQ(0, sServiceDied2);
366
367 {
368 auto service = mediautils::getService<IServiceSingletonTest>();
369 EXPECT_FALSE(service);
370
371 auto service2 = mediautils::getService<aidl::IServiceSingletonTest>();
372 EXPECT_FALSE(service2);
373 }
374
375 EXPECT_EQ(4, sNewService);
376 EXPECT_EQ(4, sServiceDied);
377 EXPECT_EQ(0, sNewService2);
378 EXPECT_EQ(0, sServiceDied2);
379
380 // Spawn the service again.
381 remoteWorker->putc('a');
382 EXPECT_EQ('a', remoteWorker->getc());
383
384 sleep(1);
385
386 EXPECT_EQ(4, sNewService); // old counters do not change.
387 EXPECT_EQ(4, sServiceDied);
388 EXPECT_EQ(2, sNewService2); // new counters change
389 EXPECT_EQ(0, sServiceDied2);
390
391 EXPECT_EQ(6, listenerServiceCreated); // listener associated with service name picks up info.
392
393 // get service pointers that will be made stale later.
394 auto stale_service = mediautils::getService<IServiceSingletonTest>();
395 EXPECT_TRUE(stale_service); // not stale yet.
396
397 auto stale_service2 = mediautils::getService<aidl::IServiceSingletonTest>();
398 EXPECT_TRUE(stale_service2); // not stale yet.
399
400 // Release the service.
401 remoteWorker->putc('b');
402 EXPECT_EQ('b', remoteWorker->getc());
403
404 sleep(1);
405
406 EXPECT_EQ(4, sNewService); // old counters do not change.
407 EXPECT_EQ(4, sServiceDied);
408 EXPECT_EQ(2, sNewService2); // new counters change
409 EXPECT_EQ(2, sServiceDied2);
410
411 // The service handles are now stale, verify that we can't register a death notification.
412 {
413 std::atomic_int32_t postDied = 0;
414 // we cannot register death notification so handles are null.
415 auto handle1 = mediautils::requestDeathNotification(stale_service, [&] { ++postDied; });
416 EXPECT_FALSE(handle1);
417 auto handle2= mediautils::requestDeathNotification(stale_service2, [&] { ++postDied; });
418 EXPECT_FALSE(handle2);
419 EXPECT_EQ(0, postDied); // no callbacks issued.
420 }
421 }
422