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