Home | History | Annotate | Download | only in binder
      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