1 /*
2 * Copyright (C) 2018 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 #include <IBinderNdkUnitTest.h>
18 #include <aidl/BnBinderNdkUnitTest.h>
19 #include <aidl/BnEmpty.h>
20 #include <android-base/logging.h>
21 #include <android/binder_ibinder_jni.h>
22 #include <android/binder_ibinder_platform.h>
23 #include <android/binder_manager.h>
24 #include <android/binder_process.h>
25 #include <gtest/gtest.h>
26 #include <iface/iface.h>
27 #include <utils/Looper.h>
28
29 // warning: this is assuming that libbinder_ndk is using the same copy
30 // of libbinder that we are.
31 #include <binder/IPCThreadState.h>
32 #include <binder/IResultReceiver.h>
33 #include <binder/IServiceManager.h>
34 #include <binder/IShellCallback.h>
35
36 #include <sys/prctl.h>
37 #include <chrono>
38 #include <condition_variable>
39 #include <iostream>
40 #include <mutex>
41
42 using namespace android;
43
44 constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
45 constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
46
47 class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
repeatInt(int32_t in,int32_t * out)48 ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
49 *out = in;
50 return ndk::ScopedAStatus::ok();
51 }
takeInterface(const std::shared_ptr<aidl::IEmpty> & empty)52 ndk::ScopedAStatus takeInterface(const std::shared_ptr<aidl::IEmpty>& empty) {
53 (void)empty;
54 return ndk::ScopedAStatus::ok();
55 }
forceFlushCommands()56 ndk::ScopedAStatus forceFlushCommands() {
57 // warning: this is assuming that libbinder_ndk is using the same copy
58 // of libbinder that we are.
59 android::IPCThreadState::self()->flushCommands();
60 return ndk::ScopedAStatus::ok();
61 }
getsRequestedSid(bool * out)62 ndk::ScopedAStatus getsRequestedSid(bool* out) {
63 const char* sid = AIBinder_getCallingSid();
64 std::cout << "Got security context: " << (sid ?: "null") << std::endl;
65 *out = sid != nullptr;
66 return ndk::ScopedAStatus::ok();
67 }
handleShellCommand(int,int out,int,const char ** args,uint32_t numArgs)68 binder_status_t handleShellCommand(int /*in*/, int out, int /*err*/, const char** args,
69 uint32_t numArgs) override {
70 for (uint32_t i = 0; i < numArgs; i++) {
71 dprintf(out, "%s", args[i]);
72 }
73 fsync(out);
74 return STATUS_OK;
75 }
76 };
77
generatedService()78 int generatedService() {
79 ABinderProcess_setThreadPoolMaxThreadCount(0);
80
81 auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
82 auto binder = service->asBinder();
83
84 AIBinder_setRequestingSid(binder.get(), true);
85
86 binder_status_t status = AServiceManager_addService(binder.get(), kBinderNdkUnitTestService);
87
88 if (status != STATUS_OK) {
89 LOG(FATAL) << "Could not register: " << status << " " << kBinderNdkUnitTestService;
90 }
91
92 ABinderProcess_joinThreadPool();
93
94 return 1; // should not return
95 }
96
97 // manually-written parceling class considered bad practice
98 class MyFoo : public IFoo {
doubleNumber(int32_t in,int32_t * out)99 binder_status_t doubleNumber(int32_t in, int32_t* out) override {
100 *out = 2 * in;
101 LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
102 return STATUS_OK;
103 }
104
die()105 binder_status_t die() override {
106 LOG(FATAL) << "IFoo::die called!";
107 return STATUS_UNKNOWN_ERROR;
108 }
109 };
110
manualService(const char * instance)111 void manualService(const char* instance) {
112 // Strong reference to MyFoo kept by service manager.
113 binder_status_t status = (new MyFoo)->addService(instance);
114
115 if (status != STATUS_OK) {
116 LOG(FATAL) << "Could not register: " << status << " " << instance;
117 }
118 }
manualPollingService(const char * instance)119 int manualPollingService(const char* instance) {
120 int fd;
121 CHECK(STATUS_OK == ABinderProcess_setupPolling(&fd));
122 manualService(instance);
123
124 class Handler : public LooperCallback {
125 int handleEvent(int /*fd*/, int /*events*/, void* /*data*/) override {
126 ABinderProcess_handlePolledCommands();
127 return 1; // Continue receiving callbacks.
128 }
129 };
130
131 sp<Looper> looper = Looper::prepare(0 /* opts */);
132 looper->addFd(fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, new Handler(), nullptr /*data*/);
133 // normally, would add additional fds
134 while (true) {
135 looper->pollAll(-1 /* timeoutMillis */);
136 }
137 return 1; // should not reach
138 }
manualThreadPoolService(const char * instance)139 int manualThreadPoolService(const char* instance) {
140 ABinderProcess_setThreadPoolMaxThreadCount(0);
141 manualService(instance);
142 ABinderProcess_joinThreadPool();
143 return 1;
144 }
145
146 // This is too slow
147 // TEST(NdkBinder, GetServiceThatDoesntExist) {
148 // sp<IFoo> foo = IFoo::getService("asdfghkl;");
149 // EXPECT_EQ(nullptr, foo.get());
150 // }
151
TEST(NdkBinder,CheckServiceThatDoesntExist)152 TEST(NdkBinder, CheckServiceThatDoesntExist) {
153 AIBinder* binder = AServiceManager_checkService("asdfghkl;");
154 ASSERT_EQ(nullptr, binder);
155 }
156
TEST(NdkBinder,CheckServiceThatDoesExist)157 TEST(NdkBinder, CheckServiceThatDoesExist) {
158 AIBinder* binder = AServiceManager_checkService(kExistingNonNdkService);
159 EXPECT_NE(nullptr, binder);
160 EXPECT_EQ(STATUS_OK, AIBinder_ping(binder));
161
162 AIBinder_decStrong(binder);
163 }
164
TEST(NdkBinder,DoubleNumber)165 TEST(NdkBinder, DoubleNumber) {
166 sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
167 ASSERT_NE(foo, nullptr);
168
169 int32_t out;
170 EXPECT_EQ(STATUS_OK, foo->doubleNumber(1, &out));
171 EXPECT_EQ(2, out);
172 }
173
LambdaOnDeath(void * cookie)174 void LambdaOnDeath(void* cookie) {
175 auto onDeath = static_cast<std::function<void(void)>*>(cookie);
176 (*onDeath)();
177 };
TEST(NdkBinder,DeathRecipient)178 TEST(NdkBinder, DeathRecipient) {
179 using namespace std::chrono_literals;
180
181 AIBinder* binder;
182 sp<IFoo> foo = IFoo::getService(IFoo::kInstanceNameToDieFor, &binder);
183 ASSERT_NE(nullptr, foo.get());
184 ASSERT_NE(nullptr, binder);
185
186 std::mutex deathMutex;
187 std::condition_variable deathCv;
188 bool deathRecieved = false;
189
190 std::function<void(void)> onDeath = [&] {
191 std::cerr << "Binder died (as requested)." << std::endl;
192 deathRecieved = true;
193 deathCv.notify_one();
194 };
195
196 AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(LambdaOnDeath);
197
198 EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(&onDeath)));
199
200 // the binder driver should return this if the service dies during the transaction
201 EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die());
202
203 foo = nullptr;
204
205 std::unique_lock<std::mutex> lock(deathMutex);
206 EXPECT_TRUE(deathCv.wait_for(lock, 1s, [&] { return deathRecieved; }));
207 EXPECT_TRUE(deathRecieved);
208
209 AIBinder_DeathRecipient_delete(recipient);
210 AIBinder_decStrong(binder);
211 binder = nullptr;
212 }
213
TEST(NdkBinder,RetrieveNonNdkService)214 TEST(NdkBinder, RetrieveNonNdkService) {
215 AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
216 ASSERT_NE(nullptr, binder);
217 EXPECT_TRUE(AIBinder_isRemote(binder));
218 EXPECT_TRUE(AIBinder_isAlive(binder));
219 EXPECT_EQ(STATUS_OK, AIBinder_ping(binder));
220
221 AIBinder_decStrong(binder);
222 }
223
OnBinderDeath(void * cookie)224 void OnBinderDeath(void* cookie) {
225 LOG(ERROR) << "BINDER DIED. COOKIE: " << cookie;
226 }
227
TEST(NdkBinder,LinkToDeath)228 TEST(NdkBinder, LinkToDeath) {
229 AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
230 ASSERT_NE(nullptr, binder);
231
232 AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath);
233 ASSERT_NE(nullptr, recipient);
234
235 EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr));
236 EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr));
237 EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
238 EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
239 EXPECT_EQ(STATUS_NAME_NOT_FOUND, AIBinder_unlinkToDeath(binder, recipient, nullptr));
240
241 AIBinder_DeathRecipient_delete(recipient);
242 AIBinder_decStrong(binder);
243 }
244
245 class MyTestFoo : public IFoo {
doubleNumber(int32_t in,int32_t * out)246 binder_status_t doubleNumber(int32_t in, int32_t* out) override {
247 *out = 2 * in;
248 LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
249 return STATUS_OK;
250 }
die()251 binder_status_t die() override {
252 ADD_FAILURE() << "die called on local instance";
253 return STATUS_OK;
254 }
255 };
256
TEST(NdkBinder,GetServiceInProcess)257 TEST(NdkBinder, GetServiceInProcess) {
258 static const char* kInstanceName = "test-get-service-in-process";
259
260 sp<IFoo> foo = new MyTestFoo;
261 EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName));
262
263 sp<IFoo> getFoo = IFoo::getService(kInstanceName);
264 EXPECT_EQ(foo.get(), getFoo.get());
265
266 int32_t out;
267 EXPECT_EQ(STATUS_OK, getFoo->doubleNumber(1, &out));
268 EXPECT_EQ(2, out);
269 }
270
TEST(NdkBinder,EqualityOfRemoteBinderPointer)271 TEST(NdkBinder, EqualityOfRemoteBinderPointer) {
272 AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService);
273 ASSERT_NE(nullptr, binderA);
274
275 AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService);
276 ASSERT_NE(nullptr, binderB);
277
278 EXPECT_EQ(binderA, binderB);
279
280 AIBinder_decStrong(binderA);
281 AIBinder_decStrong(binderB);
282 }
283
TEST(NdkBinder,ToFromJavaNullptr)284 TEST(NdkBinder, ToFromJavaNullptr) {
285 EXPECT_EQ(nullptr, AIBinder_toJavaBinder(nullptr, nullptr));
286 EXPECT_EQ(nullptr, AIBinder_fromJavaBinder(nullptr, nullptr));
287 }
288
TEST(NdkBinder,ABpBinderRefCount)289 TEST(NdkBinder, ABpBinderRefCount) {
290 AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
291 AIBinder_Weak* wBinder = AIBinder_Weak_new(binder);
292
293 ASSERT_NE(nullptr, binder);
294 EXPECT_EQ(1, AIBinder_debugGetRefCount(binder));
295
296 AIBinder_decStrong(binder);
297
298 // assert because would need to decStrong if non-null and we shouldn't need to add a no-op here
299 ASSERT_NE(nullptr, AIBinder_Weak_promote(wBinder));
300
301 AIBinder_Weak_delete(wBinder);
302 }
303
TEST(NdkBinder,AddServiceMultipleTimes)304 TEST(NdkBinder, AddServiceMultipleTimes) {
305 static const char* kInstanceName1 = "test-multi-1";
306 static const char* kInstanceName2 = "test-multi-2";
307 sp<IFoo> foo = new MyTestFoo;
308 EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName1));
309 EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName2));
310 EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
311 }
312
TEST(NdkBinder,RequestedSidWorks)313 TEST(NdkBinder, RequestedSidWorks) {
314 ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
315 std::shared_ptr<aidl::IBinderNdkUnitTest> service =
316 aidl::IBinderNdkUnitTest::fromBinder(binder);
317
318 bool gotSid = false;
319 EXPECT_TRUE(service->getsRequestedSid(&gotSid).isOk());
320 EXPECT_TRUE(gotSid);
321 }
322
TEST(NdkBinder,SentAidlBinderCanBeDestroyed)323 TEST(NdkBinder, SentAidlBinderCanBeDestroyed) {
324 static volatile bool destroyed = false;
325 static std::mutex dMutex;
326 static std::condition_variable cv;
327
328 class MyEmpty : public aidl::BnEmpty {
329 virtual ~MyEmpty() {
330 destroyed = true;
331 cv.notify_one();
332 }
333 };
334
335 std::shared_ptr<MyEmpty> empty = ndk::SharedRefBase::make<MyEmpty>();
336
337 ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
338 std::shared_ptr<aidl::IBinderNdkUnitTest> service =
339 aidl::IBinderNdkUnitTest::fromBinder(binder);
340
341 EXPECT_FALSE(destroyed);
342
343 service->takeInterface(empty);
344 service->forceFlushCommands();
345 empty = nullptr;
346
347 // give other binder thread time to process commands
348 {
349 using namespace std::chrono_literals;
350 std::unique_lock<std::mutex> lk(dMutex);
351 cv.wait_for(lk, 1s, [] { return destroyed; });
352 }
353
354 EXPECT_TRUE(destroyed);
355 }
356
TEST(NdkBinder,ConvertToPlatformBinder)357 TEST(NdkBinder, ConvertToPlatformBinder) {
358 for (const ndk::SpAIBinder& binder :
359 {// remote
360 ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
361 // local
362 ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
363 // convert to platform binder
364 EXPECT_NE(binder.get(), nullptr);
365 sp<IBinder> platformBinder = AIBinder_toPlatformBinder(binder.get());
366 EXPECT_NE(platformBinder.get(), nullptr);
367 auto proxy = interface_cast<IBinderNdkUnitTest>(platformBinder);
368 EXPECT_NE(proxy, nullptr);
369
370 // use platform binder
371 int out;
372 EXPECT_TRUE(proxy->repeatInt(4, &out).isOk());
373 EXPECT_EQ(out, 4);
374
375 // convert back
376 ndk::SpAIBinder backBinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(platformBinder));
377 EXPECT_EQ(backBinder.get(), binder.get());
378 }
379 }
380
381 class MyResultReceiver : public BnResultReceiver {
382 public:
383 Mutex mMutex;
384 Condition mCondition;
385 bool mHaveResult = false;
386 int32_t mResult = 0;
387
send(int32_t resultCode)388 virtual void send(int32_t resultCode) {
389 AutoMutex _l(mMutex);
390 mResult = resultCode;
391 mHaveResult = true;
392 mCondition.signal();
393 }
394
waitForResult()395 int32_t waitForResult() {
396 AutoMutex _l(mMutex);
397 while (!mHaveResult) {
398 mCondition.wait(mMutex);
399 }
400 return mResult;
401 }
402 };
403
404 class MyShellCallback : public BnShellCallback {
405 public:
openFile(const String16 &,const String16 &,const String16 &)406 virtual int openFile(const String16& /*path*/, const String16& /*seLinuxContext*/,
407 const String16& /*mode*/) {
408 // Empty implementation.
409 return 0;
410 }
411 };
412
ReadFdToString(int fd,std::string * content)413 bool ReadFdToString(int fd, std::string* content) {
414 char buf[64];
415 ssize_t n;
416 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
417 content->append(buf, n);
418 }
419 return (n == 0) ? true : false;
420 }
421
shellCmdToString(sp<IBinder> unitTestService,const std::vector<const char * > & args)422 std::string shellCmdToString(sp<IBinder> unitTestService, const std::vector<const char*>& args) {
423 int inFd[2] = {-1, -1};
424 int outFd[2] = {-1, -1};
425 int errFd[2] = {-1, -1};
426
427 EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, inFd));
428 EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, outFd));
429 EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, errFd));
430
431 sp<MyShellCallback> cb = new MyShellCallback();
432 sp<MyResultReceiver> resultReceiver = new MyResultReceiver();
433
434 Vector<String16> argsVec;
435 for (int i = 0; i < args.size(); i++) {
436 argsVec.add(String16(args[i]));
437 }
438 status_t error = IBinder::shellCommand(unitTestService, inFd[0], outFd[0], errFd[0], argsVec,
439 cb, resultReceiver);
440 EXPECT_EQ(error, android::OK);
441
442 status_t res = resultReceiver->waitForResult();
443 EXPECT_EQ(res, android::OK);
444
445 close(inFd[0]);
446 close(inFd[1]);
447 close(outFd[0]);
448 close(errFd[0]);
449 close(errFd[1]);
450
451 std::string ret;
452 EXPECT_TRUE(ReadFdToString(outFd[1], &ret));
453 close(outFd[1]);
454 return ret;
455 }
456
TEST(NdkBinder,UseHandleShellCommand)457 TEST(NdkBinder, UseHandleShellCommand) {
458 static const sp<android::IServiceManager> sm(android::defaultServiceManager());
459 sp<IBinder> testService = sm->getService(String16(kBinderNdkUnitTestService));
460
461 EXPECT_EQ("", shellCmdToString(testService, {}));
462 EXPECT_EQ("", shellCmdToString(testService, {"", ""}));
463 EXPECT_EQ("Hello world!", shellCmdToString(testService, {"Hello ", "world!"}));
464 EXPECT_EQ("CMD", shellCmdToString(testService, {"C", "M", "D"}));
465 }
466
main(int argc,char * argv[])467 int main(int argc, char* argv[]) {
468 ::testing::InitGoogleTest(&argc, argv);
469
470 if (fork() == 0) {
471 prctl(PR_SET_PDEATHSIG, SIGHUP);
472 return manualThreadPoolService(IFoo::kInstanceNameToDieFor);
473 }
474 if (fork() == 0) {
475 prctl(PR_SET_PDEATHSIG, SIGHUP);
476 return manualPollingService(IFoo::kSomeInstanceName);
477 }
478 if (fork() == 0) {
479 prctl(PR_SET_PDEATHSIG, SIGHUP);
480 return generatedService();
481 }
482
483 ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications/callbacks
484 ABinderProcess_startThreadPool();
485
486 return RUN_ALL_TESTS();
487 }
488
489 #include <android/binder_auto_utils.h>
490 #include <android/binder_interface_utils.h>
491 #include <android/binder_parcel_utils.h>
492