1 /*
2 * Copyright 2019 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MediaPlayerService-DeathNotifier"
19 #include <android-base/logging.h>
20 #include <map>
21
22 #include "DeathNotifier.h"
23
24 namespace android {
25
26 // Only dereference the cookie if it's valid (if it's in this set)
27 // Only used with ndk
28 static uintptr_t sCookieKeyCounter = 0;
29 static std::map<uintptr_t, wp<DeathNotifier::DeathRecipient>> sCookies;
30 static std::mutex sCookiesMutex;
31
32 class DeathNotifier::DeathRecipient :
33 public IBinder::DeathRecipient,
34 public hardware::hidl_death_recipient {
35 public:
36 using Notify = DeathNotifier::Notify;
37
DeathRecipient(Notify const & notify)38 DeathRecipient(Notify const& notify): mNotify{notify} {
39 }
40
initNdk()41 void initNdk() {
42 mNdkRecipient.set(AIBinder_DeathRecipient_new(OnBinderDied));
43 }
44
binderDied(wp<IBinder> const &)45 virtual void binderDied(wp<IBinder> const&) override {
46 mNotify();
47 }
48
serviceDied(uint64_t,wp<HBase> const &)49 virtual void serviceDied(uint64_t, wp<HBase> const&) override {
50 mNotify();
51 }
52
OnBinderDied(void * cookie)53 static void OnBinderDied(void *cookie) {
54 std::unique_lock<std::mutex> guard(sCookiesMutex);
55 if (auto it = sCookies.find(reinterpret_cast<uintptr_t>(cookie)); it != sCookies.end()) {
56 sp<DeathRecipient> recipient = it->second.promote();
57 sCookies.erase(it);
58 guard.unlock();
59
60 if (recipient) {
61 LOG(INFO) << "Notifying DeathRecipient from OnBinderDied.";
62 recipient->mNotify();
63 } else {
64 LOG(INFO) <<
65 "Tried to notify DeathRecipient from OnBinderDied but could not promote.";
66 }
67 }
68 }
69
getNdkRecipient()70 AIBinder_DeathRecipient *getNdkRecipient() {
71 return mNdkRecipient.get();;
72 }
~DeathRecipient()73 ~DeathRecipient() {
74 // lock must be taken so object is not used in OnBinderDied"
75 std::lock_guard<std::mutex> guard(sCookiesMutex);
76 sCookies.erase(mCookieKey);
77 }
78
79 uintptr_t mCookieKey;
80
81 private:
82 Notify mNotify;
83 ::ndk::ScopedAIBinder_DeathRecipient mNdkRecipient;
84 };
85
DeathNotifier(sp<IBinder> const & service,Notify const & notify)86 DeathNotifier::DeathNotifier(sp<IBinder> const& service, Notify const& notify)
87 : mService{std::in_place_index<1>, service},
88 mDeathRecipient{new DeathRecipient(notify)} {
89 service->linkToDeath(mDeathRecipient);
90 }
91
DeathNotifier(sp<HBase> const & service,Notify const & notify)92 DeathNotifier::DeathNotifier(sp<HBase> const& service, Notify const& notify)
93 : mService{std::in_place_index<2>, service},
94 mDeathRecipient{new DeathRecipient(notify)} {
95 service->linkToDeath(mDeathRecipient, 0);
96 }
97
DeathNotifier(::ndk::SpAIBinder const & service,Notify const & notify)98 DeathNotifier::DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify)
99 : mService{std::in_place_index<3>, service},
100 mDeathRecipient{new DeathRecipient(notify)} {
101 mDeathRecipient->initNdk();
102 {
103 std::lock_guard<std::mutex> guard(sCookiesMutex);
104 mDeathRecipient->mCookieKey = sCookieKeyCounter++;
105 sCookies[mDeathRecipient->mCookieKey] = mDeathRecipient;
106 }
107 AIBinder_linkToDeath(
108 service.get(),
109 mDeathRecipient->getNdkRecipient(),
110 reinterpret_cast<void*>(mDeathRecipient->mCookieKey));
111 }
112
DeathNotifier(DeathNotifier && other)113 DeathNotifier::DeathNotifier(DeathNotifier&& other)
114 : mService{other.mService}, mDeathRecipient{other.mDeathRecipient} {
115 other.mService.emplace<0>();
116 other.mDeathRecipient = nullptr;
117 }
118
~DeathNotifier()119 DeathNotifier::~DeathNotifier() {
120 switch (mService.index()) {
121 case 0:
122 break;
123 case 1:
124 std::get<1>(mService)->unlinkToDeath(mDeathRecipient);
125 break;
126 case 2:
127 std::get<2>(mService)->unlinkToDeath(mDeathRecipient);
128 break;
129 case 3:
130
131 AIBinder_unlinkToDeath(
132 std::get<3>(mService).get(),
133 mDeathRecipient->getNdkRecipient(),
134 reinterpret_cast<void*>(mDeathRecipient->mCookieKey));
135 break;
136 default:
137 CHECK(false) << "Corrupted service type during destruction.";
138 }
139 }
140
141 } // namespace android
142
143