Loading system/service/ipc/binder/remote_callback_list.h +17 −13 Original line number Diff line number Diff line Loading @@ -17,8 +17,8 @@ #pragma once #include <functional> #include <map> #include <mutex> #include <unordered_map> #include <base/logging.h> #include <base/macros.h> Loading Loading @@ -69,12 +69,12 @@ class RemoteCallbackList final { private: class CallbackDeathRecipient : public android::IBinder::DeathRecipient { public: explicit CallbackDeathRecipient(const android::sp<T>& callback, CallbackDeathRecipient(const android::sp<T>& callback, RemoteCallbackList* owner); android::sp<T> get_callback() const { return callback_; } // android::DeathRecipient override: // android::IBinder::DeathRecipient override: void binderDied(const android::wp<android::IBinder>& who) override; private: Loading @@ -84,7 +84,7 @@ class RemoteCallbackList final { // Typedef for internal map container. This keeps track of a given Binder and // a death receiver associated with it. using CallbackMap = std::map<android::sp<android::IBinder>, using CallbackMap = std::unordered_map<android::IBinder*, android::sp<CallbackDeathRecipient>>; bool UnregisterInternal(typename CallbackMap::iterator iter); Loading Loading @@ -115,7 +115,7 @@ bool RemoteCallbackList<T>::Register(const sp<T>& callback) { std::lock_guard<std::mutex> lock(map_lock_); sp<IBinder> binder = IInterface::asBinder(callback.get()); if (callbacks_.find(binder) != callbacks_.end()) { if (callbacks_.find(binder.get()) != callbacks_.end()) { VLOG(1) << "Callback list already contains given callback"; return false; } Loading @@ -127,9 +127,9 @@ bool RemoteCallbackList<T>::Register(const sp<T>& callback) { return false; } callbacks_[binder] = dr; callbacks_[binder.get()] = dr; VLOG(1) << "Callback successfully registered"; VLOG(2) << "Callback successfully registered with list"; return true; } Loading @@ -139,9 +139,9 @@ bool RemoteCallbackList<T>::Unregister(const sp<T>& callback) { std::lock_guard<std::mutex> lock(map_lock_); sp<IBinder> binder = IInterface::asBinder(callback.get()); auto iter = callbacks_.find(binder); auto iter = callbacks_.find(binder.get()); if (iter == callbacks_.end()) { VLOG(1) << "Given callback not registered"; VLOG(2) << "Given callback not registered with this list"; return false; } Loading @@ -164,10 +164,14 @@ bool RemoteCallbackList<T>::UnregisterInternal( if (IInterface::asBinder(dr->get_callback().get())->unlinkToDeath(dr) != android::NO_ERROR) { LOG(ERROR) << "Failed to unlink death recipient from binder"; // We removed the entry from |map_| but unlinkToDeath failed. There isn't // really much we can do here other than deleting the binder and returning // an error. return false; } VLOG(1) << "Callback successfully unregistered"; VLOG(2) << "Callback successfully removed from list"; return true; } Loading @@ -192,7 +196,7 @@ void RemoteCallbackList<T>::CallbackDeathRecipient::binderDied( // Remove the callback but no need to call unlinkToDeath. std::lock_guard<std::mutex> lock(owner_->map_lock_); auto iter = owner_->callbacks_.find(binder); auto iter = owner_->callbacks_.find(binder.get()); CHECK(iter != owner_->callbacks_.end()); owner_->callbacks_.erase(iter); Loading system/service/ipc/binder/remote_callback_map.h 0 → 100644 +260 −0 Original line number Diff line number Diff line // // Copyright (C) 2015 Google, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #pragma once #include <mutex> #include <unordered_map> #include <base/logging.h> #include <base/macros.h> #include <binder/IBinder.h> #include <binder/IInterface.h> namespace ipc { namespace binder { // A map of remote interfaces where the value type "V" must inherit from // android::IInterface. This is just like RemoteCallbackList except it provides // a key-value mapping. // // TODO(armansito): We should make this class non-final and the template // interface abstract, so that code that depends on this can be unit tested // against a mock version of this class. template<typename K, typename V> class RemoteCallbackMap final { public: RemoteCallbackMap() = default; ~RemoteCallbackMap(); // The Delegate interface is used to notify when a registered callback is // removed from the map as a result of the death of the remote process that // owns the registered callback. class Delegate { public: virtual ~Delegate() = default; // Called when a remote callback associated with the key |key| has been // removed. This won't get called if the callback was removed as a result of // a call to RemoteCallbackMap::Unregister. virtual void OnRemoteCallbackRemoved(const K& key) = 0; }; // Register a callback interface and associate it with the given key. // Registering will automatically start tracking for death notifications in // case the remote process hosting the Binder dies. In such a case, the Binder // is automatically removed from the map. // // An optional |delegate| can be passed which will be assocated with the given // key/value pair. |delegate| must outlive this map. bool Register(const K& key, const android::sp<V>& callback, Delegate* delegate = nullptr); // Unregisters a previously registered callback with the given key. Returns // false if |key| doesn't exist. bool Unregister(const K& key); // Returns the callback associated with the given key. Returns NULL if |key| // doesn't exist. android::sp<V> Get(const K& key); // Removes the callback associated with the given key from the map and returns // the value. Returns NULL if the key doesn't exists. android::sp<V> Remove(const K& key); // Clear the contents of the map. void Clear(); private: class CallbackDeathRecipient : public android::IBinder::DeathRecipient { public: CallbackDeathRecipient( const K& key, const android::sp<V>& callback, RemoteCallbackMap<K, V>* owner, Delegate* delegate); android::sp<V> get_callback() const { return callback_; } // android::IBinder::DeathRecipient override: void binderDied(const android::wp<android::IBinder>& who) override; private: K key_; android::sp<V> callback_; RemoteCallbackMap<K, V>* owner_; // weak Delegate* delegate_; // weak }; // Typedef for internal map container. using CallbackMap = std::unordered_map<K, android::sp<CallbackDeathRecipient>>; bool UnregisterInternal(typename CallbackMap::iterator iter); std::mutex map_lock_; CallbackMap map_; DISALLOW_COPY_AND_ASSIGN(RemoteCallbackMap); }; // Template Implementation details below // ======================================================== using android::IBinder; using android::IInterface; using android::sp; using android::wp; using std::lock_guard; using std::mutex; template<typename K, typename V> RemoteCallbackMap<K, V>::~RemoteCallbackMap() { Clear(); } template<typename K, typename V> bool RemoteCallbackMap<K, V>::Register( const K& key, const sp<V>& callback, Delegate* delegate) { lock_guard<mutex> lock(map_lock_); if (map_.find(key) != map_.end()) { VLOG(1) << "Callback map already contains key"; return false; } sp<CallbackDeathRecipient> dr( new CallbackDeathRecipient(key, callback, this, delegate)); sp<IBinder> binder = IInterface::asBinder(callback.get()); if (binder->linkToDeath(dr) != android::NO_ERROR) { LOG(ERROR) << "Failed to link death recipient to binder"; return false; } map_[key] = dr; VLOG(2) << "Callback successfully registered with map"; return true; } template<typename K, typename V> bool RemoteCallbackMap<K, V>::Unregister(const K& key) { lock_guard<mutex> lock(map_lock_); auto iter = map_.find(key); if (iter == map_.end()) { VLOG(1) << "Callback with given key not found"; return false; } return UnregisterInternal(iter); } template<typename K, typename V> sp<V> RemoteCallbackMap<K, V>::Get(const K& key) { lock_guard<mutex> lock(map_lock_); auto iter = map_.find(key); if (iter == map_.end()) return nullptr; return iter->second; } template<typename K, typename V> sp<V> RemoteCallbackMap<K, V>::Remove(const K& key) { lock_guard<mutex> lock(map_lock_); auto iter = map_.find(key); if (iter == map_.end()) return nullptr; sp<V> val = iter->second->get_callback(); UnregisterInternal(iter); return val; } template<typename K, typename V> void RemoteCallbackMap<K, V>::Clear() { lock_guard<mutex> lock(map_lock_); for (auto iter = map_.begin(); iter != map_.end();) UnregisterInternal(iter++); } template<typename K, typename V> bool RemoteCallbackMap<K, V>::UnregisterInternal( typename CallbackMap::iterator iter) { sp<CallbackDeathRecipient> dr = iter->second; map_.erase(iter); if (IInterface::asBinder(dr->get_callback().get())->unlinkToDeath(dr) != android::NO_ERROR) { LOG(ERROR) << "Failed to unlink death recipient from binder"; // We removed the entry from |map_| but unlinkToDeath failed. There isn't // really much we can do here other than deleting the binder and returning // an error. return false; } VLOG(2) << "Callback successfully removed from map"; return true; } template<typename K, typename V> RemoteCallbackMap<K, V>::CallbackDeathRecipient::CallbackDeathRecipient( const K& key, const sp<V>& callback, RemoteCallbackMap<K, V>* owner, Delegate* delegate) : key_(key), callback_(callback), owner_(owner), delegate_(delegate) { CHECK(callback_.get()); } template<typename K, typename V> void RemoteCallbackMap<K, V>::CallbackDeathRecipient::binderDied( const wp<IBinder>& who) { VLOG(1) << "Received binderDied"; sp<IBinder> binder = IInterface::asBinder(callback_.get()); CHECK(who.unsafe_get() == binder.get()); // Remove the callback but no need to call unlinkToDeath. { lock_guard<mutex> lock(owner_->map_lock_); auto iter = owner_->map_.find(key_); CHECK(iter != owner_->map_.end()); owner_->map_.erase(iter); } VLOG(1) << "Callback from dead process unregistered; notifying delegate"; // Notify delegate. if (delegate_) delegate_->OnRemoteCallbackRemoved(key_); } } // namespace binder } // namespace ipc system/service/uuid.h +20 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <array> #include <string> #include <base/hash.h> #include "hardware/bluetooth.h" namespace bluetooth { Loading Loading @@ -72,3 +74,21 @@ class UUID { }; } // namespace bluetooth // Custom std::hash specialization so that bluetooth::UUID can be used as a key // in std::unordered_map. namespace std { template<> struct hash<bluetooth::UUID> { std::size_t operator()(const bluetooth::UUID& key) const { // Compute individual hash values for each byte and then combine them using // XOR and bitshifting. const auto& uuid_bytes = key.GetFullBigEndian(); return base::SuperFastHash(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size()); } }; } // namespace std Loading
system/service/ipc/binder/remote_callback_list.h +17 −13 Original line number Diff line number Diff line Loading @@ -17,8 +17,8 @@ #pragma once #include <functional> #include <map> #include <mutex> #include <unordered_map> #include <base/logging.h> #include <base/macros.h> Loading Loading @@ -69,12 +69,12 @@ class RemoteCallbackList final { private: class CallbackDeathRecipient : public android::IBinder::DeathRecipient { public: explicit CallbackDeathRecipient(const android::sp<T>& callback, CallbackDeathRecipient(const android::sp<T>& callback, RemoteCallbackList* owner); android::sp<T> get_callback() const { return callback_; } // android::DeathRecipient override: // android::IBinder::DeathRecipient override: void binderDied(const android::wp<android::IBinder>& who) override; private: Loading @@ -84,7 +84,7 @@ class RemoteCallbackList final { // Typedef for internal map container. This keeps track of a given Binder and // a death receiver associated with it. using CallbackMap = std::map<android::sp<android::IBinder>, using CallbackMap = std::unordered_map<android::IBinder*, android::sp<CallbackDeathRecipient>>; bool UnregisterInternal(typename CallbackMap::iterator iter); Loading Loading @@ -115,7 +115,7 @@ bool RemoteCallbackList<T>::Register(const sp<T>& callback) { std::lock_guard<std::mutex> lock(map_lock_); sp<IBinder> binder = IInterface::asBinder(callback.get()); if (callbacks_.find(binder) != callbacks_.end()) { if (callbacks_.find(binder.get()) != callbacks_.end()) { VLOG(1) << "Callback list already contains given callback"; return false; } Loading @@ -127,9 +127,9 @@ bool RemoteCallbackList<T>::Register(const sp<T>& callback) { return false; } callbacks_[binder] = dr; callbacks_[binder.get()] = dr; VLOG(1) << "Callback successfully registered"; VLOG(2) << "Callback successfully registered with list"; return true; } Loading @@ -139,9 +139,9 @@ bool RemoteCallbackList<T>::Unregister(const sp<T>& callback) { std::lock_guard<std::mutex> lock(map_lock_); sp<IBinder> binder = IInterface::asBinder(callback.get()); auto iter = callbacks_.find(binder); auto iter = callbacks_.find(binder.get()); if (iter == callbacks_.end()) { VLOG(1) << "Given callback not registered"; VLOG(2) << "Given callback not registered with this list"; return false; } Loading @@ -164,10 +164,14 @@ bool RemoteCallbackList<T>::UnregisterInternal( if (IInterface::asBinder(dr->get_callback().get())->unlinkToDeath(dr) != android::NO_ERROR) { LOG(ERROR) << "Failed to unlink death recipient from binder"; // We removed the entry from |map_| but unlinkToDeath failed. There isn't // really much we can do here other than deleting the binder and returning // an error. return false; } VLOG(1) << "Callback successfully unregistered"; VLOG(2) << "Callback successfully removed from list"; return true; } Loading @@ -192,7 +196,7 @@ void RemoteCallbackList<T>::CallbackDeathRecipient::binderDied( // Remove the callback but no need to call unlinkToDeath. std::lock_guard<std::mutex> lock(owner_->map_lock_); auto iter = owner_->callbacks_.find(binder); auto iter = owner_->callbacks_.find(binder.get()); CHECK(iter != owner_->callbacks_.end()); owner_->callbacks_.erase(iter); Loading
system/service/ipc/binder/remote_callback_map.h 0 → 100644 +260 −0 Original line number Diff line number Diff line // // Copyright (C) 2015 Google, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #pragma once #include <mutex> #include <unordered_map> #include <base/logging.h> #include <base/macros.h> #include <binder/IBinder.h> #include <binder/IInterface.h> namespace ipc { namespace binder { // A map of remote interfaces where the value type "V" must inherit from // android::IInterface. This is just like RemoteCallbackList except it provides // a key-value mapping. // // TODO(armansito): We should make this class non-final and the template // interface abstract, so that code that depends on this can be unit tested // against a mock version of this class. template<typename K, typename V> class RemoteCallbackMap final { public: RemoteCallbackMap() = default; ~RemoteCallbackMap(); // The Delegate interface is used to notify when a registered callback is // removed from the map as a result of the death of the remote process that // owns the registered callback. class Delegate { public: virtual ~Delegate() = default; // Called when a remote callback associated with the key |key| has been // removed. This won't get called if the callback was removed as a result of // a call to RemoteCallbackMap::Unregister. virtual void OnRemoteCallbackRemoved(const K& key) = 0; }; // Register a callback interface and associate it with the given key. // Registering will automatically start tracking for death notifications in // case the remote process hosting the Binder dies. In such a case, the Binder // is automatically removed from the map. // // An optional |delegate| can be passed which will be assocated with the given // key/value pair. |delegate| must outlive this map. bool Register(const K& key, const android::sp<V>& callback, Delegate* delegate = nullptr); // Unregisters a previously registered callback with the given key. Returns // false if |key| doesn't exist. bool Unregister(const K& key); // Returns the callback associated with the given key. Returns NULL if |key| // doesn't exist. android::sp<V> Get(const K& key); // Removes the callback associated with the given key from the map and returns // the value. Returns NULL if the key doesn't exists. android::sp<V> Remove(const K& key); // Clear the contents of the map. void Clear(); private: class CallbackDeathRecipient : public android::IBinder::DeathRecipient { public: CallbackDeathRecipient( const K& key, const android::sp<V>& callback, RemoteCallbackMap<K, V>* owner, Delegate* delegate); android::sp<V> get_callback() const { return callback_; } // android::IBinder::DeathRecipient override: void binderDied(const android::wp<android::IBinder>& who) override; private: K key_; android::sp<V> callback_; RemoteCallbackMap<K, V>* owner_; // weak Delegate* delegate_; // weak }; // Typedef for internal map container. using CallbackMap = std::unordered_map<K, android::sp<CallbackDeathRecipient>>; bool UnregisterInternal(typename CallbackMap::iterator iter); std::mutex map_lock_; CallbackMap map_; DISALLOW_COPY_AND_ASSIGN(RemoteCallbackMap); }; // Template Implementation details below // ======================================================== using android::IBinder; using android::IInterface; using android::sp; using android::wp; using std::lock_guard; using std::mutex; template<typename K, typename V> RemoteCallbackMap<K, V>::~RemoteCallbackMap() { Clear(); } template<typename K, typename V> bool RemoteCallbackMap<K, V>::Register( const K& key, const sp<V>& callback, Delegate* delegate) { lock_guard<mutex> lock(map_lock_); if (map_.find(key) != map_.end()) { VLOG(1) << "Callback map already contains key"; return false; } sp<CallbackDeathRecipient> dr( new CallbackDeathRecipient(key, callback, this, delegate)); sp<IBinder> binder = IInterface::asBinder(callback.get()); if (binder->linkToDeath(dr) != android::NO_ERROR) { LOG(ERROR) << "Failed to link death recipient to binder"; return false; } map_[key] = dr; VLOG(2) << "Callback successfully registered with map"; return true; } template<typename K, typename V> bool RemoteCallbackMap<K, V>::Unregister(const K& key) { lock_guard<mutex> lock(map_lock_); auto iter = map_.find(key); if (iter == map_.end()) { VLOG(1) << "Callback with given key not found"; return false; } return UnregisterInternal(iter); } template<typename K, typename V> sp<V> RemoteCallbackMap<K, V>::Get(const K& key) { lock_guard<mutex> lock(map_lock_); auto iter = map_.find(key); if (iter == map_.end()) return nullptr; return iter->second; } template<typename K, typename V> sp<V> RemoteCallbackMap<K, V>::Remove(const K& key) { lock_guard<mutex> lock(map_lock_); auto iter = map_.find(key); if (iter == map_.end()) return nullptr; sp<V> val = iter->second->get_callback(); UnregisterInternal(iter); return val; } template<typename K, typename V> void RemoteCallbackMap<K, V>::Clear() { lock_guard<mutex> lock(map_lock_); for (auto iter = map_.begin(); iter != map_.end();) UnregisterInternal(iter++); } template<typename K, typename V> bool RemoteCallbackMap<K, V>::UnregisterInternal( typename CallbackMap::iterator iter) { sp<CallbackDeathRecipient> dr = iter->second; map_.erase(iter); if (IInterface::asBinder(dr->get_callback().get())->unlinkToDeath(dr) != android::NO_ERROR) { LOG(ERROR) << "Failed to unlink death recipient from binder"; // We removed the entry from |map_| but unlinkToDeath failed. There isn't // really much we can do here other than deleting the binder and returning // an error. return false; } VLOG(2) << "Callback successfully removed from map"; return true; } template<typename K, typename V> RemoteCallbackMap<K, V>::CallbackDeathRecipient::CallbackDeathRecipient( const K& key, const sp<V>& callback, RemoteCallbackMap<K, V>* owner, Delegate* delegate) : key_(key), callback_(callback), owner_(owner), delegate_(delegate) { CHECK(callback_.get()); } template<typename K, typename V> void RemoteCallbackMap<K, V>::CallbackDeathRecipient::binderDied( const wp<IBinder>& who) { VLOG(1) << "Received binderDied"; sp<IBinder> binder = IInterface::asBinder(callback_.get()); CHECK(who.unsafe_get() == binder.get()); // Remove the callback but no need to call unlinkToDeath. { lock_guard<mutex> lock(owner_->map_lock_); auto iter = owner_->map_.find(key_); CHECK(iter != owner_->map_.end()); owner_->map_.erase(iter); } VLOG(1) << "Callback from dead process unregistered; notifying delegate"; // Notify delegate. if (delegate_) delegate_->OnRemoteCallbackRemoved(key_); } } // namespace binder } // namespace ipc
system/service/uuid.h +20 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <array> #include <string> #include <base/hash.h> #include "hardware/bluetooth.h" namespace bluetooth { Loading Loading @@ -72,3 +74,21 @@ class UUID { }; } // namespace bluetooth // Custom std::hash specialization so that bluetooth::UUID can be used as a key // in std::unordered_map. namespace std { template<> struct hash<bluetooth::UUID> { std::size_t operator()(const bluetooth::UUID& key) const { // Compute individual hash values for each byte and then combine them using // XOR and bitshifting. const auto& uuid_bytes = key.GetFullBigEndian(); return base::SuperFastHash(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size()); } }; } // namespace std