Home | History | Annotate | Download | only in binder
      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,
     64                 const android::sp<V>& callback,
     65                 Delegate* delegate = nullptr);
     66 
     67   // Unregisters a previously registered callback with the given key. Returns
     68   // false if |key| doesn't exist.
     69   bool Unregister(const K& key);
     70 
     71   // Returns the callback associated with the given key. Returns NULL if |key|
     72   // doesn't exist.
     73   android::sp<V> Get(const K& key);
     74 
     75   // Removes the callback associated with the given key from the map and returns
     76   // the value. Returns NULL if the key doesn't exists.
     77   android::sp<V> Remove(const K& key);
     78 
     79   // Clear the contents of the map.
     80   void Clear();
     81 
     82  private:
     83   class CallbackDeathRecipient : public android::IBinder::DeathRecipient {
     84    public:
     85     CallbackDeathRecipient(
     86         const K& key,
     87         const android::sp<V>& callback,
     88         RemoteCallbackMap<K, V>* owner,
     89         Delegate* delegate);
     90 
     91     android::sp<V> get_callback() const { return callback_; }
     92 
     93     // android::IBinder::DeathRecipient override:
     94     void binderDied(const android::wp<android::IBinder>& who) override;
     95 
     96    private:
     97     K key_;
     98     android::sp<V> callback_;
     99     RemoteCallbackMap<K, V>* owner_;  // weak
    100     Delegate* delegate_;  // weak
    101   };
    102 
    103   // Typedef for internal map container.
    104   using CallbackMap =
    105       std::unordered_map<K, android::sp<CallbackDeathRecipient>>;
    106 
    107   bool UnregisterInternal(typename CallbackMap::iterator iter);
    108 
    109   std::mutex map_lock_;
    110   CallbackMap map_;
    111 
    112   DISALLOW_COPY_AND_ASSIGN(RemoteCallbackMap);
    113 };
    114 
    115 // Template Implementation details below
    116 // ========================================================
    117 
    118 using android::IBinder;
    119 using android::IInterface;
    120 using android::sp;
    121 using android::wp;
    122 using std::lock_guard;
    123 using std::mutex;
    124 
    125 template<typename K, typename V>
    126 RemoteCallbackMap<K, V>::~RemoteCallbackMap() {
    127   Clear();
    128 }
    129 
    130 template<typename K, typename V>
    131 bool RemoteCallbackMap<K, V>::Register(
    132     const K& key,
    133     const sp<V>& callback,
    134     Delegate* delegate) {
    135   lock_guard<mutex> lock(map_lock_);
    136 
    137   if (map_.find(key) != map_.end()) {
    138     VLOG(1) << "Callback map already contains key";
    139     return false;
    140   }
    141 
    142   sp<CallbackDeathRecipient> dr(
    143       new CallbackDeathRecipient(key, callback, this, delegate));
    144   sp<IBinder> binder = IInterface::asBinder(callback.get());
    145   if (binder->linkToDeath(dr) != android::NO_ERROR) {
    146     LOG(ERROR) << "Failed to link death recipient to binder";
    147     return false;
    148   }
    149 
    150   map_[key] = dr;
    151 
    152   VLOG(2) << "Callback successfully registered with map";
    153 
    154   return true;
    155 }
    156 
    157 template<typename K, typename V>
    158 bool RemoteCallbackMap<K, V>::Unregister(const K& key) {
    159   lock_guard<mutex> lock(map_lock_);
    160 
    161   auto iter = map_.find(key);
    162   if (iter == map_.end()) {
    163     VLOG(1) << "Callback with given key not found";
    164     return false;
    165   }
    166 
    167   return UnregisterInternal(iter);
    168 }
    169 
    170 template<typename K, typename V>
    171 sp<V> RemoteCallbackMap<K, V>::Get(const K& key) {
    172   lock_guard<mutex> lock(map_lock_);
    173 
    174   auto iter = map_.find(key);
    175   if (iter == map_.end())
    176     return nullptr;
    177 
    178   return iter->second->get_callback();
    179 }
    180 
    181 template<typename K, typename V>
    182 sp<V> RemoteCallbackMap<K, V>::Remove(const K& key) {
    183   lock_guard<mutex> lock(map_lock_);
    184 
    185   auto iter = map_.find(key);
    186   if (iter == map_.end())
    187     return nullptr;
    188 
    189   sp<V> val = iter->second->get_callback();
    190   UnregisterInternal(iter);
    191 
    192   return val;
    193 }
    194 template<typename K, typename V>
    195 void RemoteCallbackMap<K, V>::Clear() {
    196   lock_guard<mutex> lock(map_lock_);
    197 
    198   for (auto iter = map_.begin(); iter != map_.end();)
    199     UnregisterInternal(iter++);
    200 }
    201 
    202 template<typename K, typename V>
    203 bool RemoteCallbackMap<K, V>::UnregisterInternal(
    204     typename CallbackMap::iterator iter) {
    205   sp<CallbackDeathRecipient> dr = iter->second;
    206   map_.erase(iter);
    207 
    208   if (IInterface::asBinder(dr->get_callback().get())->unlinkToDeath(dr) !=
    209       android::NO_ERROR) {
    210     LOG(ERROR) << "Failed to unlink death recipient from binder";
    211 
    212     // We removed the entry from |map_| but unlinkToDeath failed. There isn't
    213     // really much we can do here other than deleting the binder and returning
    214     // an error.
    215     return false;
    216   }
    217 
    218   VLOG(2) << "Callback successfully removed from map";
    219 
    220   return true;
    221 }
    222 
    223 template<typename K, typename V>
    224 RemoteCallbackMap<K, V>::CallbackDeathRecipient::CallbackDeathRecipient(
    225     const K& key,
    226     const sp<V>& callback,
    227     RemoteCallbackMap<K, V>* owner,
    228     Delegate* delegate)
    229     : key_(key),
    230       callback_(callback),
    231       owner_(owner),
    232       delegate_(delegate) {
    233   CHECK(callback_.get());
    234 }
    235 
    236 template<typename K, typename V>
    237 void RemoteCallbackMap<K, V>::CallbackDeathRecipient::binderDied(
    238     const wp<IBinder>& who) {
    239   VLOG(1) << "Received binderDied";
    240 
    241   sp<IBinder> binder = IInterface::asBinder(callback_.get());
    242   CHECK(who.unsafe_get() == binder.get());
    243 
    244   // Remove the callback but no need to call unlinkToDeath.
    245   {
    246     lock_guard<mutex> lock(owner_->map_lock_);
    247     auto iter = owner_->map_.find(key_);
    248     CHECK(iter != owner_->map_.end());
    249     owner_->map_.erase(iter);
    250   }
    251 
    252   VLOG(1) << "Callback from dead process unregistered; notifying delegate";
    253 
    254   // Notify delegate.
    255   if (delegate_)
    256     delegate_->OnRemoteCallbackRemoved(key_);
    257 }
    258 
    259 }  // namespace binder
    260 }  // namespace ipc
    261