xref: /aosp_15_r20/frameworks/native/libs/binder/tests/binderCacheUnitTest.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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 #include <gtest/gtest.h>
17 
18 #include <android-base/logging.h>
19 #include <android/os/IServiceManager.h>
20 #include <binder/IBinder.h>
21 #include <binder/IPCThreadState.h>
22 #include <binder/IServiceManager.h>
23 #include <binder/IServiceManagerUnitTestHelper.h>
24 #include "fakeservicemanager/FakeServiceManager.h"
25 
26 #include <sys/prctl.h>
27 #include <thread>
28 
29 using namespace android;
30 
31 #ifdef LIBBINDER_CLIENT_CACHE
32 constexpr bool kUseLibbinderCache = true;
33 #else
34 constexpr bool kUseLibbinderCache = false;
35 #endif
36 
37 #ifdef LIBBINDER_ADDSERVICE_CACHE
38 constexpr bool kUseCacheInAddService = true;
39 #else
40 constexpr bool kUseCacheInAddService = false;
41 #endif
42 
43 #ifdef LIBBINDER_REMOVE_CACHE_STATIC_LIST
44 constexpr bool kRemoveStaticList = true;
45 #else
46 constexpr bool kRemoveStaticList = false;
47 #endif
48 
49 // A service name which is in the static list of cachable services
50 const String16 kCachedServiceName = String16("isub");
51 
52 #define EXPECT_OK(status)                 \
53     do {                                  \
54         binder::Status stat = (status);   \
55         EXPECT_TRUE(stat.isOk()) << stat; \
56     } while (false)
57 
58 const String16 kServerName = String16("binderCacheUnitTest");
59 
60 class FooBar : public BBinder {
61 public:
onTransact(uint32_t,const Parcel &,Parcel *,uint32_t)62     status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t) {
63         // exit the server
64         std::thread([] { exit(EXIT_FAILURE); }).detach();
65         return OK;
66     }
killServer(sp<IBinder> binder)67     void killServer(sp<IBinder> binder) {
68         Parcel data, reply;
69         binder->transact(0, data, &reply, 0);
70     }
71 };
72 
73 class MockAidlServiceManager : public os::IServiceManagerDefault {
74 public:
MockAidlServiceManager()75     MockAidlServiceManager() : innerSm() {}
76 
checkService(const::std::string & name,os::Service * _out)77     binder::Status checkService(const ::std::string& name, os::Service* _out) override {
78         os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
79         serviceWithMetadata.service = innerSm.getService(String16(name.c_str()));
80         serviceWithMetadata.isLazyService = false;
81         *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(serviceWithMetadata);
82         return binder::Status::ok();
83     }
84 
addService(const std::string & name,const sp<IBinder> & service,bool allowIsolated,int32_t dumpPriority)85     binder::Status addService(const std::string& name, const sp<IBinder>& service,
86                               bool allowIsolated, int32_t dumpPriority) override {
87         return binder::Status::fromStatusT(
88                 innerSm.addService(String16(name.c_str()), service, allowIsolated, dumpPriority));
89     }
90 
clearServices()91     void clearServices() { innerSm.clear(); }
92 
93     FakeServiceManager innerSm;
94 };
95 
96 // Returns services with isLazyService flag as true.
97 class MockAidlServiceManager2 : public os::IServiceManagerDefault {
98 public:
MockAidlServiceManager2()99     MockAidlServiceManager2() : innerSm() {}
100 
checkService(const::std::string & name,os::Service * _out)101     binder::Status checkService(const ::std::string& name, os::Service* _out) override {
102         os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
103         serviceWithMetadata.service = innerSm.getService(String16(name.c_str()));
104         serviceWithMetadata.isLazyService = true;
105         *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(serviceWithMetadata);
106         return binder::Status::ok();
107     }
108 
addService(const std::string & name,const sp<IBinder> & service,bool allowIsolated,int32_t dumpPriority)109     binder::Status addService(const std::string& name, const sp<IBinder>& service,
110                               bool allowIsolated, int32_t dumpPriority) override {
111         return binder::Status::fromStatusT(
112                 innerSm.addService(String16(name.c_str()), service, allowIsolated, dumpPriority));
113     }
114 
clearServices()115     void clearServices() { innerSm.clear(); }
116 
117     FakeServiceManager innerSm;
118 };
119 
120 class LibbinderCacheRemoveStaticList : public ::testing::Test {
121 protected:
SetUp()122     void SetUp() override {
123         fakeServiceManager = sp<MockAidlServiceManager2>::make();
124         mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
125         mServiceManager->enableAddServiceCache(true);
126     }
TearDown()127     void TearDown() override {}
128 
129 public:
cacheAddServiceAndConfirmCacheMiss(const sp<IBinder> & binder1)130     void cacheAddServiceAndConfirmCacheMiss(const sp<IBinder>& binder1) {
131         // Add a service. This shouldn't cache it.
132         EXPECT_EQ(OK,
133                   mServiceManager->addService(kCachedServiceName, binder1,
134                                               /*allowIsolated = */ false,
135                                               android::os::IServiceManager::FLAG_IS_LAZY_SERVICE));
136         // Try to populate cache. Cache shouldn't be updated.
137         EXPECT_EQ(binder1, mServiceManager->checkService(kCachedServiceName));
138         fakeServiceManager->clearServices();
139         EXPECT_EQ(nullptr, mServiceManager->checkService(kCachedServiceName));
140     }
141 
142     sp<MockAidlServiceManager2> fakeServiceManager;
143     sp<android::IServiceManager> mServiceManager;
144 };
145 
TEST_F(LibbinderCacheRemoveStaticList,AddLocalServiceAndConfirmCacheMiss)146 TEST_F(LibbinderCacheRemoveStaticList, AddLocalServiceAndConfirmCacheMiss) {
147     if (!kRemoveStaticList) {
148         GTEST_SKIP() << "Skipping as feature is not enabled";
149         return;
150     }
151     sp<IBinder> binder1 = sp<BBinder>::make();
152     cacheAddServiceAndConfirmCacheMiss(binder1);
153 }
154 
TEST_F(LibbinderCacheRemoveStaticList,AddRemoteServiceAndConfirmCacheMiss)155 TEST_F(LibbinderCacheRemoveStaticList, AddRemoteServiceAndConfirmCacheMiss) {
156     if (!kRemoveStaticList) {
157         GTEST_SKIP() << "Skipping as feature is not enabled";
158         return;
159     }
160     sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
161     ASSERT_NE(binder1, nullptr);
162     cacheAddServiceAndConfirmCacheMiss(binder1);
163 }
164 
165 class LibbinderCacheAddServiceTest : public ::testing::Test {
166 protected:
SetUp()167     void SetUp() override {
168         fakeServiceManager = sp<MockAidlServiceManager>::make();
169         mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
170         mServiceManager->enableAddServiceCache(true);
171     }
172 
TearDown()173     void TearDown() override {}
174 
175 public:
cacheAddServiceAndConfirmCacheHit(const sp<IBinder> & binder1)176     void cacheAddServiceAndConfirmCacheHit(const sp<IBinder>& binder1) {
177         // Add a service. This also caches it.
178         EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));
179         // remove services from fakeservicemanager
180         fakeServiceManager->clearServices();
181 
182         sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
183         if (kUseCacheInAddService && kUseLibbinderCache) {
184             // If cache is enabled, we should get the binder.
185             EXPECT_EQ(binder1, result);
186         } else {
187             // If cache is disabled, then we should get the null binder
188             EXPECT_EQ(nullptr, result);
189         }
190     }
191     sp<MockAidlServiceManager> fakeServiceManager;
192     sp<android::IServiceManager> mServiceManager;
193 };
194 
TEST_F(LibbinderCacheAddServiceTest,AddLocalServiceAndConfirmCacheHit)195 TEST_F(LibbinderCacheAddServiceTest, AddLocalServiceAndConfirmCacheHit) {
196     sp<IBinder> binder1 = sp<BBinder>::make();
197     cacheAddServiceAndConfirmCacheHit(binder1);
198 }
199 
TEST_F(LibbinderCacheAddServiceTest,AddRemoteServiceAndConfirmCacheHit)200 TEST_F(LibbinderCacheAddServiceTest, AddRemoteServiceAndConfirmCacheHit) {
201     sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
202     ASSERT_NE(binder1, nullptr);
203     cacheAddServiceAndConfirmCacheHit(binder1);
204 }
205 
206 class LibbinderCacheTest : public ::testing::Test {
207 protected:
SetUp()208     void SetUp() override {
209         fakeServiceManager = sp<MockAidlServiceManager>::make();
210         mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
211         mServiceManager->enableAddServiceCache(false);
212     }
213 
TearDown()214     void TearDown() override {}
215 
216 public:
cacheAndConfirmCacheHit(const sp<IBinder> & binder1,const sp<IBinder> & binder2)217     void cacheAndConfirmCacheHit(const sp<IBinder>& binder1, const sp<IBinder>& binder2) {
218         // Add a service
219         EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));
220         // Get the service. This caches it.
221         sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
222         ASSERT_EQ(binder1, result);
223 
224         // Add the different binder and replace the service.
225         // The cache should still hold the original binder.
226         EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));
227 
228         result = mServiceManager->checkService(kCachedServiceName);
229         if (kUseLibbinderCache) {
230             // If cache is enabled, we should get the binder to Service Manager.
231             EXPECT_EQ(binder1, result);
232         } else {
233             // If cache is disabled, then we should get the newer binder
234             EXPECT_EQ(binder2, result);
235         }
236     }
237 
238     sp<MockAidlServiceManager> fakeServiceManager;
239     sp<android::IServiceManager> mServiceManager;
240 };
241 
TEST_F(LibbinderCacheTest,AddLocalServiceAndConfirmCacheHit)242 TEST_F(LibbinderCacheTest, AddLocalServiceAndConfirmCacheHit) {
243     sp<IBinder> binder1 = sp<BBinder>::make();
244     sp<IBinder> binder2 = sp<BBinder>::make();
245 
246     cacheAndConfirmCacheHit(binder1, binder2);
247 }
248 
TEST_F(LibbinderCacheTest,AddRemoteServiceAndConfirmCacheHit)249 TEST_F(LibbinderCacheTest, AddRemoteServiceAndConfirmCacheHit) {
250     sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
251     ASSERT_NE(binder1, nullptr);
252     sp<IBinder> binder2 = IInterface::asBinder(mServiceManager);
253 
254     cacheAndConfirmCacheHit(binder1, binder2);
255 }
256 
TEST_F(LibbinderCacheTest,RemoveFromCacheOnServerDeath)257 TEST_F(LibbinderCacheTest, RemoveFromCacheOnServerDeath) {
258     sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
259     FooBar foo = FooBar();
260 
261     EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));
262 
263     // Check Service, this caches the binder
264     sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
265     ASSERT_EQ(binder1, result);
266 
267     // Kill the server, this should remove from cache.
268     pid_t pid;
269     ASSERT_EQ(OK, binder1->getDebugPid(&pid));
270     foo.killServer(binder1);
271     system(("kill -9 " + std::to_string(pid)).c_str());
272 
273     sp<IBinder> binder2 = sp<BBinder>::make();
274 
275     // Add new service with the same name.
276     // This will replace the service in FakeServiceManager.
277     EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));
278 
279     // Confirm that new service is returned instead of old.
280     int retry_count = 20;
281     sp<IBinder> result2;
282     do {
283         std::this_thread::sleep_for(std::chrono::milliseconds(50));
284         if (retry_count-- == 0) {
285             break;
286         }
287         result2 = mServiceManager->checkService(kCachedServiceName);
288     } while (result2 != binder2);
289 
290     ASSERT_EQ(binder2, result2);
291 }
292 
TEST_F(LibbinderCacheTest,NullBinderNotCached)293 TEST_F(LibbinderCacheTest, NullBinderNotCached) {
294     sp<IBinder> binder1 = nullptr;
295     sp<IBinder> binder2 = sp<BBinder>::make();
296 
297     // Check for a cacheble service which isn't registered.
298     // FakeServiceManager should return nullptr.
299     // This shouldn't be cached.
300     sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
301     ASSERT_EQ(binder1, result);
302 
303     // Add the same service
304     EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));
305 
306     // This should return the newly added service.
307     result = mServiceManager->checkService(kCachedServiceName);
308     EXPECT_EQ(binder2, result);
309 }
310 
311 // TODO(b/333854840): Remove this test removing the static list
TEST_F(LibbinderCacheTest,DoNotCacheServiceNotInList)312 TEST_F(LibbinderCacheTest, DoNotCacheServiceNotInList) {
313     if (kRemoveStaticList) {
314         GTEST_SKIP() << "Skipping test as static list is disabled";
315         return;
316     }
317 
318     sp<IBinder> binder1 = sp<BBinder>::make();
319     sp<IBinder> binder2 = sp<BBinder>::make();
320     String16 serviceName = String16("NewLibbinderCacheTest");
321     // Add a service
322     EXPECT_EQ(OK, mServiceManager->addService(serviceName, binder1));
323     // Get the service. This shouldn't caches it.
324     sp<IBinder> result = mServiceManager->checkService(serviceName);
325     ASSERT_EQ(binder1, result);
326 
327     // Add the different binder and replace the service.
328     EXPECT_EQ(OK, mServiceManager->addService(serviceName, binder2));
329 
330     // Confirm that we get the new service
331     result = mServiceManager->checkService(serviceName);
332     EXPECT_EQ(binder2, result);
333 }
334 
main(int argc,char ** argv)335 int main(int argc, char** argv) {
336     ::testing::InitGoogleTest(&argc, argv);
337 
338     if (fork() == 0) {
339         prctl(PR_SET_PDEATHSIG, SIGHUP);
340 
341         // Start a FooBar service and add it to the servicemanager.
342         sp<IBinder> server = new FooBar();
343         defaultServiceManager()->addService(kServerName, server);
344 
345         IPCThreadState::self()->joinThreadPool(true);
346         exit(1); // should not reach
347     }
348 
349     status_t err = ProcessState::self()->setThreadPoolMaxThreadCount(3);
350     ProcessState::self()->startThreadPool();
351     CHECK_EQ(ProcessState::self()->isThreadPoolStarted(), true);
352     CHECK_GT(ProcessState::self()->getThreadPoolMaxTotalThreadCount(), 0);
353 
354     auto binder = defaultServiceManager()->waitForService(kServerName);
355     CHECK_NE(nullptr, binder.get());
356     return RUN_ALL_TESTS();
357 }
358