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 
get_callback()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>
~RemoteCallbackList()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>
Register(const sp<T> & callback)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>
Unregister(const sp<T> & callback)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>
ForEach(const std::function<void (T *)> & callback)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>
UnregisterInternal(typename CallbackMap::iterator iter)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>
CallbackDeathRecipient(const sp<T> & callback,RemoteCallbackList<T> * owner)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>
binderDied(const wp<IBinder> & who)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