1 /*
2 * Copyright (C) 2018 The Android Open Source Project
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 /**
18 * @addtogroup NdkBinder
19 * @{
20 */
21
22 /**
23 * @file binder_interface_utils.h
24 * @brief This provides common C++ classes for common operations and as base classes for C++
25 * interfaces.
26 */
27
28 #pragma once
29
30 #include <android/binder_auto_utils.h>
31 #include <android/binder_ibinder.h>
32
33 #if __has_include(<android/binder_shell.h>)
34 #include <android/binder_shell.h>
35 #define HAS_BINDER_SHELL_COMMAND
36 #endif //_has_include
37
38 #include <assert.h>
39
40 #include <memory>
41 #include <mutex>
42
43 namespace ndk {
44
45 /**
46 * analog using std::shared_ptr for internally held refcount
47 *
48 * ref must be called at least one time during the lifetime of this object. The recommended way to
49 * construct this object is with SharedRefBase::make.
50 */
51 class SharedRefBase {
52 public:
SharedRefBase()53 SharedRefBase() {}
~SharedRefBase()54 virtual ~SharedRefBase() {
55 std::call_once(mFlagThis, [&]() {
56 __assert(__FILE__, __LINE__, "SharedRefBase: no ref created during lifetime");
57 });
58 }
59
60 /**
61 * A shared_ptr must be held to this object when this is called. This must be called once during
62 * the lifetime of this object.
63 */
ref()64 std::shared_ptr<SharedRefBase> ref() {
65 std::shared_ptr<SharedRefBase> thiz = mThis.lock();
66
67 std::call_once(mFlagThis, [&]() { mThis = thiz = std::shared_ptr<SharedRefBase>(this); });
68
69 return thiz;
70 }
71
72 /**
73 * Convenience method for a ref (see above) which automatically casts to the desired child type.
74 */
75 template <typename CHILD>
ref()76 std::shared_ptr<CHILD> ref() {
77 return std::static_pointer_cast<CHILD>(ref());
78 }
79
80 /**
81 * Convenience method for making an object directly with a reference.
82 */
83 template <class T, class... Args>
make(Args &&...args)84 static std::shared_ptr<T> make(Args&&... args) {
85 T* t = new T(std::forward<Args>(args)...);
86 return t->template ref<T>();
87 }
88
delete(void * p)89 static void operator delete(void* p) { std::free(p); }
90
91 private:
92 std::once_flag mFlagThis;
93 std::weak_ptr<SharedRefBase> mThis;
94
95 // Use 'SharedRefBase::make<T>(...)' to make. SharedRefBase has implicit
96 // ownership. Making this operator private to avoid double-ownership.
new(size_t s)97 static void* operator new(size_t s) { return std::malloc(s); }
98 };
99
100 /**
101 * wrapper analog to IInterface
102 */
103 class ICInterface : public SharedRefBase {
104 public:
ICInterface()105 ICInterface() {}
~ICInterface()106 virtual ~ICInterface() {}
107
108 /**
109 * This either returns the single existing implementation or creates a new implementation.
110 */
111 virtual SpAIBinder asBinder() = 0;
112
113 /**
114 * Returns whether this interface is in a remote process. If it cannot be determined locally,
115 * this will be checked using AIBinder_isRemote.
116 */
117 virtual bool isRemote() = 0;
118
119 /**
120 * Dumps information about the interface. By default, dumps nothing.
121 */
122 virtual inline binder_status_t dump(int fd, const char** args, uint32_t numArgs);
123
124 #ifdef HAS_BINDER_SHELL_COMMAND
125 /**
126 * Process shell commands. By default, does nothing.
127 */
128 virtual inline binder_status_t handleShellCommand(int in, int out, int err, const char** argv,
129 uint32_t argc);
130 #endif
131
132 /**
133 * Interprets this binder as this underlying interface if this has stored an ICInterface in the
134 * binder's user data.
135 *
136 * This does not do type checking and should only be used when the binder is known to originate
137 * from ICInterface. Most likely, you want to use I*::fromBinder.
138 */
139 static inline std::shared_ptr<ICInterface> asInterface(AIBinder* binder);
140
141 /**
142 * Helper method to create a class
143 */
144 static inline AIBinder_Class* defineClass(const char* interfaceDescriptor,
145 AIBinder_Class_onTransact onTransact);
146
147 private:
148 class ICInterfaceData {
149 public:
150 std::shared_ptr<ICInterface> interface;
151
152 static inline std::shared_ptr<ICInterface> getInterface(AIBinder* binder);
153
154 static inline void* onCreate(void* args);
155 static inline void onDestroy(void* userData);
156 static inline binder_status_t onDump(AIBinder* binder, int fd, const char** args,
157 uint32_t numArgs);
158
159 #ifdef HAS_BINDER_SHELL_COMMAND
160 static inline binder_status_t handleShellCommand(AIBinder* binder, int in, int out, int err,
161 const char** argv, uint32_t argc);
162 #endif
163 };
164 };
165
166 /**
167 * implementation of IInterface for server (n = native)
168 */
169 template <typename INTERFACE>
170 class BnCInterface : public INTERFACE {
171 public:
BnCInterface()172 BnCInterface() {}
~BnCInterface()173 virtual ~BnCInterface() {}
174
175 SpAIBinder asBinder() override;
176
isRemote()177 bool isRemote() override { return false; }
178
179 protected:
180 /**
181 * This function should only be called by asBinder. Otherwise, there is a possibility of
182 * multiple AIBinder* objects being created for the same instance of an object.
183 */
184 virtual SpAIBinder createBinder() = 0;
185
186 private:
187 std::mutex mMutex; // for asBinder
188 ScopedAIBinder_Weak mWeakBinder;
189 };
190
191 /**
192 * implementation of IInterface for client (p = proxy)
193 */
194 template <typename INTERFACE>
195 class BpCInterface : public INTERFACE {
196 public:
BpCInterface(const SpAIBinder & binder)197 explicit BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
~BpCInterface()198 virtual ~BpCInterface() {}
199
200 SpAIBinder asBinder() override;
201
isRemote()202 bool isRemote() override { return AIBinder_isRemote(mBinder.get()); }
203
dump(int fd,const char ** args,uint32_t numArgs)204 binder_status_t dump(int fd, const char** args, uint32_t numArgs) override {
205 return AIBinder_dump(asBinder().get(), fd, args, numArgs);
206 }
207
208 private:
209 SpAIBinder mBinder;
210 };
211
212 // END OF CLASS DECLARATIONS
213
dump(int,const char **,uint32_t)214 binder_status_t ICInterface::dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/) {
215 return STATUS_OK;
216 }
217
218 #ifdef HAS_BINDER_SHELL_COMMAND
handleShellCommand(int,int,int,const char **,uint32_t)219 binder_status_t ICInterface::handleShellCommand(int /*in*/, int /*out*/, int /*err*/,
220 const char** /*argv*/, uint32_t /*argc*/) {
221 return STATUS_OK;
222 }
223 #endif
224
asInterface(AIBinder * binder)225 std::shared_ptr<ICInterface> ICInterface::asInterface(AIBinder* binder) {
226 return ICInterfaceData::getInterface(binder);
227 }
228
defineClass(const char * interfaceDescriptor,AIBinder_Class_onTransact onTransact)229 AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
230 AIBinder_Class_onTransact onTransact) {
231 AIBinder_Class* clazz = AIBinder_Class_define(interfaceDescriptor, ICInterfaceData::onCreate,
232 ICInterfaceData::onDestroy, onTransact);
233 if (clazz == nullptr) {
234 return nullptr;
235 }
236
237 // We can't know if these methods are overridden by a subclass interface, so we must register
238 // ourselves. The defaults are harmless.
239 AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump);
240 #ifdef HAS_BINDER_SHELL_COMMAND
241 if (AIBinder_Class_setHandleShellCommand != nullptr) {
242 AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand);
243 }
244 #endif
245 return clazz;
246 }
247
getInterface(AIBinder * binder)248 std::shared_ptr<ICInterface> ICInterface::ICInterfaceData::getInterface(AIBinder* binder) {
249 if (binder == nullptr) return nullptr;
250
251 void* userData = AIBinder_getUserData(binder);
252 if (userData == nullptr) return nullptr;
253
254 return static_cast<ICInterfaceData*>(userData)->interface;
255 }
256
onCreate(void * args)257 void* ICInterface::ICInterfaceData::onCreate(void* args) {
258 std::shared_ptr<ICInterface> interface = static_cast<ICInterface*>(args)->ref<ICInterface>();
259 ICInterfaceData* data = new ICInterfaceData{interface};
260 return static_cast<void*>(data);
261 }
262
onDestroy(void * userData)263 void ICInterface::ICInterfaceData::onDestroy(void* userData) {
264 delete static_cast<ICInterfaceData*>(userData);
265 }
266
onDump(AIBinder * binder,int fd,const char ** args,uint32_t numArgs)267 binder_status_t ICInterface::ICInterfaceData::onDump(AIBinder* binder, int fd, const char** args,
268 uint32_t numArgs) {
269 std::shared_ptr<ICInterface> interface = getInterface(binder);
270 return interface->dump(fd, args, numArgs);
271 }
272
273 #ifdef HAS_BINDER_SHELL_COMMAND
handleShellCommand(AIBinder * binder,int in,int out,int err,const char ** argv,uint32_t argc)274 binder_status_t ICInterface::ICInterfaceData::handleShellCommand(AIBinder* binder, int in, int out,
275 int err, const char** argv,
276 uint32_t argc) {
277 std::shared_ptr<ICInterface> interface = getInterface(binder);
278 return interface->handleShellCommand(in, out, err, argv, argc);
279 }
280 #endif
281
282 template <typename INTERFACE>
asBinder()283 SpAIBinder BnCInterface<INTERFACE>::asBinder() {
284 std::lock_guard<std::mutex> l(mMutex);
285
286 SpAIBinder binder;
287 if (mWeakBinder.get() != nullptr) {
288 binder.set(AIBinder_Weak_promote(mWeakBinder.get()));
289 }
290 if (binder.get() == nullptr) {
291 binder = createBinder();
292 mWeakBinder.set(AIBinder_Weak_new(binder.get()));
293 }
294
295 return binder;
296 }
297
298 template <typename INTERFACE>
asBinder()299 SpAIBinder BpCInterface<INTERFACE>::asBinder() {
300 return mBinder;
301 }
302
303 } // namespace ndk
304
305 /** @} */
306