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_libbinder.h>
24 #include <android/binder_manager.h>
25 #include <android/binder_process.h>
26 #include <gtest/gtest.h>
27 #include <iface/iface.h>
28 #include <utils/Looper.h>
29
30 // warning: this is assuming that libbinder_ndk is using the same copy
31 // of libbinder that we are.
32 #include <binder/IPCThreadState.h>
33 #include <binder/IResultReceiver.h>
34 #include <binder/IServiceManager.h>
35 #include <binder/IShellCallback.h>
36
37 #include <sys/prctl.h>
38 #include <chrono>
39 #include <condition_variable>
40 #include <iostream>
41 #include <mutex>
42 #include "android/binder_ibinder.h"
43
44 using namespace android;
45
46 constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
47 constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
48 constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest";
49 constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService";
50 constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";
51
52 constexpr unsigned int kShutdownWaitTime = 10;
53 constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
54
55 class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
repeatInt(int32_t in,int32_t * out)56 ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
57 *out = in;
58 return ndk::ScopedAStatus::ok();
59 }
takeInterface(const std::shared_ptr<aidl::IEmpty> & empty)60 ndk::ScopedAStatus takeInterface(const std::shared_ptr<aidl::IEmpty>& empty) {
61 (void)empty;
62 return ndk::ScopedAStatus::ok();
63 }
forceFlushCommands()64 ndk::ScopedAStatus forceFlushCommands() {
65 // warning: this is assuming that libbinder_ndk is using the same copy
66 // of libbinder that we are.
67 android::IPCThreadState::self()->flushCommands();
68 return ndk::ScopedAStatus::ok();
69 }
getsRequestedSid(bool * out)70 ndk::ScopedAStatus getsRequestedSid(bool* out) {
71 const char* sid = AIBinder_getCallingSid();
72 std::cout << "Got security context: " << (sid ?: "null") << std::endl;
73 *out = sid != nullptr;
74 return ndk::ScopedAStatus::ok();
75 }
handleShellCommand(int,int out,int,const char ** args,uint32_t numArgs)76 binder_status_t handleShellCommand(int /*in*/, int out, int /*err*/, const char** args,
77 uint32_t numArgs) override {
78 for (uint32_t i = 0; i < numArgs; i++) {
79 dprintf(out, "%s", args[i]);
80 }
81 fsync(out);
82 return STATUS_OK;
83 }
forcePersist(bool persist)84 ndk::ScopedAStatus forcePersist(bool persist) {
85 AServiceManager_forceLazyServicesPersist(persist);
86 return ndk::ScopedAStatus::ok();
87 }
setCustomActiveServicesCallback()88 ndk::ScopedAStatus setCustomActiveServicesCallback() {
89 AServiceManager_setActiveServicesCallback(activeServicesCallback, this);
90 return ndk::ScopedAStatus::ok();
91 }
activeServicesCallback(bool hasClients,void * context)92 static bool activeServicesCallback(bool hasClients, void* context) {
93 if (hasClients) {
94 return false;
95 }
96
97 // Unregister all services
98 if (!AServiceManager_tryUnregister()) {
99 // Prevent shutdown (test will fail)
100 return false;
101 }
102
103 // Re-register all services
104 AServiceManager_reRegister();
105
106 // Unregister again before shutdown
107 if (!AServiceManager_tryUnregister()) {
108 // Prevent shutdown (test will fail)
109 return false;
110 }
111
112 // Check if the context was passed correctly
113 MyBinderNdkUnitTest* service = static_cast<MyBinderNdkUnitTest*>(context);
114 if (service->contextTestValue != kContextTestValue) {
115 // Prevent shutdown (test will fail)
116 return false;
117 }
118
119 exit(EXIT_SUCCESS);
120 // Unreachable
121 }
122
123 uint64_t contextTestValue = kContextTestValue;
124 };
125
generatedService()126 int generatedService() {
127 ABinderProcess_setThreadPoolMaxThreadCount(0);
128
129 auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
130 auto binder = service->asBinder();
131
132 AIBinder_setRequestingSid(binder.get(), true);
133
134 binder_exception_t exception =
135 AServiceManager_addService(binder.get(), kBinderNdkUnitTestService);
136
137 if (exception != EX_NONE) {
138 LOG(FATAL) << "Could not register: " << exception << " " << kBinderNdkUnitTestService;
139 }
140
141 ABinderProcess_joinThreadPool();
142
143 return 1; // should not return
144 }
145
146 // manually-written parceling class considered bad practice
147 class MyFoo : public IFoo {
doubleNumber(int32_t in,int32_t * out)148 binder_status_t doubleNumber(int32_t in, int32_t* out) override {
149 *out = 2 * in;
150 LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
151 return STATUS_OK;
152 }
153
die()154 binder_status_t die() override {
155 LOG(FATAL) << "IFoo::die called!";
156 return STATUS_UNKNOWN_ERROR;
157 }
158 };
159
manualService(const char * instance)160 void manualService(const char* instance) {
161 // Strong reference to MyFoo kept by service manager.
162 binder_exception_t exception = (new MyFoo)->addService(instance);
163
164 if (exception != EX_NONE) {
165 LOG(FATAL) << "Could not register: " << exception << " " << instance;
166 }
167 }
manualPollingService(const char * instance)168 int manualPollingService(const char* instance) {
169 int fd;
170 CHECK(STATUS_OK == ABinderProcess_setupPolling(&fd));
171 manualService(instance);
172
173 class Handler : public LooperCallback {
174 int handleEvent(int /*fd*/, int /*events*/, void* /*data*/) override {
175 ABinderProcess_handlePolledCommands();
176 return 1; // Continue receiving callbacks.
177 }
178 };
179
180 sp<Looper> looper = Looper::prepare(0 /* opts */);
181 looper->addFd(fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, new Handler(), nullptr /*data*/);
182 // normally, would add additional fds
183 while (true) {
184 looper->pollAll(-1 /* timeoutMillis */);
185 }
186 return 1; // should not reach
187 }
manualThreadPoolService(const char * instance)188 int manualThreadPoolService(const char* instance) {
189 ABinderProcess_setThreadPoolMaxThreadCount(0);
190 manualService(instance);
191 ABinderProcess_joinThreadPool();
192 return 1;
193 }
194
lazyService(const char * instance)195 int lazyService(const char* instance) {
196 ABinderProcess_setThreadPoolMaxThreadCount(0);
197 // Wait to register this service to make sure the main test process will
198 // actually wait for the service to be available. Tested with sleep(60),
199 // and reduced for sake of time.
200 sleep(1);
201 // Strong reference to MyBinderNdkUnitTest kept by service manager.
202 // This is just for testing, it has no corresponding init behavior.
203 auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
204 auto binder = service->asBinder();
205
206 binder_status_t status = AServiceManager_registerLazyService(binder.get(), instance);
207 if (status != STATUS_OK) {
208 LOG(FATAL) << "Could not register: " << status << " " << instance;
209 }
210
211 ABinderProcess_joinThreadPool();
212
213 return 1; // should not return
214 }
215
isServiceRunning(const char * serviceName)216 bool isServiceRunning(const char* serviceName) {
217 AIBinder* binder = AServiceManager_checkService(serviceName);
218 if (binder == nullptr) {
219 return false;
220 }
221 AIBinder_decStrong(binder);
222
223 return true;
224 }
225
TEST(NdkBinder,GetServiceThatDoesntExist)226 TEST(NdkBinder, GetServiceThatDoesntExist) {
227 sp<IFoo> foo = IFoo::getService("asdfghkl;");
228 EXPECT_EQ(nullptr, foo.get());
229 }
230
TEST(NdkBinder,CheckServiceThatDoesntExist)231 TEST(NdkBinder, CheckServiceThatDoesntExist) {
232 AIBinder* binder = AServiceManager_checkService("asdfghkl;");
233 ASSERT_EQ(nullptr, binder);
234 }
235
TEST(NdkBinder,CheckServiceThatDoesExist)236 TEST(NdkBinder, CheckServiceThatDoesExist) {
237 AIBinder* binder = AServiceManager_checkService(kExistingNonNdkService);
238 EXPECT_NE(nullptr, binder);
239 EXPECT_EQ(STATUS_OK, AIBinder_ping(binder));
240
241 AIBinder_decStrong(binder);
242 }
243
TEST(NdkBinder,UnimplementedDump)244 TEST(NdkBinder, UnimplementedDump) {
245 sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
246 ASSERT_NE(foo, nullptr);
247 AIBinder* binder = foo->getBinder();
248 EXPECT_EQ(OK, AIBinder_dump(binder, STDOUT_FILENO, nullptr, 0));
249 AIBinder_decStrong(binder);
250 }
251
TEST(NdkBinder,UnimplementedShell)252 TEST(NdkBinder, UnimplementedShell) {
253 // libbinder_ndk doesn't support calling shell, so we are calling from the
254 // libbinder across processes to the NDK service which doesn't implement
255 // shell
256 static const sp<android::IServiceManager> sm(android::defaultServiceManager());
257 sp<IBinder> testService = sm->getService(String16(IFoo::kSomeInstanceName));
258
259 Vector<String16> argsVec;
260 EXPECT_EQ(OK, IBinder::shellCommand(testService, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
261 argsVec, nullptr, nullptr));
262 }
263
TEST(NdkBinder,DoubleNumber)264 TEST(NdkBinder, DoubleNumber) {
265 sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
266 ASSERT_NE(foo, nullptr);
267
268 int32_t out;
269 EXPECT_EQ(STATUS_OK, foo->doubleNumber(1, &out));
270 EXPECT_EQ(2, out);
271 }
272
defaultInstanceCounter(const char * instance,void * context)273 void defaultInstanceCounter(const char* instance, void* context) {
274 if (strcmp(instance, "default") == 0) {
275 ++*(size_t*)(context);
276 }
277 }
278
TEST(NdkBinder,GetDeclaredInstances)279 TEST(NdkBinder, GetDeclaredInstances) {
280 bool hasLight = AServiceManager_isDeclared("android.hardware.light.ILights/default");
281
282 size_t count;
283 AServiceManager_forEachDeclaredInstance("android.hardware.light.ILights", &count,
284 defaultInstanceCounter);
285
286 // At the time of writing this test, there is no good interface guaranteed
287 // to be on all devices. Cuttlefish has light, so this will generally test
288 // things.
289 EXPECT_EQ(count, hasLight ? 1 : 0);
290 }
291
TEST(NdkBinder,GetLazyService)292 TEST(NdkBinder, GetLazyService) {
293 // Not declared in the vintf manifest
294 ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService));
295 ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
296 std::shared_ptr<aidl::IBinderNdkUnitTest> service =
297 aidl::IBinderNdkUnitTest::fromBinder(binder);
298 ASSERT_NE(service, nullptr);
299
300 EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
301 }
302
TEST(NdkBinder,IsUpdatable)303 TEST(NdkBinder, IsUpdatable) {
304 bool isUpdatable = AServiceManager_isUpdatableViaApex("android.hardware.light.ILights/default");
305 EXPECT_EQ(isUpdatable, false);
306 }
307
308 // This is too slow
TEST(NdkBinder,CheckLazyServiceShutDown)309 TEST(NdkBinder, CheckLazyServiceShutDown) {
310 ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
311 std::shared_ptr<aidl::IBinderNdkUnitTest> service =
312 aidl::IBinderNdkUnitTest::fromBinder(binder);
313 ASSERT_NE(service, nullptr);
314
315 EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
316 binder = nullptr;
317 service = nullptr;
318 IPCThreadState::self()->flushCommands();
319 // Make sure the service is dead after some time of no use
320 sleep(kShutdownWaitTime);
321 ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
322 }
323
TEST(NdkBinder,ForcedPersistenceTest)324 TEST(NdkBinder, ForcedPersistenceTest) {
325 for (int i = 0; i < 2; i++) {
326 ndk::SpAIBinder binder(AServiceManager_waitForService(kForcePersistNdkUnitTestService));
327 std::shared_ptr<aidl::IBinderNdkUnitTest> service =
328 aidl::IBinderNdkUnitTest::fromBinder(binder);
329 ASSERT_NE(service, nullptr);
330 ASSERT_TRUE(service->forcePersist(i == 0).isOk());
331
332 binder = nullptr;
333 service = nullptr;
334 IPCThreadState::self()->flushCommands();
335
336 sleep(kShutdownWaitTime);
337
338 bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService);
339
340 if (i == 0) {
341 ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have.";
342 } else {
343 ASSERT_FALSE(isRunning) << "Service failed to shut down.";
344 }
345 }
346 }
347
TEST(NdkBinder,ActiveServicesCallbackTest)348 TEST(NdkBinder, ActiveServicesCallbackTest) {
349 ndk::SpAIBinder binder(AServiceManager_waitForService(kActiveServicesNdkUnitTestService));
350 std::shared_ptr<aidl::IBinderNdkUnitTest> service =
351 aidl::IBinderNdkUnitTest::fromBinder(binder);
352 ASSERT_NE(service, nullptr);
353 ASSERT_TRUE(service->setCustomActiveServicesCallback().isOk());
354
355 binder = nullptr;
356 service = nullptr;
357 IPCThreadState::self()->flushCommands();
358
359 sleep(kShutdownWaitTime);
360
361 ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService))
362 << "Service failed to shut down.";
363 }
364
LambdaOnDeath(void * cookie)365 void LambdaOnDeath(void* cookie) {
366 auto onDeath = static_cast<std::function<void(void)>*>(cookie);
367 (*onDeath)();
368 };
TEST(NdkBinder,DeathRecipient)369 TEST(NdkBinder, DeathRecipient) {
370 using namespace std::chrono_literals;
371
372 AIBinder* binder;
373 sp<IFoo> foo = IFoo::getService(IFoo::kInstanceNameToDieFor, &binder);
374 ASSERT_NE(nullptr, foo.get());
375 ASSERT_NE(nullptr, binder);
376
377 std::mutex deathMutex;
378 std::condition_variable deathCv;
379 bool deathRecieved = false;
380
381 std::function<void(void)> onDeath = [&] {
382 std::cerr << "Binder died (as requested)." << std::endl;
383 deathRecieved = true;
384 deathCv.notify_one();
385 };
386
387 AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(LambdaOnDeath);
388
389 EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(&onDeath)));
390
391 // the binder driver should return this if the service dies during the transaction
392 EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die());
393
394 foo = nullptr;
395
396 std::unique_lock<std::mutex> lock(deathMutex);
397 EXPECT_TRUE(deathCv.wait_for(lock, 1s, [&] { return deathRecieved; }));
398 EXPECT_TRUE(deathRecieved);
399
400 AIBinder_DeathRecipient_delete(recipient);
401 AIBinder_decStrong(binder);
402 binder = nullptr;
403 }
404
TEST(NdkBinder,RetrieveNonNdkService)405 TEST(NdkBinder, RetrieveNonNdkService) {
406 AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
407 ASSERT_NE(nullptr, binder);
408 EXPECT_TRUE(AIBinder_isRemote(binder));
409 EXPECT_TRUE(AIBinder_isAlive(binder));
410 EXPECT_EQ(STATUS_OK, AIBinder_ping(binder));
411
412 AIBinder_decStrong(binder);
413 }
414
OnBinderDeath(void * cookie)415 void OnBinderDeath(void* cookie) {
416 LOG(ERROR) << "BINDER DIED. COOKIE: " << cookie;
417 }
418
TEST(NdkBinder,LinkToDeath)419 TEST(NdkBinder, LinkToDeath) {
420 AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
421 ASSERT_NE(nullptr, binder);
422
423 AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath);
424 ASSERT_NE(nullptr, recipient);
425
426 EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr));
427 EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr));
428 EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
429 EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
430 EXPECT_EQ(STATUS_NAME_NOT_FOUND, AIBinder_unlinkToDeath(binder, recipient, nullptr));
431
432 AIBinder_DeathRecipient_delete(recipient);
433 AIBinder_decStrong(binder);
434 }
435
436 class MyTestFoo : public IFoo {
doubleNumber(int32_t in,int32_t * out)437 binder_status_t doubleNumber(int32_t in, int32_t* out) override {
438 *out = 2 * in;
439 LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
440 return STATUS_OK;
441 }
die()442 binder_status_t die() override {
443 ADD_FAILURE() << "die called on local instance";
444 return STATUS_OK;
445 }
446 };
447
TEST(NdkBinder,AddNullService)448 TEST(NdkBinder, AddNullService) {
449 EXPECT_EQ(EX_ILLEGAL_ARGUMENT, AServiceManager_addService(nullptr, "any-service-name"));
450 }
451
TEST(NdkBinder,AddInvalidServiceName)452 TEST(NdkBinder, AddInvalidServiceName) {
453 sp<IFoo> foo = new MyTestFoo;
454 EXPECT_EQ(EX_ILLEGAL_ARGUMENT, foo->addService("!@#$%^&"));
455 }
456
TEST(NdkBinder,GetServiceInProcess)457 TEST(NdkBinder, GetServiceInProcess) {
458 static const char* kInstanceName = "test-get-service-in-process";
459
460 sp<IFoo> foo = new MyTestFoo;
461 EXPECT_EQ(EX_NONE, foo->addService(kInstanceName));
462
463 sp<IFoo> getFoo = IFoo::getService(kInstanceName);
464 EXPECT_EQ(foo.get(), getFoo.get());
465
466 int32_t out;
467 EXPECT_EQ(STATUS_OK, getFoo->doubleNumber(1, &out));
468 EXPECT_EQ(2, out);
469 }
470
TEST(NdkBinder,EqualityOfRemoteBinderPointer)471 TEST(NdkBinder, EqualityOfRemoteBinderPointer) {
472 AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService);
473 ASSERT_NE(nullptr, binderA);
474
475 AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService);
476 ASSERT_NE(nullptr, binderB);
477
478 EXPECT_EQ(binderA, binderB);
479
480 AIBinder_decStrong(binderA);
481 AIBinder_decStrong(binderB);
482 }
483
TEST(NdkBinder,ToFromJavaNullptr)484 TEST(NdkBinder, ToFromJavaNullptr) {
485 EXPECT_EQ(nullptr, AIBinder_toJavaBinder(nullptr, nullptr));
486 EXPECT_EQ(nullptr, AIBinder_fromJavaBinder(nullptr, nullptr));
487 }
488
TEST(NdkBinder,ABpBinderRefCount)489 TEST(NdkBinder, ABpBinderRefCount) {
490 AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
491 AIBinder_Weak* wBinder = AIBinder_Weak_new(binder);
492
493 ASSERT_NE(nullptr, binder);
494 EXPECT_EQ(1, AIBinder_debugGetRefCount(binder));
495
496 AIBinder_decStrong(binder);
497
498 ASSERT_EQ(nullptr, AIBinder_Weak_promote(wBinder));
499
500 AIBinder_Weak_delete(wBinder);
501 }
502
TEST(NdkBinder,AddServiceMultipleTimes)503 TEST(NdkBinder, AddServiceMultipleTimes) {
504 static const char* kInstanceName1 = "test-multi-1";
505 static const char* kInstanceName2 = "test-multi-2";
506 sp<IFoo> foo = new MyTestFoo;
507 EXPECT_EQ(EX_NONE, foo->addService(kInstanceName1));
508 EXPECT_EQ(EX_NONE, foo->addService(kInstanceName2));
509 EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
510 }
511
TEST(NdkBinder,RequestedSidWorks)512 TEST(NdkBinder, RequestedSidWorks) {
513 ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
514 std::shared_ptr<aidl::IBinderNdkUnitTest> service =
515 aidl::IBinderNdkUnitTest::fromBinder(binder);
516
517 bool gotSid = false;
518 EXPECT_TRUE(service->getsRequestedSid(&gotSid).isOk());
519 EXPECT_TRUE(gotSid);
520 }
521
TEST(NdkBinder,SentAidlBinderCanBeDestroyed)522 TEST(NdkBinder, SentAidlBinderCanBeDestroyed) {
523 static volatile bool destroyed = false;
524 static std::mutex dMutex;
525 static std::condition_variable cv;
526
527 class MyEmpty : public aidl::BnEmpty {
528 virtual ~MyEmpty() {
529 destroyed = true;
530 cv.notify_one();
531 }
532 };
533
534 std::shared_ptr<MyEmpty> empty = ndk::SharedRefBase::make<MyEmpty>();
535
536 ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
537 std::shared_ptr<aidl::IBinderNdkUnitTest> service =
538 aidl::IBinderNdkUnitTest::fromBinder(binder);
539
540 EXPECT_FALSE(destroyed);
541
542 service->takeInterface(empty);
543 service->forceFlushCommands();
544 empty = nullptr;
545
546 // give other binder thread time to process commands
547 {
548 using namespace std::chrono_literals;
549 std::unique_lock<std::mutex> lk(dMutex);
550 cv.wait_for(lk, 1s, [] { return destroyed; });
551 }
552
553 EXPECT_TRUE(destroyed);
554 }
555
TEST(NdkBinder,ConvertToPlatformBinder)556 TEST(NdkBinder, ConvertToPlatformBinder) {
557 for (const ndk::SpAIBinder& binder :
558 {// remote
559 ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
560 // local
561 ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
562 // convert to platform binder
563 EXPECT_NE(binder.get(), nullptr);
564 sp<IBinder> platformBinder = AIBinder_toPlatformBinder(binder.get());
565 EXPECT_NE(platformBinder.get(), nullptr);
566 auto proxy = interface_cast<IBinderNdkUnitTest>(platformBinder);
567 EXPECT_NE(proxy, nullptr);
568
569 // use platform binder
570 int out;
571 EXPECT_TRUE(proxy->repeatInt(4, &out).isOk());
572 EXPECT_EQ(out, 4);
573
574 // convert back
575 ndk::SpAIBinder backBinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(platformBinder));
576 EXPECT_EQ(backBinder.get(), binder.get());
577 }
578 }
579
580 class MyResultReceiver : public BnResultReceiver {
581 public:
582 Mutex mMutex;
583 Condition mCondition;
584 bool mHaveResult = false;
585 int32_t mResult = 0;
586
send(int32_t resultCode)587 virtual void send(int32_t resultCode) {
588 AutoMutex _l(mMutex);
589 mResult = resultCode;
590 mHaveResult = true;
591 mCondition.signal();
592 }
593
waitForResult()594 int32_t waitForResult() {
595 AutoMutex _l(mMutex);
596 while (!mHaveResult) {
597 mCondition.wait(mMutex);
598 }
599 return mResult;
600 }
601 };
602
603 class MyShellCallback : public BnShellCallback {
604 public:
openFile(const String16 &,const String16 &,const String16 &)605 virtual int openFile(const String16& /*path*/, const String16& /*seLinuxContext*/,
606 const String16& /*mode*/) {
607 // Empty implementation.
608 return 0;
609 }
610 };
611
ReadFdToString(int fd,std::string * content)612 bool ReadFdToString(int fd, std::string* content) {
613 char buf[64];
614 ssize_t n;
615 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
616 content->append(buf, n);
617 }
618 return (n == 0) ? true : false;
619 }
620
shellCmdToString(sp<IBinder> unitTestService,const std::vector<const char * > & args)621 std::string shellCmdToString(sp<IBinder> unitTestService, const std::vector<const char*>& args) {
622 int inFd[2] = {-1, -1};
623 int outFd[2] = {-1, -1};
624 int errFd[2] = {-1, -1};
625
626 EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, inFd));
627 EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, outFd));
628 EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, errFd));
629
630 sp<MyShellCallback> cb = new MyShellCallback();
631 sp<MyResultReceiver> resultReceiver = new MyResultReceiver();
632
633 Vector<String16> argsVec;
634 for (int i = 0; i < args.size(); i++) {
635 argsVec.add(String16(args[i]));
636 }
637 status_t error = IBinder::shellCommand(unitTestService, inFd[0], outFd[0], errFd[0], argsVec,
638 cb, resultReceiver);
639 EXPECT_EQ(error, android::OK);
640
641 status_t res = resultReceiver->waitForResult();
642 EXPECT_EQ(res, android::OK);
643
644 close(inFd[0]);
645 close(inFd[1]);
646 close(outFd[0]);
647 close(errFd[0]);
648 close(errFd[1]);
649
650 std::string ret;
651 EXPECT_TRUE(ReadFdToString(outFd[1], &ret));
652 close(outFd[1]);
653 return ret;
654 }
655
TEST(NdkBinder,UseHandleShellCommand)656 TEST(NdkBinder, UseHandleShellCommand) {
657 static const sp<android::IServiceManager> sm(android::defaultServiceManager());
658 sp<IBinder> testService = sm->getService(String16(kBinderNdkUnitTestService));
659
660 EXPECT_EQ("", shellCmdToString(testService, {}));
661 EXPECT_EQ("", shellCmdToString(testService, {"", ""}));
662 EXPECT_EQ("Hello world!", shellCmdToString(testService, {"Hello ", "world!"}));
663 EXPECT_EQ("CMD", shellCmdToString(testService, {"C", "M", "D"}));
664 }
665
TEST(NdkBinder,GetClassInterfaceDescriptor)666 TEST(NdkBinder, GetClassInterfaceDescriptor) {
667 ASSERT_STREQ(IFoo::kIFooDescriptor, AIBinder_Class_getDescriptor(IFoo::kClass));
668 }
669
main(int argc,char * argv[])670 int main(int argc, char* argv[]) {
671 ::testing::InitGoogleTest(&argc, argv);
672
673 if (fork() == 0) {
674 prctl(PR_SET_PDEATHSIG, SIGHUP);
675 return manualThreadPoolService(IFoo::kInstanceNameToDieFor);
676 }
677 if (fork() == 0) {
678 prctl(PR_SET_PDEATHSIG, SIGHUP);
679 return manualPollingService(IFoo::kSomeInstanceName);
680 }
681 if (fork() == 0) {
682 prctl(PR_SET_PDEATHSIG, SIGHUP);
683 return lazyService(kLazyBinderNdkUnitTestService);
684 }
685 if (fork() == 0) {
686 prctl(PR_SET_PDEATHSIG, SIGHUP);
687 return lazyService(kForcePersistNdkUnitTestService);
688 }
689 if (fork() == 0) {
690 prctl(PR_SET_PDEATHSIG, SIGHUP);
691 return lazyService(kActiveServicesNdkUnitTestService);
692 }
693 if (fork() == 0) {
694 prctl(PR_SET_PDEATHSIG, SIGHUP);
695 return generatedService();
696 }
697
698 ABinderProcess_setThreadPoolMaxThreadCount(1); // to receive death notifications/callbacks
699 ABinderProcess_startThreadPool();
700
701 return RUN_ALL_TESTS();
702 }
703
704 #include <android/binder_auto_utils.h>
705 #include <android/binder_interface_utils.h>
706 #include <android/binder_parcel_utils.h>
707