@@ -536,6 +536,7 @@ TEST(NdkBinder, DeathRecipient) {
536536 bool deathReceived = false ;
537537
538538 std::function<void (void )> onDeath = [&] {
539+ std::unique_lock<std::mutex> lockDeath (deathMutex);
539540 std::cerr << " Binder died (as requested)." << std::endl;
540541 deathReceived = true ;
541542 deathCv.notify_one ();
@@ -547,6 +548,7 @@ TEST(NdkBinder, DeathRecipient) {
547548 bool wasDeathReceivedFirst = false ;
548549
549550 std::function<void (void )> onUnlink = [&] {
551+ std::unique_lock<std::mutex> lockUnlink (unlinkMutex);
550552 std::cerr << " Binder unlinked (as requested)." << std::endl;
551553 wasDeathReceivedFirst = deathReceived;
552554 unlinkReceived = true ;
@@ -560,7 +562,6 @@ TEST(NdkBinder, DeathRecipient) {
560562
561563 EXPECT_EQ (STATUS_OK, AIBinder_linkToDeath (binder, recipient, static_cast <void *>(cookie)));
562564
563- // the binder driver should return this if the service dies during the transaction
564565 EXPECT_EQ (STATUS_DEAD_OBJECT, foo->die ());
565566
566567 foo = nullptr ;
@@ -579,6 +580,123 @@ TEST(NdkBinder, DeathRecipient) {
579580 binder = nullptr ;
580581}
581582
583+ TEST (NdkBinder, DeathRecipientDropBinderNoDeath) {
584+ using namespace std ::chrono_literals;
585+
586+ std::mutex deathMutex;
587+ std::condition_variable deathCv;
588+ bool deathReceived = false ;
589+
590+ std::function<void (void )> onDeath = [&] {
591+ std::unique_lock<std::mutex> lockDeath (deathMutex);
592+ std::cerr << " Binder died (as requested)." << std::endl;
593+ deathReceived = true ;
594+ deathCv.notify_one ();
595+ };
596+
597+ std::mutex unlinkMutex;
598+ std::condition_variable unlinkCv;
599+ bool unlinkReceived = false ;
600+ bool wasDeathReceivedFirst = false ;
601+
602+ std::function<void (void )> onUnlink = [&] {
603+ std::unique_lock<std::mutex> lockUnlink (unlinkMutex);
604+ std::cerr << " Binder unlinked (as requested)." << std::endl;
605+ wasDeathReceivedFirst = deathReceived;
606+ unlinkReceived = true ;
607+ unlinkCv.notify_one ();
608+ };
609+
610+ // keep the death recipient around
611+ ndk::ScopedAIBinder_DeathRecipient recipient (AIBinder_DeathRecipient_new (LambdaOnDeath));
612+ AIBinder_DeathRecipient_setOnUnlinked (recipient.get (), LambdaOnUnlink);
613+
614+ {
615+ AIBinder* binder;
616+ sp<IFoo> foo = IFoo::getService (IFoo::kInstanceNameToDieFor2 , &binder);
617+ ASSERT_NE (nullptr , foo.get ());
618+ ASSERT_NE (nullptr , binder);
619+
620+ DeathRecipientCookie* cookie = new DeathRecipientCookie{&onDeath, &onUnlink};
621+
622+ EXPECT_EQ (STATUS_OK,
623+ AIBinder_linkToDeath (binder, recipient.get (), static_cast <void *>(cookie)));
624+ // let the sp<IFoo> and AIBinder fall out of scope
625+ AIBinder_decStrong (binder);
626+ binder = nullptr ;
627+ }
628+
629+ {
630+ std::unique_lock<std::mutex> lockDeath (deathMutex);
631+ EXPECT_FALSE (deathCv.wait_for (lockDeath, 100ms, [&] { return deathReceived; }));
632+ EXPECT_FALSE (deathReceived);
633+ }
634+
635+ {
636+ std::unique_lock<std::mutex> lockUnlink (unlinkMutex);
637+ EXPECT_TRUE (deathCv.wait_for (lockUnlink, 1s, [&] { return unlinkReceived; }));
638+ EXPECT_TRUE (unlinkReceived);
639+ EXPECT_FALSE (wasDeathReceivedFirst);
640+ }
641+ }
642+
643+ TEST (NdkBinder, DeathRecipientDropBinderOnDied) {
644+ using namespace std ::chrono_literals;
645+
646+ std::mutex deathMutex;
647+ std::condition_variable deathCv;
648+ bool deathReceived = false ;
649+
650+ sp<IFoo> foo;
651+ AIBinder* binder;
652+ std::function<void (void )> onDeath = [&] {
653+ std::unique_lock<std::mutex> lockDeath (deathMutex);
654+ std::cerr << " Binder died (as requested)." << std::endl;
655+ deathReceived = true ;
656+ AIBinder_decStrong (binder);
657+ binder = nullptr ;
658+ deathCv.notify_one ();
659+ };
660+
661+ std::mutex unlinkMutex;
662+ std::condition_variable unlinkCv;
663+ bool unlinkReceived = false ;
664+ bool wasDeathReceivedFirst = false ;
665+
666+ std::function<void (void )> onUnlink = [&] {
667+ std::unique_lock<std::mutex> lockUnlink (unlinkMutex);
668+ std::cerr << " Binder unlinked (as requested)." << std::endl;
669+ wasDeathReceivedFirst = deathReceived;
670+ unlinkReceived = true ;
671+ unlinkCv.notify_one ();
672+ };
673+
674+ ndk::ScopedAIBinder_DeathRecipient recipient (AIBinder_DeathRecipient_new (LambdaOnDeath));
675+ AIBinder_DeathRecipient_setOnUnlinked (recipient.get (), LambdaOnUnlink);
676+
677+ foo = IFoo::getService (IFoo::kInstanceNameToDieFor2 , &binder);
678+ ASSERT_NE (nullptr , foo.get ());
679+ ASSERT_NE (nullptr , binder);
680+
681+ DeathRecipientCookie* cookie = new DeathRecipientCookie{&onDeath, &onUnlink};
682+ EXPECT_EQ (STATUS_OK, AIBinder_linkToDeath (binder, recipient.get (), static_cast <void *>(cookie)));
683+
684+ EXPECT_EQ (STATUS_DEAD_OBJECT, foo->die ());
685+
686+ {
687+ std::unique_lock<std::mutex> lockDeath (deathMutex);
688+ EXPECT_TRUE (deathCv.wait_for (lockDeath, 1s, [&] { return deathReceived; }));
689+ EXPECT_TRUE (deathReceived);
690+ }
691+
692+ {
693+ std::unique_lock<std::mutex> lockUnlink (unlinkMutex);
694+ EXPECT_TRUE (deathCv.wait_for (lockUnlink, 100ms, [&] { return unlinkReceived; }));
695+ EXPECT_TRUE (unlinkReceived);
696+ EXPECT_TRUE (wasDeathReceivedFirst);
697+ }
698+ }
699+
582700TEST (NdkBinder, RetrieveNonNdkService) {
583701#pragma clang diagnostic push
584702#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -956,6 +1074,10 @@ int main(int argc, char* argv[]) {
9561074 prctl (PR_SET_PDEATHSIG, SIGHUP);
9571075 return manualThreadPoolService (IFoo::kInstanceNameToDieFor );
9581076 }
1077+ if (fork () == 0 ) {
1078+ prctl (PR_SET_PDEATHSIG, SIGHUP);
1079+ return manualThreadPoolService (IFoo::kInstanceNameToDieFor2 );
1080+ }
9591081 if (fork () == 0 ) {
9601082 prctl (PR_SET_PDEATHSIG, SIGHUP);
9611083 return manualPollingService (IFoo::kSomeInstanceName );
0 commit comments