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