blob: b7f56364dd55401b28f869dcaa9c546ca473bbcf [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
Steven Moreland65867d72018-09-04 14:22:26 -0700205bool AIBinder_isAlive(const AIBinder* binder) {
206 if (binder == nullptr) {
207 return false;
208 }
209
210 return const_cast<AIBinder*>(binder)->getBinder()->isBinderAlive();
211}
212
213binder_status_t AIBinder_ping(AIBinder* binder) {
214 if (binder == nullptr) {
215 return EX_NULL_POINTER;
216 }
217
218 return binder->getBinder()->pingBinder();
219}
220
Steven Moreland2e87adc2018-08-20 19:47:00 -0700221void AIBinder_incStrong(AIBinder* binder) {
222 if (binder == nullptr) {
223 LOG(ERROR) << __func__ << ": on null binder";
224 return;
225 }
226
227 binder->incStrong(nullptr);
228}
229void AIBinder_decStrong(AIBinder* binder) {
230 if (binder == nullptr) {
231 LOG(ERROR) << __func__ << ": on null binder";
232 return;
233 }
234
235 binder->decStrong(nullptr);
236}
237int32_t AIBinder_debugGetRefCount(AIBinder* binder) {
238 if (binder == nullptr) {
239 LOG(ERROR) << __func__ << ": on null binder";
240 return -1;
241 }
242
243 return binder->getStrongCount();
244}
245
Steven Moreland71cddc32018-08-30 23:39:22 -0700246bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) {
247 if (binder == nullptr) {
248 return false;
Steven Moreland2e87adc2018-08-20 19:47:00 -0700249 }
250
Steven Moreland71cddc32018-08-30 23:39:22 -0700251 return binder->associateClass(clazz);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700252}
253
254const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
255 if (binder == nullptr) {
256 return nullptr;
257 }
258
259 return binder->getClass();
260}
261
262void* AIBinder_getUserData(AIBinder* binder) {
263 if (binder == nullptr) {
264 return nullptr;
265 }
266
267 ABBinder* bBinder = binder->asABBinder();
268 if (bBinder == nullptr) {
269 return nullptr;
270 }
271
272 return bBinder->getUserData();
273}
274
275binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
276 if (binder == nullptr || in == nullptr) {
277 LOG(ERROR) << __func__ << ": requires non-null parameters.";
278 return EX_NULL_POINTER;
279 }
280 const AIBinder_Class* clazz = binder->getClass();
281 if (clazz == nullptr) {
282 LOG(ERROR) << __func__
283 << ": Class must be defined for a remote binder transaction. See "
284 "AIBinder_associateClass.";
285 return EX_ILLEGAL_STATE;
286 }
287
Steven Moreland3527c2e2018-09-05 17:07:14 -0700288 if (!binder->isRemote()) {
289 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.";
290 }
291
Steven Moreland2e87adc2018-08-20 19:47:00 -0700292 *in = new AParcel(binder);
293 binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
294 if (status != EX_NONE) {
295 delete *in;
296 *in = nullptr;
297 }
298
299 return status;
300}
301
Steven Moreland2e87adc2018-08-20 19:47:00 -0700302binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
303 AParcel** out, binder_flags_t flags) {
304 if (in == nullptr) {
305 LOG(ERROR) << __func__ << ": requires non-null in parameter";
306 return EX_NULL_POINTER;
307 }
308
Steven Morelandcaa776c2018-09-04 13:48:11 -0700309 using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
Steven Moreland2e87adc2018-08-20 19:47:00 -0700310 // This object is the input to the transaction. This function takes ownership of it and deletes
311 // it.
Steven Morelandcaa776c2018-09-04 13:48:11 -0700312 AutoParcelDestroyer forIn(in, AParcel_delete);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700313
314 if (!isUserCommand(code)) {
315 LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
316 return EX_UNSUPPORTED_OPERATION;
317 }
318
319 if ((flags & ~FLAG_ONEWAY) != 0) {
320 LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
321 return EX_ILLEGAL_ARGUMENT;
322 }
323
324 if (binder == nullptr || *in == nullptr || out == nullptr) {
325 LOG(ERROR) << __func__ << ": requires non-null parameters.";
326 return EX_NULL_POINTER;
327 }
328
329 if ((*in)->getBinder() != binder) {
330 LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
331 << " but called with " << (*in)->getBinder();
332 return EX_ILLEGAL_STATE;
333 }
334
335 *out = new AParcel(binder);
336
337 binder_status_t parcelStatus =
338 binder->getBinder()->transact(code, *(*in)->operator->(), (*out)->operator->(), flags);
339
340 if (parcelStatus != EX_NONE) {
341 delete *out;
342 *out = nullptr;
343 }
344
345 return parcelStatus;
346}