blob: 80c64c0fc45424f33e91013da8745912f04a4bec [file] [log] [blame]
Steven Moreland2e87adc2018-08-20 19:47:00 -07001/*
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#include <android/binder_ibinder.h>
18#include "AIBinder_internal.h"
19
20#include <android/binder_status.h>
21#include "AParcel_internal.h"
22
23#include <android-base/logging.h>
24
25using ::android::IBinder;
26using ::android::Parcel;
27using ::android::sp;
28using ::android::String16;
29using ::android::wp;
30
Steven Moreland71cddc32018-08-30 23:39:22 -070031namespace ABBinderTag {
32
33static const void* kId = "ABBinder";
34static void* kValue = static_cast<void*>(new bool{true});
35void cleanId(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
36
37static void attach(const sp<IBinder>& binder) {
38 binder->attachObject(kId, kValue, nullptr /*cookie*/, cleanId);
39}
40static bool has(const sp<IBinder>& binder) {
41 return binder != nullptr && binder->findObject(kId) == kValue;
42}
43
44} // namespace ABBinderTag
45
Steven Moreland2e87adc2018-08-20 19:47:00 -070046AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
47AIBinder::~AIBinder() {}
48
Steven Moreland71cddc32018-08-30 23:39:22 -070049bool AIBinder::associateClass(const AIBinder_Class* clazz) {
Steven Moreland2e87adc2018-08-20 19:47:00 -070050 using ::android::String8;
51
Steven Moreland71cddc32018-08-30 23:39:22 -070052 if (clazz == nullptr) return false;
53 if (mClazz == clazz) return true;
Steven Moreland2e87adc2018-08-20 19:47:00 -070054
55 String8 newDescriptor(clazz->getInterfaceDescriptor());
56
57 if (mClazz != nullptr) {
58 String8 currentDescriptor(mClazz->getInterfaceDescriptor());
59 if (newDescriptor == currentDescriptor) {
60 LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
61 << "' match during associateClass, but they are different class objects. "
62 "Class descriptor collision?";
Steven Moreland71cddc32018-08-30 23:39:22 -070063 } else {
64 LOG(ERROR) << __func__
65 << ": Class cannot be associated on object which already has a class. "
66 "Trying to associate to '"
67 << newDescriptor.c_str() << "' but already set to '"
68 << currentDescriptor.c_str() << "'.";
Steven Moreland2e87adc2018-08-20 19:47:00 -070069 }
70
Steven Moreland71cddc32018-08-30 23:39:22 -070071 // always a failure because we know mClazz != clazz
72 return false;
Steven Moreland2e87adc2018-08-20 19:47:00 -070073 }
74
Steven Moreland71cddc32018-08-30 23:39:22 -070075 CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor
76
Steven Moreland2e87adc2018-08-20 19:47:00 -070077 String8 descriptor(getBinder()->getInterfaceDescriptor());
78 if (descriptor != newDescriptor) {
79 LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
80 << "' but descriptor is actually '" << descriptor.c_str() << "'.";
Steven Moreland71cddc32018-08-30 23:39:22 -070081 return false;
Steven Moreland2e87adc2018-08-20 19:47:00 -070082 }
83
Steven Moreland71cddc32018-08-30 23:39:22 -070084 // if this is a local object, it's not one known to libbinder_ndk
Steven Moreland2e87adc2018-08-20 19:47:00 -070085 mClazz = clazz;
86
Steven Moreland71cddc32018-08-30 23:39:22 -070087 return true;
Steven Moreland2e87adc2018-08-20 19:47:00 -070088}
89
90ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
91 : AIBinder(clazz), BBinder(), mUserData(userData) {
92 CHECK(clazz != nullptr);
93}
94ABBinder::~ABBinder() {
95 getClass()->onDestroy(mUserData);
96}
97
98const String16& ABBinder::getInterfaceDescriptor() const {
99 return getClass()->getInterfaceDescriptor();
100}
101
102binder_status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
103 binder_flags_t flags) {
104 if (isUserCommand(code)) {
105 if (!data.checkInterface(this)) {
106 return EX_ILLEGAL_STATE;
107 }
108
109 const AParcel in = AParcel::readOnly(this, &data);
110 AParcel out = AParcel(this, reply, false /*owns*/);
111
112 return getClass()->onTransact(this, code, &in, &out);
113 } else {
114 return BBinder::onTransact(code, data, reply, flags);
115 }
116}
117
Steven Moreland71cddc32018-08-30 23:39:22 -0700118ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
Steven Moreland2e87adc2018-08-20 19:47:00 -0700119 : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
120 CHECK(binder != nullptr);
121}
122ABpBinder::~ABpBinder() {}
123
Steven Moreland71cddc32018-08-30 23:39:22 -0700124sp<AIBinder> ABpBinder::fromBinder(const ::android::sp<::android::IBinder>& binder) {
125 if (binder == nullptr) {
126 return nullptr;
127 }
128 if (ABBinderTag::has(binder)) {
129 return static_cast<ABBinder*>(binder.get());
130 }
131 return new ABpBinder(binder);
132}
133
Steven Moreland2e87adc2018-08-20 19:47:00 -0700134struct AIBinder_Weak {
135 wp<AIBinder> binder;
136};
137AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) {
Steven Moreland5ccb70f2018-09-04 16:30:21 -0700138 if (binder == nullptr) {
139 return nullptr;
140 }
141
Steven Moreland2e87adc2018-08-20 19:47:00 -0700142 return new AIBinder_Weak{wp<AIBinder>(binder)};
143}
Steven Moreland5ccb70f2018-09-04 16:30:21 -0700144void AIBinder_Weak_delete(AIBinder_Weak** weakBinder) {
145 if (weakBinder == nullptr) {
146 return;
147 }
148
149 delete *weakBinder;
150 *weakBinder = nullptr;
Steven Moreland2e87adc2018-08-20 19:47:00 -0700151}
152AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
Steven Moreland5ccb70f2018-09-04 16:30:21 -0700153 if (weakBinder == nullptr) {
154 return nullptr;
155 }
156
Steven Moreland2e87adc2018-08-20 19:47:00 -0700157 sp<AIBinder> binder = weakBinder->binder.promote();
158 AIBinder_incStrong(binder.get());
159 return binder.get();
160}
161
162AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
163 AIBinder_Class_onDestroy onDestroy,
164 AIBinder_Class_onTransact onTransact)
165 : onCreate(onCreate),
166 onDestroy(onDestroy),
167 onTransact(onTransact),
168 mInterfaceDescriptor(interfaceDescriptor) {}
169
170AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
171 AIBinder_Class_onCreate onCreate,
172 AIBinder_Class_onDestroy onDestroy,
173 AIBinder_Class_onTransact onTransact) {
174 if (interfaceDescriptor == nullptr || onCreate == nullptr || onDestroy == nullptr ||
175 onTransact == nullptr) {
176 return nullptr;
177 }
178
179 return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
180}
181
182AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
183 if (clazz == nullptr) {
184 LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
185 return nullptr;
186 }
187
188 void* userData = clazz->onCreate(args);
189
Steven Moreland71cddc32018-08-30 23:39:22 -0700190 sp<AIBinder> ret = new ABBinder(clazz, userData);
191 ABBinderTag::attach(ret->getBinder());
192
193 AIBinder_incStrong(ret.get());
194 return ret.get();
Steven Moreland2e87adc2018-08-20 19:47:00 -0700195}
196
Steven Moreland5ea54da2018-09-04 13:29:55 -0700197bool AIBinder_isRemote(const AIBinder* binder) {
Steven Moreland2e87adc2018-08-20 19:47:00 -0700198 if (binder == nullptr) {
199 return true;
200 }
201
202 return binder->isRemote();
203}
204
205void AIBinder_incStrong(AIBinder* binder) {
206 if (binder == nullptr) {
207 LOG(ERROR) << __func__ << ": on null binder";
208 return;
209 }
210
211 binder->incStrong(nullptr);
212}
213void AIBinder_decStrong(AIBinder* binder) {
214 if (binder == nullptr) {
215 LOG(ERROR) << __func__ << ": on null binder";
216 return;
217 }
218
219 binder->decStrong(nullptr);
220}
221int32_t AIBinder_debugGetRefCount(AIBinder* binder) {
222 if (binder == nullptr) {
223 LOG(ERROR) << __func__ << ": on null binder";
224 return -1;
225 }
226
227 return binder->getStrongCount();
228}
229
Steven Moreland71cddc32018-08-30 23:39:22 -0700230bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) {
231 if (binder == nullptr) {
232 return false;
Steven Moreland2e87adc2018-08-20 19:47:00 -0700233 }
234
Steven Moreland71cddc32018-08-30 23:39:22 -0700235 return binder->associateClass(clazz);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700236}
237
238const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
239 if (binder == nullptr) {
240 return nullptr;
241 }
242
243 return binder->getClass();
244}
245
246void* AIBinder_getUserData(AIBinder* binder) {
247 if (binder == nullptr) {
248 return nullptr;
249 }
250
251 ABBinder* bBinder = binder->asABBinder();
252 if (bBinder == nullptr) {
253 return nullptr;
254 }
255
256 return bBinder->getUserData();
257}
258
259binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
260 if (binder == nullptr || in == nullptr) {
261 LOG(ERROR) << __func__ << ": requires non-null parameters.";
262 return EX_NULL_POINTER;
263 }
264 const AIBinder_Class* clazz = binder->getClass();
265 if (clazz == nullptr) {
266 LOG(ERROR) << __func__
267 << ": Class must be defined for a remote binder transaction. See "
268 "AIBinder_associateClass.";
269 return EX_ILLEGAL_STATE;
270 }
271
Steven Moreland3527c2e2018-09-05 17:07:14 -0700272 if (!binder->isRemote()) {
273 LOG(WARNING) << "A binder object at " << binder << " is being transacted on, however, this object is in the same process as its proxy. Transacting with this binder is expensive compared to just calling the corresponding functionality in the same process.";
274 }
275
Steven Moreland2e87adc2018-08-20 19:47:00 -0700276 *in = new AParcel(binder);
277 binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
278 if (status != EX_NONE) {
279 delete *in;
280 *in = nullptr;
281 }
282
283 return status;
284}
285
Steven Moreland2e87adc2018-08-20 19:47:00 -0700286binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
287 AParcel** out, binder_flags_t flags) {
288 if (in == nullptr) {
289 LOG(ERROR) << __func__ << ": requires non-null in parameter";
290 return EX_NULL_POINTER;
291 }
292
Steven Morelandcaa776c2018-09-04 13:48:11 -0700293 using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
Steven Moreland2e87adc2018-08-20 19:47:00 -0700294 // This object is the input to the transaction. This function takes ownership of it and deletes
295 // it.
Steven Morelandcaa776c2018-09-04 13:48:11 -0700296 AutoParcelDestroyer forIn(in, AParcel_delete);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700297
298 if (!isUserCommand(code)) {
299 LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
300 return EX_UNSUPPORTED_OPERATION;
301 }
302
303 if ((flags & ~FLAG_ONEWAY) != 0) {
304 LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
305 return EX_ILLEGAL_ARGUMENT;
306 }
307
308 if (binder == nullptr || *in == nullptr || out == nullptr) {
309 LOG(ERROR) << __func__ << ": requires non-null parameters.";
310 return EX_NULL_POINTER;
311 }
312
313 if ((*in)->getBinder() != binder) {
314 LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
315 << " but called with " << (*in)->getBinder();
316 return EX_ILLEGAL_STATE;
317 }
318
319 *out = new AParcel(binder);
320
321 binder_status_t parcelStatus =
322 binder->getBinder()->transact(code, *(*in)->operator->(), (*out)->operator->(), flags);
323
324 if (parcelStatus != EX_NONE) {
325 delete *out;
326 *out = nullptr;
327 }
328
329 return parcelStatus;
330}