blob: 482d197688e8d9610e42e29854dd7c0b8b053819 [file] [log] [blame]
Parth Saneb6ed0eb2024-06-25 14:38:42 +00001/*
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
29using namespace android;
30
31#ifdef LIBBINDER_CLIENT_CACHE
32constexpr bool kUseLibbinderCache = true;
33#else
34constexpr bool kUseLibbinderCache = false;
35#endif
36
37// A service name which is in the static list of cachable services
38const String16 kCachedServiceName = String16("isub");
39
40#define EXPECT_OK(status) \
41 do { \
42 binder::Status stat = (status); \
43 EXPECT_TRUE(stat.isOk()) << stat; \
44 } while (false)
45
46const String16 kServerName = String16("binderCacheUnitTest");
47
48class FooBar : public BBinder {
49public:
50 status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t) {
51 // exit the server
52 std::thread([] { exit(EXIT_FAILURE); }).detach();
53 return OK;
54 }
55 void killServer(sp<IBinder> binder) {
56 Parcel data, reply;
57 binder->transact(0, data, &reply, 0);
58 }
59};
60
61class MockAidlServiceManager : public os::IServiceManagerDefault {
62public:
63 MockAidlServiceManager() : innerSm() {}
64
65 binder::Status checkService(const ::std::string& name, os::Service* _out) override {
66 sp<IBinder> binder = innerSm.getService(String16(name.c_str()));
67 *_out = os::Service::make<os::Service::Tag::binder>(binder);
68 return binder::Status::ok();
69 }
70
71 binder::Status addService(const std::string& name, const sp<IBinder>& service,
72 bool allowIsolated, int32_t dumpPriority) override {
73 return binder::Status::fromStatusT(
74 innerSm.addService(String16(name.c_str()), service, allowIsolated, dumpPriority));
75 }
76
77 FakeServiceManager innerSm;
78};
79
80class LibbinderCacheTest : public ::testing::Test {
81protected:
82 void SetUp() override {
83 sp<MockAidlServiceManager> sm = sp<MockAidlServiceManager>::make();
84 mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(sm);
85 }
86
87 void TearDown() override {}
88
89public:
90 void cacheAndConfirmCacheHit(const sp<IBinder>& binder1, const sp<IBinder>& binder2) {
91 // Add a service
92 EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));
93 // Get the service. This caches it.
94 sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
95 ASSERT_EQ(binder1, result);
96
97 // Add the different binder and replace the service.
98 // The cache should still hold the original binder.
99 EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));
100
101 result = mServiceManager->checkService(kCachedServiceName);
102 if (kUseLibbinderCache) {
103 // If cache is enabled, we should get the binder to Service Manager.
104 EXPECT_EQ(binder1, result);
105 } else {
106 // If cache is disabled, then we should get the newer binder
107 EXPECT_EQ(binder2, result);
108 }
109 }
110
111 sp<android::IServiceManager> mServiceManager;
112};
113
114TEST_F(LibbinderCacheTest, AddLocalServiceAndConfirmCacheHit) {
115 sp<IBinder> binder1 = sp<BBinder>::make();
116 sp<IBinder> binder2 = sp<BBinder>::make();
117
118 cacheAndConfirmCacheHit(binder1, binder2);
119}
120
121TEST_F(LibbinderCacheTest, AddRemoteServiceAndConfirmCacheHit) {
122 sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
123 ASSERT_NE(binder1, nullptr);
124 sp<IBinder> binder2 = IInterface::asBinder(mServiceManager);
125
126 cacheAndConfirmCacheHit(binder1, binder2);
127}
128
129TEST_F(LibbinderCacheTest, RemoveFromCacheOnServerDeath) {
130 sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
131 FooBar foo = FooBar();
132
133 EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));
134
135 // Check Service, this caches the binder
136 sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
137 ASSERT_EQ(binder1, result);
138
139 // Kill the server, this should remove from cache.
Parth Saneb6ed0eb2024-06-25 14:38:42 +0000140 pid_t pid;
141 ASSERT_EQ(OK, binder1->getDebugPid(&pid));
Parth Sane9dc99842024-09-17 18:07:22 +0000142 foo.killServer(binder1);
Parth Saneb6ed0eb2024-06-25 14:38:42 +0000143 system(("kill -9 " + std::to_string(pid)).c_str());
144
145 sp<IBinder> binder2 = sp<BBinder>::make();
146
147 // Add new service with the same name.
148 // This will replace the service in FakeServiceManager.
149 EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));
150
151 // Confirm that new service is returned instead of old.
152 sp<IBinder> result2 = mServiceManager->checkService(kCachedServiceName);
153 ASSERT_EQ(binder2, result2);
154}
155
156TEST_F(LibbinderCacheTest, NullBinderNotCached) {
157 sp<IBinder> binder1 = nullptr;
158 sp<IBinder> binder2 = sp<BBinder>::make();
159
160 // Check for a cacheble service which isn't registered.
161 // FakeServiceManager should return nullptr.
162 // This shouldn't be cached.
163 sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
164 ASSERT_EQ(binder1, result);
165
166 // Add the same service
167 EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));
168
169 // This should return the newly added service.
170 result = mServiceManager->checkService(kCachedServiceName);
171 EXPECT_EQ(binder2, result);
172}
173
174TEST_F(LibbinderCacheTest, DoNotCacheServiceNotInList) {
175 sp<IBinder> binder1 = sp<BBinder>::make();
176 sp<IBinder> binder2 = sp<BBinder>::make();
177 String16 serviceName = String16("NewLibbinderCacheTest");
178 // Add a service
179 EXPECT_EQ(OK, mServiceManager->addService(serviceName, binder1));
180 // Get the service. This shouldn't caches it.
181 sp<IBinder> result = mServiceManager->checkService(serviceName);
182 ASSERT_EQ(binder1, result);
183
184 // Add the different binder and replace the service.
185 EXPECT_EQ(OK, mServiceManager->addService(serviceName, binder2));
186
187 // Confirm that we get the new service
188 result = mServiceManager->checkService(serviceName);
189 EXPECT_EQ(binder2, result);
190}
191
192int main(int argc, char** argv) {
193 ::testing::InitGoogleTest(&argc, argv);
194
195 if (fork() == 0) {
196 prctl(PR_SET_PDEATHSIG, SIGHUP);
197
198 // Start a FooBar service and add it to the servicemanager.
199 sp<IBinder> server = new FooBar();
200 defaultServiceManager()->addService(kServerName, server);
201
202 IPCThreadState::self()->joinThreadPool(true);
203 exit(1); // should not reach
204 }
205
206 status_t err = ProcessState::self()->setThreadPoolMaxThreadCount(3);
207 ProcessState::self()->startThreadPool();
208 CHECK_EQ(ProcessState::self()->isThreadPoolStarted(), true);
209 CHECK_GT(ProcessState::self()->getThreadPoolMaxTotalThreadCount(), 0);
210
211 auto binder = defaultServiceManager()->waitForService(kServerName);
212 CHECK_NE(nullptr, binder.get());
213 return RUN_ALL_TESTS();
214}