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 <functional> 20#include <mutex> 21#include <unordered_map> 22 23#include <base/logging.h> 24#include <base/macros.h> 25#include <binder/IBinder.h> 26#include <binder/IInterface.h> 27 28namespace ipc { 29namespace binder { 30 31// Takes care of the grunt work of maintaining a list of remote interfaces, 32// typically for the use of performing registered callbacks from a remote 33// service. This is a native equivalent of the the android.os.RemoteCallbackList 34// Java class. The type "T" must inherit from android::IInterface. 35// 36// TODO(armansito): We need to unit test this class. Right now it's defined as a 37// simple template interface over the native libbinder types directly and we 38// can't compile libbinder for host unless the Binder kernel module is enabled 39// on the system. Figure out whether to: 40// 1) write the Binder test-code in a new target-only executable; 41// 2) conditionally compile into the host-native test suite if the Binder 42// module is built; 43// 3) provide a test-only static library that re-defines the libbinder 44// classes as mocks. 45// (See http://b/23386387) 46// 47// TODO(armansito): We should make this class non-final and the template 48// interface abstract, so that code that depends on this can be unit tested 49// against a mock version of this class. 50// 51// TODO(armansito): Consider submitting this class to frameworks/native/binder. 52template<typename T> 53class RemoteCallbackList final { 54 public: 55 RemoteCallbackList() = default; 56 ~RemoteCallbackList(); 57 58 // Register and unregister a callback interface. Registering will 59 // automatically start tracking for death notifications in case the remote 60 // process hosting the Binder dies. In such a case, the Binder is 61 // automatically removed from the list. 62 bool Register(const android::sp<T>& callback); 63 bool Unregister(const android::sp<T>& callback); 64 65 // Calls the given function on each of the contained callbacks. The internal 66 // mutex is locked for the duration of the iteration. 67 void ForEach(const std::function<void(T*)>& callback); 68 69 private: 70 class CallbackDeathRecipient : public android::IBinder::DeathRecipient { 71 public: 72 CallbackDeathRecipient(const android::sp<T>& callback, 73 RemoteCallbackList* owner); 74 75 android::sp<T> get_callback() const { return callback_; } 76 77 // android::IBinder::DeathRecipient override: 78 void binderDied(const android::wp<android::IBinder>& who) override; 79 80 private: 81 android::sp<T> callback_; 82 RemoteCallbackList<T>* owner_; // weak 83 }; 84 85 // Typedef for internal map container. This keeps track of a given Binder and 86 // a death receiver associated with it. 87 using CallbackMap = std::unordered_map<android::IBinder*, 88 android::sp<CallbackDeathRecipient>>; 89 90 bool UnregisterInternal(typename CallbackMap::iterator iter); 91 92 std::mutex map_lock_; 93 CallbackMap callbacks_; 94 95 DISALLOW_COPY_AND_ASSIGN(RemoteCallbackList); 96}; 97 98// Template Implementation details below 99// ======================================================== 100 101using android::IBinder; 102using android::IInterface; 103using android::sp; 104using android::wp; 105 106template<typename T> 107RemoteCallbackList<T>::~RemoteCallbackList() { 108 std::lock_guard<std::mutex> lock(map_lock_); 109 for (auto iter = callbacks_.begin(); iter != callbacks_.end(); ++iter) 110 UnregisterInternal(iter); 111} 112 113template<typename T> 114bool RemoteCallbackList<T>::Register(const sp<T>& callback) { 115 std::lock_guard<std::mutex> lock(map_lock_); 116 117 sp<IBinder> binder = IInterface::asBinder(callback.get()); 118 if (callbacks_.find(binder.get()) != callbacks_.end()) { 119 VLOG(1) << "Callback list already contains given callback"; 120 return false; 121 } 122 123 sp<CallbackDeathRecipient> dr(new CallbackDeathRecipient(callback, this)); 124 125 if (binder->linkToDeath(dr) != android::NO_ERROR) { 126 LOG(ERROR) << "Failed to link death recipient to binder"; 127 return false; 128 } 129 130 callbacks_[binder.get()] = dr; 131 132 VLOG(2) << "Callback successfully registered with list"; 133 134 return true; 135} 136 137template<typename T> 138bool RemoteCallbackList<T>::Unregister(const sp<T>& callback) { 139 std::lock_guard<std::mutex> lock(map_lock_); 140 141 sp<IBinder> binder = IInterface::asBinder(callback.get()); 142 auto iter = callbacks_.find(binder.get()); 143 if (iter == callbacks_.end()) { 144 VLOG(2) << "Given callback not registered with this list"; 145 return false; 146 } 147 148 return UnregisterInternal(iter); 149} 150 151template<typename T> 152void RemoteCallbackList<T>::ForEach(const std::function<void(T*)>& callback) { 153 std::lock_guard<std::mutex> lock(map_lock_); 154 for (const auto& iter : callbacks_) 155 callback(iter.second->get_callback().get()); 156} 157 158template<typename T> 159bool RemoteCallbackList<T>::UnregisterInternal( 160 typename CallbackMap::iterator iter) { 161 sp<CallbackDeathRecipient> dr = iter->second; 162 callbacks_.erase(iter); 163 164 if (IInterface::asBinder(dr->get_callback().get())->unlinkToDeath(dr) != 165 android::NO_ERROR) { 166 LOG(ERROR) << "Failed to unlink death recipient from binder"; 167 168 // We removed the entry from |map_| but unlinkToDeath failed. There isn't 169 // really much we can do here other than deleting the binder and returning 170 // an error. 171 return false; 172 } 173 174 VLOG(2) << "Callback successfully removed from list"; 175 176 return true; 177} 178 179template<typename T> 180RemoteCallbackList<T>::CallbackDeathRecipient::CallbackDeathRecipient( 181 const sp<T>& callback, 182 RemoteCallbackList<T>* owner) 183 : callback_(callback), 184 owner_(owner) { 185 CHECK(callback_.get()); 186 CHECK(owner_); 187} 188 189template<typename T> 190void RemoteCallbackList<T>::CallbackDeathRecipient::binderDied( 191 const wp<IBinder>& who) { 192 VLOG(1) << "Received binderDied"; 193 194 sp<IBinder> binder = IInterface::asBinder(callback_.get()); 195 CHECK(who.unsafe_get() == binder.get()); 196 197 // Remove the callback but no need to call unlinkToDeath. 198 std::lock_guard<std::mutex> lock(owner_->map_lock_); 199 auto iter = owner_->callbacks_.find(binder.get()); 200 CHECK(iter != owner_->callbacks_.end()); 201 owner_->callbacks_.erase(iter); 202 203 VLOG(1) << "Callback from dead process unregistered"; 204} 205 206} // namespace binder 207} // namespace ipc 208