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