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, 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 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> 122 RemoteCallbackMap<K, V>::~RemoteCallbackMap() { 123 Clear(); 124 } 125 126 template <typename K, typename V> 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> 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> 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> 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> 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> 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> 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> 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