• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 defined(__BIONIC__)
34 #define API_LEVEL_AT_LEAST(sdk_api_level) __builtin_available(android sdk_api_level, *)
35 #elif defined(TRUSTY_USERSPACE)
36 // TODO(b/349936395): set to true for Trusty
37 #define API_LEVEL_AT_LEAST(sdk_api_level) (false)
38 #else
39 #define API_LEVEL_AT_LEAST(sdk_api_level) (true)
40 #endif  // __BIONIC__
41 
42 #if __has_include(<android/binder_shell.h>)
43 #include <android/binder_shell.h>
44 #define HAS_BINDER_SHELL_COMMAND
45 #endif  //_has_include
46 
47 #include <assert.h>
48 
49 #include <memory>
50 #include <mutex>
51 
52 namespace ndk {
53 
54 /**
55  * Binder analog to using std::shared_ptr for an internally held refcount.
56  *
57  * ref must be called at least one time during the lifetime of this object. The recommended way to
58  * construct this object is with SharedRefBase::make.
59  *
60  * If you need a "this" shared reference analogous to shared_from_this, use this->ref().
61  */
62 class SharedRefBase {
63    public:
SharedRefBase()64     SharedRefBase() {}
~SharedRefBase()65     virtual ~SharedRefBase() {
66         std::call_once(mFlagThis, [&]() {
67             __assert(__FILE__, __LINE__, "SharedRefBase: no ref created during lifetime");
68         });
69 
70         if (ref() != nullptr) {
71             __assert(__FILE__, __LINE__,
72                      "SharedRefBase: destructed but still able to lock weak_ptr. Is this object "
73                      "double-owned?");
74         }
75     }
76 
77     /**
78      * A shared_ptr must be held to this object when this is called. This must be called once during
79      * the lifetime of this object.
80      */
ref()81     std::shared_ptr<SharedRefBase> ref() {
82         std::shared_ptr<SharedRefBase> thiz = mThis.lock();
83 
84         std::call_once(mFlagThis, [&]() { mThis = thiz = std::shared_ptr<SharedRefBase>(this); });
85 
86         return thiz;
87     }
88 
89     /**
90      * Convenience method for a ref (see above) which automatically casts to the desired child type.
91      */
92     template <typename CHILD>
ref()93     std::shared_ptr<CHILD> ref() {
94         return std::static_pointer_cast<CHILD>(ref());
95     }
96 
97     /**
98      * Convenience method for making an object directly with a reference.
99      */
100     template <class T, class... Args>
make(Args &&...args)101     static std::shared_ptr<T> make(Args&&... args) {
102 #pragma clang diagnostic push
103 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
104         T* t = new T(std::forward<Args>(args)...);
105 #pragma clang diagnostic pop
106         // warning: Potential leak of memory pointed to by 't' [clang-analyzer-unix.Malloc]
107         return t->template ref<T>();  // NOLINT(clang-analyzer-unix.Malloc)
108     }
109 
delete(void * p)110     static void operator delete(void* p) { std::free(p); }
111 
112     // Once minSdkVersion is 30, we are guaranteed to be building with the
113     // Android 11 AIDL compiler which supports the SharedRefBase::make API.
114     //
115     // Use 'SharedRefBase::make<T>(...)' to make. SharedRefBase has implicit
116     // ownership. Making this operator private to avoid double-ownership.
117 #if !defined(__ANDROID_API__) || __ANDROID_API__ >= 30 || defined(__ANDROID_APEX__)
118    private:
119 #else
120     [[deprecated("Prefer SharedRefBase::make<T>(...) if possible.")]]
121 #endif
new(size_t s)122     static void* operator new(size_t s) { return std::malloc(s); }
123 
124    private:
125     std::once_flag mFlagThis;
126     std::weak_ptr<SharedRefBase> mThis;
127 };
128 
129 /**
130  * wrapper analog to IInterface
131  */
132 class ICInterface : public SharedRefBase {
133    public:
ICInterface()134     ICInterface() {}
~ICInterface()135     virtual ~ICInterface() {}
136 
137     /**
138      * This either returns the single existing implementation or creates a new implementation.
139      */
140     virtual SpAIBinder asBinder() = 0;
141 
142     /**
143      * Returns whether this interface is in a remote process. If it cannot be determined locally,
144      * this will be checked using AIBinder_isRemote.
145      */
146     virtual bool isRemote() = 0;
147 
148     /**
149      * Dumps information about the interface. By default, dumps nothing.
150      *
151      * This method is not given ownership of the FD.
152      */
153     virtual inline binder_status_t dump(int fd, const char** args, uint32_t numArgs);
154 
155 #ifdef HAS_BINDER_SHELL_COMMAND
156     /**
157      * Process shell commands. By default, does nothing.
158      */
159     virtual inline binder_status_t handleShellCommand(int in, int out, int err, const char** argv,
160                                                       uint32_t argc);
161 #endif
162 
163     /**
164      * Interprets this binder as this underlying interface if this has stored an ICInterface in the
165      * binder's user data.
166      *
167      * This does not do type checking and should only be used when the binder is known to originate
168      * from ICInterface. Most likely, you want to use I*::fromBinder.
169      */
170     static inline std::shared_ptr<ICInterface> asInterface(AIBinder* binder);
171 
172     /**
173      * Helper method to create a class
174      */
175     static inline AIBinder_Class* defineClass(const char* interfaceDescriptor,
176                                               AIBinder_Class_onTransact onTransact,
177                                               const char** codeToFunction, size_t functionCount);
178 
179     static inline AIBinder_Class* defineClass(const char* interfaceDescriptor,
180                                               AIBinder_Class_onTransact onTransact);
181 
182    private:
183     class ICInterfaceData {
184        public:
185         std::shared_ptr<ICInterface> interface;
186 
187         static inline std::shared_ptr<ICInterface> getInterface(AIBinder* binder);
188 
189         static inline void* onCreate(void* args);
190         static inline void onDestroy(void* userData);
191         static inline binder_status_t onDump(AIBinder* binder, int fd, const char** args,
192                                              uint32_t numArgs);
193 
194 #ifdef HAS_BINDER_SHELL_COMMAND
195         static inline binder_status_t handleShellCommand(AIBinder* binder, int in, int out, int err,
196                                                          const char** argv, uint32_t argc);
197 #endif
198     };
199 };
200 
201 /**
202  * implementation of IInterface for server (n = native)
203  */
204 template <typename INTERFACE>
205 class BnCInterface : public INTERFACE {
206    public:
BnCInterface()207     BnCInterface() {}
~BnCInterface()208     virtual ~BnCInterface() {}
209 
210     SpAIBinder asBinder() override final;
211 
isRemote()212     bool isRemote() override final { return false; }
213 
makeServiceName(std::string_view instance)214     static std::string makeServiceName(std::string_view instance) {
215         return INTERFACE::descriptor + ("/" + std::string(instance));
216     }
217 
218    protected:
219     /**
220      * This function should only be called by asBinder. Otherwise, there is a possibility of
221      * multiple AIBinder* objects being created for the same instance of an object.
222      */
223     virtual SpAIBinder createBinder() = 0;
224 
225    private:
226     std::mutex mMutex;  // for asBinder
227     ScopedAIBinder_Weak mWeakBinder;
228 };
229 
230 /**
231  * implementation of IInterface for client (p = proxy)
232  */
233 template <typename INTERFACE>
234 class BpCInterface : public INTERFACE {
235    public:
BpCInterface(const SpAIBinder & binder)236     explicit BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
~BpCInterface()237     virtual ~BpCInterface() {}
238 
239     SpAIBinder asBinder() override final;
240 
asBinderReference()241     const SpAIBinder& asBinderReference() { return mBinder; }
242 
isRemote()243     bool isRemote() override final { return AIBinder_isRemote(mBinder.get()); }
244 
dump(int fd,const char ** args,uint32_t numArgs)245     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override {
246         return AIBinder_dump(asBinder().get(), fd, args, numArgs);
247     }
248 
249    private:
250     SpAIBinder mBinder;
251 };
252 
253 // END OF CLASS DECLARATIONS
254 
dump(int,const char **,uint32_t)255 binder_status_t ICInterface::dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/) {
256     return STATUS_OK;
257 }
258 
259 #ifdef HAS_BINDER_SHELL_COMMAND
handleShellCommand(int,int,int,const char **,uint32_t)260 binder_status_t ICInterface::handleShellCommand(int /*in*/, int /*out*/, int /*err*/,
261                                                 const char** /*argv*/, uint32_t /*argc*/) {
262     return STATUS_OK;
263 }
264 #endif
265 
asInterface(AIBinder * binder)266 std::shared_ptr<ICInterface> ICInterface::asInterface(AIBinder* binder) {
267     return ICInterfaceData::getInterface(binder);
268 }
269 
defineClass(const char * interfaceDescriptor,AIBinder_Class_onTransact onTransact)270 AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
271                                          AIBinder_Class_onTransact onTransact) {
272 
273     return defineClass(interfaceDescriptor, onTransact, nullptr, 0);
274 }
275 
defineClass(const char * interfaceDescriptor,AIBinder_Class_onTransact onTransact,const char ** codeToFunction,size_t functionCount)276 AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
277                                          AIBinder_Class_onTransact onTransact,
278                                          const char** codeToFunction, size_t functionCount) {
279     AIBinder_Class* clazz = AIBinder_Class_define(interfaceDescriptor, ICInterfaceData::onCreate,
280                                                   ICInterfaceData::onDestroy, onTransact);
281     if (clazz == nullptr) {
282         return nullptr;
283     }
284 
285     // We can't know if these methods are overridden by a subclass interface, so we must register
286     // ourselves. The defaults are harmless.
287     AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump);
288 #ifdef HAS_BINDER_SHELL_COMMAND
289 #ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__
290     if (__builtin_available(android 30, *)) {
291 #else
292     if (__ANDROID_API__ >= 30) {
293 #endif
294         AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand);
295     }
296 #endif
297 
298 #if defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) || __ANDROID_API__ >= 36
299     if (API_LEVEL_AT_LEAST(36)) {
300         if (codeToFunction != nullptr) {
301             AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, codeToFunction,
302                                                                functionCount);
303         }
304     }
305 #else
306     (void)codeToFunction;
307     (void)functionCount;
308 #endif  // defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) || __ANDROID_API__ >= 36
309     return clazz;
310 }
311 
312 std::shared_ptr<ICInterface> ICInterface::ICInterfaceData::getInterface(AIBinder* binder) {
313     if (binder == nullptr) return nullptr;
314 
315     void* userData = AIBinder_getUserData(binder);
316     if (userData == nullptr) return nullptr;
317 
318     return static_cast<ICInterfaceData*>(userData)->interface;
319 }
320 
321 void* ICInterface::ICInterfaceData::onCreate(void* args) {
322     std::shared_ptr<ICInterface> interface = static_cast<ICInterface*>(args)->ref<ICInterface>();
323     ICInterfaceData* data = new ICInterfaceData{interface};
324     return static_cast<void*>(data);
325 }
326 
327 void ICInterface::ICInterfaceData::onDestroy(void* userData) {
328     delete static_cast<ICInterfaceData*>(userData);
329 }
330 
331 binder_status_t ICInterface::ICInterfaceData::onDump(AIBinder* binder, int fd, const char** args,
332                                                      uint32_t numArgs) {
333     std::shared_ptr<ICInterface> interface = getInterface(binder);
334     if (interface != nullptr) {
335         return interface->dump(fd, args, numArgs);
336     }
337     return STATUS_DEAD_OBJECT;
338 }
339 
340 #ifdef HAS_BINDER_SHELL_COMMAND
341 binder_status_t ICInterface::ICInterfaceData::handleShellCommand(AIBinder* binder, int in, int out,
342                                                                  int err, const char** argv,
343                                                                  uint32_t argc) {
344     std::shared_ptr<ICInterface> interface = getInterface(binder);
345     if (interface != nullptr) {
346         return interface->handleShellCommand(in, out, err, argv, argc);
347     }
348     return STATUS_DEAD_OBJECT;
349 }
350 #endif
351 
352 template <typename INTERFACE>
353 SpAIBinder BnCInterface<INTERFACE>::asBinder() {
354     std::lock_guard<std::mutex> l(mMutex);
355 
356     SpAIBinder binder;
357     if (mWeakBinder.get() != nullptr) {
358         binder.set(AIBinder_Weak_promote(mWeakBinder.get()));
359     }
360     if (binder.get() == nullptr) {
361         binder = createBinder();
362         mWeakBinder.set(AIBinder_Weak_new(binder.get()));
363     }
364 
365     return binder;
366 }
367 
368 template <typename INTERFACE>
369 SpAIBinder BpCInterface<INTERFACE>::asBinder() {
370     return mBinder;
371 }
372 
373 }  // namespace ndk
374 
375 // Once minSdkVersion is 30, we are guaranteed to be building with the
376 // Android 11 AIDL compiler which supports the SharedRefBase::make API.
377 #if !defined(__ANDROID_API__) || __ANDROID_API__ >= 30 || defined(__ANDROID_APEX__)
378 namespace ndk::internal {
379 template <typename T, typename = void>
380 struct is_complete_type : std::false_type {};
381 
382 template <typename T>
383 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
384 }  // namespace ndk::internal
385 
386 namespace std {
387 
388 // Define `SharedRefBase` specific versions of `std::make_shared` and
389 // `std::make_unique` to block people from using them. Using them to allocate
390 // `ndk::SharedRefBase` objects results in double ownership. Use
391 // `ndk::SharedRefBase::make<T>(...)` instead.
392 //
393 // Note: We exclude incomplete types because `std::is_base_of` is undefined in
394 // that case.
395 
396 template <typename T, typename... Args,
397           std::enable_if_t<ndk::internal::is_complete_type<T>::value, bool> = true,
398           std::enable_if_t<std::is_base_of<ndk::SharedRefBase, T>::value, bool> = true>
399 shared_ptr<T> make_shared(Args...) {  // SEE COMMENT ABOVE.
400     static_assert(!std::is_base_of<ndk::SharedRefBase, T>::value);
401 }
402 
403 template <typename T, typename... Args,
404           std::enable_if_t<ndk::internal::is_complete_type<T>::value, bool> = true,
405           std::enable_if_t<std::is_base_of<ndk::SharedRefBase, T>::value, bool> = true>
406 unique_ptr<T> make_unique(Args...) {  // SEE COMMENT ABOVE.
407     static_assert(!std::is_base_of<ndk::SharedRefBase, T>::value);
408 }
409 
410 }  // namespace std
411 #endif
412 
413 /** @} */
414