1 // 2 // Copyright (C) 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, 64 const android::sp<V>& callback, 65 Delegate* delegate = nullptr); 66 67 // Unregisters a previously registered callback with the given key. Returns 68 // false if |key| doesn't exist. 69 bool Unregister(const K& key); 70 71 // Returns the callback associated with the given key. Returns NULL if |key| 72 // doesn't exist. 73 android::sp<V> Get(const K& key); 74 75 // Removes the callback associated with the given key from the map and returns 76 // the value. Returns NULL if the key doesn't exists. 77 android::sp<V> Remove(const K& key); 78 79 // Clear the contents of the map. 80 void Clear(); 81 82 private: 83 class CallbackDeathRecipient : public android::IBinder::DeathRecipient { 84 public: 85 CallbackDeathRecipient( 86 const K& key, 87 const android::sp<V>& callback, 88 RemoteCallbackMap<K, V>* owner, 89 Delegate* delegate); 90 91 android::sp<V> get_callback() const { return callback_; } 92 93 // android::IBinder::DeathRecipient override: 94 void binderDied(const android::wp<android::IBinder>& who) override; 95 96 private: 97 K key_; 98 android::sp<V> callback_; 99 RemoteCallbackMap<K, V>* owner_; // weak 100 Delegate* delegate_; // weak 101 }; 102 103 // Typedef for internal map container. 104 using CallbackMap = 105 std::unordered_map<K, android::sp<CallbackDeathRecipient>>; 106 107 bool UnregisterInternal(typename CallbackMap::iterator iter); 108 109 std::mutex map_lock_; 110 CallbackMap map_; 111 112 DISALLOW_COPY_AND_ASSIGN(RemoteCallbackMap); 113 }; 114 115 // Template Implementation details below 116 // ======================================================== 117 118 using android::IBinder; 119 using android::IInterface; 120 using android::sp; 121 using android::wp; 122 using std::lock_guard; 123 using std::mutex; 124 125 template<typename K, typename V> 126 RemoteCallbackMap<K, V>::~RemoteCallbackMap() { 127 Clear(); 128 } 129 130 template<typename K, typename V> 131 bool RemoteCallbackMap<K, V>::Register( 132 const K& key, 133 const sp<V>& callback, 134 Delegate* delegate) { 135 lock_guard<mutex> lock(map_lock_); 136 137 if (map_.find(key) != map_.end()) { 138 VLOG(1) << "Callback map already contains key"; 139 return false; 140 } 141 142 sp<CallbackDeathRecipient> dr( 143 new CallbackDeathRecipient(key, callback, this, delegate)); 144 sp<IBinder> binder = IInterface::asBinder(callback.get()); 145 if (binder->linkToDeath(dr) != android::NO_ERROR) { 146 LOG(ERROR) << "Failed to link death recipient to binder"; 147 return false; 148 } 149 150 map_[key] = dr; 151 152 VLOG(2) << "Callback successfully registered with map"; 153 154 return true; 155 } 156 157 template<typename K, typename V> 158 bool RemoteCallbackMap<K, V>::Unregister(const K& key) { 159 lock_guard<mutex> lock(map_lock_); 160 161 auto iter = map_.find(key); 162 if (iter == map_.end()) { 163 VLOG(1) << "Callback with given key not found"; 164 return false; 165 } 166 167 return UnregisterInternal(iter); 168 } 169 170 template<typename K, typename V> 171 sp<V> RemoteCallbackMap<K, V>::Get(const K& key) { 172 lock_guard<mutex> lock(map_lock_); 173 174 auto iter = map_.find(key); 175 if (iter == map_.end()) 176 return nullptr; 177 178 return iter->second->get_callback(); 179 } 180 181 template<typename K, typename V> 182 sp<V> RemoteCallbackMap<K, V>::Remove(const K& key) { 183 lock_guard<mutex> lock(map_lock_); 184 185 auto iter = map_.find(key); 186 if (iter == map_.end()) 187 return nullptr; 188 189 sp<V> val = iter->second->get_callback(); 190 UnregisterInternal(iter); 191 192 return val; 193 } 194 template<typename K, typename V> 195 void RemoteCallbackMap<K, V>::Clear() { 196 lock_guard<mutex> lock(map_lock_); 197 198 for (auto iter = map_.begin(); iter != map_.end();) 199 UnregisterInternal(iter++); 200 } 201 202 template<typename K, typename V> 203 bool RemoteCallbackMap<K, V>::UnregisterInternal( 204 typename CallbackMap::iterator iter) { 205 sp<CallbackDeathRecipient> dr = iter->second; 206 map_.erase(iter); 207 208 if (IInterface::asBinder(dr->get_callback().get())->unlinkToDeath(dr) != 209 android::NO_ERROR) { 210 LOG(ERROR) << "Failed to unlink death recipient from binder"; 211 212 // We removed the entry from |map_| but unlinkToDeath failed. There isn't 213 // really much we can do here other than deleting the binder and returning 214 // an error. 215 return false; 216 } 217 218 VLOG(2) << "Callback successfully removed from map"; 219 220 return true; 221 } 222 223 template<typename K, typename V> 224 RemoteCallbackMap<K, V>::CallbackDeathRecipient::CallbackDeathRecipient( 225 const K& key, 226 const sp<V>& callback, 227 RemoteCallbackMap<K, V>* owner, 228 Delegate* delegate) 229 : key_(key), 230 callback_(callback), 231 owner_(owner), 232 delegate_(delegate) { 233 CHECK(callback_.get()); 234 } 235 236 template<typename K, typename V> 237 void RemoteCallbackMap<K, V>::CallbackDeathRecipient::binderDied( 238 const wp<IBinder>& who) { 239 VLOG(1) << "Received binderDied"; 240 241 sp<IBinder> binder = IInterface::asBinder(callback_.get()); 242 CHECK(who.unsafe_get() == binder.get()); 243 244 // Remove the callback but no need to call unlinkToDeath. 245 { 246 lock_guard<mutex> lock(owner_->map_lock_); 247 auto iter = owner_->map_.find(key_); 248 CHECK(iter != owner_->map_.end()); 249 owner_->map_.erase(iter); 250 } 251 252 VLOG(1) << "Callback from dead process unregistered; notifying delegate"; 253 254 // Notify delegate. 255 if (delegate_) 256 delegate_->OnRemoteCallbackRemoved(key_); 257 } 258 259 } // namespace binder 260 } // namespace ipc 261