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