1 //
2 // Copyright 2015 Google, Inc.
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 #pragma once
18
19 #include <mutex>
20 #include <unordered_map>
21
22 #include <base/logging.h>
23 #include <base/macros.h>
24 #include <binder/IBinder.h>
25 #include <binder/IInterface.h>
26
27 namespace ipc {
28 namespace binder {
29
30 // A map of remote interfaces where the value type "V" must inherit from
31 // android::IInterface. This is just like RemoteCallbackList except it provides
32 // a key-value mapping.
33 //
34 // TODO(armansito): We should make this class non-final and the template
35 // interface abstract, so that code that depends on this can be unit tested
36 // against a mock version of this class.
37 template <typename K, typename V>
38 class RemoteCallbackMap final {
39 public:
40 RemoteCallbackMap() = default;
41 ~RemoteCallbackMap();
42
43 // The Delegate interface is used to notify when a registered callback is
44 // removed from the map as a result of the death of the remote process that
45 // owns the registered callback.
46 class Delegate {
47 public:
48 virtual ~Delegate() = default;
49
50 // Called when a remote callback associated with the key |key| has been
51 // removed. This won't get called if the callback was removed as a result of
52 // a call to RemoteCallbackMap::Unregister.
53 virtual void OnRemoteCallbackRemoved(const K& key) = 0;
54 };
55
56 // Register a callback interface and associate it with the given key.
57 // Registering will automatically start tracking for death notifications in
58 // case the remote process hosting the Binder dies. In such a case, the Binder
59 // is automatically removed from the map.
60 //
61 // An optional |delegate| can be passed which will be assocated with the given
62 // key/value pair. |delegate| must outlive this map.
63 bool Register(const K& key, const android::sp<V>& callback,
64 Delegate* delegate = nullptr);
65
66 // Unregisters a previously registered callback with the given key. Returns
67 // false if |key| doesn't exist.
68 bool Unregister(const K& key);
69
70 // Returns the callback associated with the given key. Returns NULL if |key|
71 // doesn't exist.
72 android::sp<V> Get(const K& key);
73
74 // Removes the callback associated with the given key from the map and returns
75 // the value. Returns NULL if the key doesn't exists.
76 android::sp<V> Remove(const K& key);
77
78 // Clear the contents of the map.
79 void Clear();
80
81 private:
82 class CallbackDeathRecipient : public android::IBinder::DeathRecipient {
83 public:
84 CallbackDeathRecipient(const K& key, const android::sp<V>& callback,
85 RemoteCallbackMap<K, V>* owner, Delegate* delegate);
86
get_callback()87 android::sp<V> get_callback() const { return callback_; }
88
89 // android::IBinder::DeathRecipient override:
90 void binderDied(const android::wp<android::IBinder>& who) override;
91
92 private:
93 K key_;
94 android::sp<V> callback_;
95 RemoteCallbackMap<K, V>* owner_; // weak
96 Delegate* delegate_; // weak
97 };
98
99 // Typedef for internal map container.
100 using CallbackMap =
101 std::unordered_map<K, android::sp<CallbackDeathRecipient>>;
102
103 bool UnregisterInternal(typename CallbackMap::iterator iter);
104
105 std::mutex map_lock_;
106 CallbackMap map_;
107
108 DISALLOW_COPY_AND_ASSIGN(RemoteCallbackMap);
109 };
110
111 // Template Implementation details below
112 // ========================================================
113
114 using android::IBinder;
115 using android::IInterface;
116 using android::sp;
117 using android::wp;
118 using std::lock_guard;
119 using std::mutex;
120
121 template <typename K, typename V>
~RemoteCallbackMap()122 RemoteCallbackMap<K, V>::~RemoteCallbackMap() {
123 Clear();
124 }
125
126 template <typename K, typename V>
Register(const K & key,const sp<V> & callback,Delegate * delegate)127 bool RemoteCallbackMap<K, V>::Register(const K& key, const sp<V>& callback,
128 Delegate* delegate) {
129 lock_guard<mutex> lock(map_lock_);
130
131 if (map_.find(key) != map_.end()) {
132 VLOG(1) << "Callback map already contains key";
133 return false;
134 }
135
136 sp<CallbackDeathRecipient> dr(
137 new CallbackDeathRecipient(key, callback, this, delegate));
138 sp<IBinder> binder = IInterface::asBinder(callback.get());
139 if (binder->linkToDeath(dr) != android::NO_ERROR) {
140 LOG(ERROR) << "Failed to link death recipient to binder";
141 return false;
142 }
143
144 map_[key] = dr;
145
146 VLOG(2) << "Callback successfully registered with map";
147
148 return true;
149 }
150
151 template <typename K, typename V>
Unregister(const K & key)152 bool RemoteCallbackMap<K, V>::Unregister(const K& key) {
153 lock_guard<mutex> lock(map_lock_);
154
155 auto iter = map_.find(key);
156 if (iter == map_.end()) {
157 VLOG(1) << "Callback with given key not found";
158 return false;
159 }
160
161 return UnregisterInternal(iter);
162 }
163
164 template <typename K, typename V>
Get(const K & key)165 sp<V> RemoteCallbackMap<K, V>::Get(const K& key) {
166 lock_guard<mutex> lock(map_lock_);
167
168 auto iter = map_.find(key);
169 if (iter == map_.end()) return nullptr;
170
171 return iter->second->get_callback();
172 }
173
174 template <typename K, typename V>
Remove(const K & key)175 sp<V> RemoteCallbackMap<K, V>::Remove(const K& key) {
176 lock_guard<mutex> lock(map_lock_);
177
178 auto iter = map_.find(key);
179 if (iter == map_.end()) return nullptr;
180
181 sp<V> val = iter->second->get_callback();
182 UnregisterInternal(iter);
183
184 return val;
185 }
186 template <typename K, typename V>
Clear()187 void RemoteCallbackMap<K, V>::Clear() {
188 lock_guard<mutex> lock(map_lock_);
189
190 for (auto iter = map_.begin(); iter != map_.end();)
191 UnregisterInternal(iter++);
192 }
193
194 template <typename K, typename V>
UnregisterInternal(typename CallbackMap::iterator iter)195 bool RemoteCallbackMap<K, V>::UnregisterInternal(
196 typename CallbackMap::iterator iter) {
197 sp<CallbackDeathRecipient> dr = iter->second;
198 map_.erase(iter);
199
200 if (IInterface::asBinder(dr->get_callback().get())->unlinkToDeath(dr) !=
201 android::NO_ERROR) {
202 LOG(ERROR) << "Failed to unlink death recipient from binder";
203
204 // We removed the entry from |map_| but unlinkToDeath failed. There isn't
205 // really much we can do here other than deleting the binder and returning
206 // an error.
207 return false;
208 }
209
210 VLOG(2) << "Callback successfully removed from map";
211
212 return true;
213 }
214
215 template <typename K, typename V>
CallbackDeathRecipient(const K & key,const sp<V> & callback,RemoteCallbackMap<K,V> * owner,Delegate * delegate)216 RemoteCallbackMap<K, V>::CallbackDeathRecipient::CallbackDeathRecipient(
217 const K& key, const sp<V>& callback, RemoteCallbackMap<K, V>* owner,
218 Delegate* delegate)
219 : key_(key), callback_(callback), owner_(owner), delegate_(delegate) {
220 CHECK(callback_.get());
221 }
222
223 template <typename K, typename V>
binderDied(const wp<IBinder> & who)224 void RemoteCallbackMap<K, V>::CallbackDeathRecipient::binderDied(
225 const wp<IBinder>& who) {
226 VLOG(1) << "Received binderDied";
227
228 sp<IBinder> binder = IInterface::asBinder(callback_.get());
229 CHECK(who.unsafe_get() == binder.get());
230
231 // Remove the callback but no need to call unlinkToDeath.
232 {
233 lock_guard<mutex> lock(owner_->map_lock_);
234 auto iter = owner_->map_.find(key_);
235 CHECK(iter != owner_->map_.end());
236 owner_->map_.erase(iter);
237 }
238
239 VLOG(1) << "Callback from dead process unregistered; notifying delegate";
240
241 // Notify delegate.
242 if (delegate_) delegate_->OnRemoteCallbackRemoved(key_);
243 }
244
245 } // namespace binder
246 } // namespace ipc
247