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 <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 28 namespace ipc { 29 namespace 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. 52 template <typename T> 53 class 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 101 using android::IBinder; 102 using android::IInterface; 103 using android::sp; 104 using android::wp; 105 106 template <typename T> 107 RemoteCallbackList<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 113 template <typename T> 114 bool 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 137 template <typename T> 138 bool 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 151 template <typename T> 152 void 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 158 template <typename T> 159 bool 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 179 template <typename T> 180 RemoteCallbackList<T>::CallbackDeathRecipient::CallbackDeathRecipient( 181 const sp<T>& callback, RemoteCallbackList<T>* owner) 182 : callback_(callback), owner_(owner) { 183 CHECK(callback_.get()); 184 CHECK(owner_); 185 } 186 187 template <typename T> 188 void RemoteCallbackList<T>::CallbackDeathRecipient::binderDied( 189 const wp<IBinder>& who) { 190 VLOG(1) << "Received binderDied"; 191 192 sp<IBinder> binder = IInterface::asBinder(callback_.get()); 193 CHECK(who.unsafe_get() == binder.get()); 194 195 // Remove the callback but no need to call unlinkToDeath. 196 std::lock_guard<std::mutex> lock(owner_->map_lock_); 197 auto iter = owner_->callbacks_.find(binder.get()); 198 CHECK(iter != owner_->callbacks_.end()); 199 owner_->callbacks_.erase(iter); 200 201 VLOG(1) << "Callback from dead process unregistered"; 202 } 203 204 } // namespace binder 205 } // namespace ipc 206