Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 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 | #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 | |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 25 | using DeathRecipient = ::android::IBinder::DeathRecipient; |
| 26 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 27 | using ::android::IBinder; |
| 28 | using ::android::Parcel; |
| 29 | using ::android::sp; |
| 30 | using ::android::String16; |
| 31 | using ::android::wp; |
| 32 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 33 | namespace ABBinderTag { |
| 34 | |
| 35 | static const void* kId = "ABBinder"; |
| 36 | static void* kValue = static_cast<void*>(new bool{true}); |
Steven Moreland | 9496895 | 2018-09-05 14:42:59 -0700 | [diff] [blame^] | 37 | void clean(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */}; |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 38 | |
| 39 | static void attach(const sp<IBinder>& binder) { |
Steven Moreland | 9496895 | 2018-09-05 14:42:59 -0700 | [diff] [blame^] | 40 | binder->attachObject(kId, kValue, nullptr /*cookie*/, clean); |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 41 | } |
| 42 | static bool has(const sp<IBinder>& binder) { |
| 43 | return binder != nullptr && binder->findObject(kId) == kValue; |
| 44 | } |
| 45 | |
| 46 | } // namespace ABBinderTag |
| 47 | |
Steven Moreland | 9496895 | 2018-09-05 14:42:59 -0700 | [diff] [blame^] | 48 | namespace ABpBinderTag { |
| 49 | |
| 50 | static std::mutex gLock; |
| 51 | static const void* kId = "ABpBinder"; |
| 52 | struct Value { |
| 53 | wp<ABpBinder> binder; |
| 54 | }; |
| 55 | void clean(const void* id, void* obj, void* cookie) { |
| 56 | CHECK(id == kId) << id << " " << obj << " " << cookie; |
| 57 | |
| 58 | delete static_cast<Value*>(obj); |
| 59 | }; |
| 60 | |
| 61 | } // namespace ABpBinderTag |
| 62 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 63 | AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {} |
| 64 | AIBinder::~AIBinder() {} |
| 65 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 66 | bool AIBinder::associateClass(const AIBinder_Class* clazz) { |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 67 | using ::android::String8; |
| 68 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 69 | if (clazz == nullptr) return false; |
| 70 | if (mClazz == clazz) return true; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 71 | |
| 72 | String8 newDescriptor(clazz->getInterfaceDescriptor()); |
| 73 | |
| 74 | if (mClazz != nullptr) { |
| 75 | String8 currentDescriptor(mClazz->getInterfaceDescriptor()); |
| 76 | if (newDescriptor == currentDescriptor) { |
| 77 | LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor |
| 78 | << "' match during associateClass, but they are different class objects. " |
| 79 | "Class descriptor collision?"; |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 80 | } else { |
| 81 | LOG(ERROR) << __func__ |
| 82 | << ": Class cannot be associated on object which already has a class. " |
| 83 | "Trying to associate to '" |
| 84 | << newDescriptor.c_str() << "' but already set to '" |
| 85 | << currentDescriptor.c_str() << "'."; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 86 | } |
| 87 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 88 | // always a failure because we know mClazz != clazz |
| 89 | return false; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 90 | } |
| 91 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 92 | CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor |
| 93 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 94 | String8 descriptor(getBinder()->getInterfaceDescriptor()); |
| 95 | if (descriptor != newDescriptor) { |
| 96 | LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str() |
| 97 | << "' but descriptor is actually '" << descriptor.c_str() << "'."; |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 98 | return false; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 99 | } |
| 100 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 101 | // if this is a local object, it's not one known to libbinder_ndk |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 102 | mClazz = clazz; |
| 103 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 104 | return true; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData) |
| 108 | : AIBinder(clazz), BBinder(), mUserData(userData) { |
| 109 | CHECK(clazz != nullptr); |
| 110 | } |
| 111 | ABBinder::~ABBinder() { |
| 112 | getClass()->onDestroy(mUserData); |
| 113 | } |
| 114 | |
| 115 | const String16& ABBinder::getInterfaceDescriptor() const { |
| 116 | return getClass()->getInterfaceDescriptor(); |
| 117 | } |
| 118 | |
| 119 | binder_status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply, |
| 120 | binder_flags_t flags) { |
| 121 | if (isUserCommand(code)) { |
| 122 | if (!data.checkInterface(this)) { |
| 123 | return EX_ILLEGAL_STATE; |
| 124 | } |
| 125 | |
| 126 | const AParcel in = AParcel::readOnly(this, &data); |
| 127 | AParcel out = AParcel(this, reply, false /*owns*/); |
| 128 | |
| 129 | return getClass()->onTransact(this, code, &in, &out); |
| 130 | } else { |
| 131 | return BBinder::onTransact(code, data, reply, flags); |
| 132 | } |
| 133 | } |
| 134 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 135 | ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder) |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 136 | : AIBinder(nullptr /*clazz*/), BpRefBase(binder) { |
| 137 | CHECK(binder != nullptr); |
| 138 | } |
| 139 | ABpBinder::~ABpBinder() {} |
| 140 | |
Steven Moreland | 9496895 | 2018-09-05 14:42:59 -0700 | [diff] [blame^] | 141 | void ABpBinder::onLastStrongRef(const void* id) { |
| 142 | { |
| 143 | std::lock_guard<std::mutex> lock(ABpBinderTag::gLock); |
| 144 | // Since ABpBinder is OBJECT_LIFETIME_WEAK, we must remove this weak reference in order for |
| 145 | // the ABpBinder to be deleted. Since a strong reference to this ABpBinder object should no |
| 146 | // longer be able to exist at the time of this method call, there is no longer a need to |
| 147 | // recover it. |
| 148 | |
| 149 | ABpBinderTag::Value* value = |
| 150 | static_cast<ABpBinderTag::Value*>(remote()->findObject(ABpBinderTag::kId)); |
| 151 | if (value != nullptr) { |
| 152 | value->binder = nullptr; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | BpRefBase::onLastStrongRef(id); |
| 157 | } |
| 158 | |
| 159 | sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(const ::android::sp<::android::IBinder>& binder) { |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 160 | if (binder == nullptr) { |
| 161 | return nullptr; |
| 162 | } |
| 163 | if (ABBinderTag::has(binder)) { |
| 164 | return static_cast<ABBinder*>(binder.get()); |
| 165 | } |
Steven Moreland | 9496895 | 2018-09-05 14:42:59 -0700 | [diff] [blame^] | 166 | |
| 167 | // The following code ensures that for a given binder object (remote or local), if it is not an |
| 168 | // ABBinder then at most one ABpBinder object exists in a given process representing it. |
| 169 | std::lock_guard<std::mutex> lock(ABpBinderTag::gLock); |
| 170 | |
| 171 | ABpBinderTag::Value* value = |
| 172 | static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId)); |
| 173 | if (value == nullptr) { |
| 174 | value = new ABpBinderTag::Value; |
| 175 | binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value), nullptr /*cookie*/, |
| 176 | ABpBinderTag::clean); |
| 177 | } |
| 178 | |
| 179 | sp<ABpBinder> ret = value->binder.promote(); |
| 180 | if (ret == nullptr) { |
| 181 | ret = new ABpBinder(binder); |
| 182 | value->binder = ret; |
| 183 | } |
| 184 | |
| 185 | return ret; |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 186 | } |
| 187 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 188 | struct AIBinder_Weak { |
| 189 | wp<AIBinder> binder; |
| 190 | }; |
| 191 | AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) { |
Steven Moreland | 5ccb70f | 2018-09-04 16:30:21 -0700 | [diff] [blame] | 192 | if (binder == nullptr) { |
| 193 | return nullptr; |
| 194 | } |
| 195 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 196 | return new AIBinder_Weak{wp<AIBinder>(binder)}; |
| 197 | } |
Steven Moreland | 5ccb70f | 2018-09-04 16:30:21 -0700 | [diff] [blame] | 198 | void AIBinder_Weak_delete(AIBinder_Weak** weakBinder) { |
| 199 | if (weakBinder == nullptr) { |
| 200 | return; |
| 201 | } |
| 202 | |
| 203 | delete *weakBinder; |
| 204 | *weakBinder = nullptr; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 205 | } |
| 206 | AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) { |
Steven Moreland | 5ccb70f | 2018-09-04 16:30:21 -0700 | [diff] [blame] | 207 | if (weakBinder == nullptr) { |
| 208 | return nullptr; |
| 209 | } |
| 210 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 211 | sp<AIBinder> binder = weakBinder->binder.promote(); |
| 212 | AIBinder_incStrong(binder.get()); |
| 213 | return binder.get(); |
| 214 | } |
| 215 | |
| 216 | AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate, |
| 217 | AIBinder_Class_onDestroy onDestroy, |
| 218 | AIBinder_Class_onTransact onTransact) |
| 219 | : onCreate(onCreate), |
| 220 | onDestroy(onDestroy), |
| 221 | onTransact(onTransact), |
| 222 | mInterfaceDescriptor(interfaceDescriptor) {} |
| 223 | |
| 224 | AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor, |
| 225 | AIBinder_Class_onCreate onCreate, |
| 226 | AIBinder_Class_onDestroy onDestroy, |
| 227 | AIBinder_Class_onTransact onTransact) { |
| 228 | if (interfaceDescriptor == nullptr || onCreate == nullptr || onDestroy == nullptr || |
| 229 | onTransact == nullptr) { |
| 230 | return nullptr; |
| 231 | } |
| 232 | |
| 233 | return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact); |
| 234 | } |
| 235 | |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 236 | void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) { |
| 237 | CHECK(who == mWho); |
| 238 | |
| 239 | mOnDied(mCookie); |
| 240 | mWho = nullptr; |
| 241 | } |
| 242 | |
| 243 | AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied) |
| 244 | : mOnDied(onDied) { |
| 245 | CHECK(onDied != nullptr); |
| 246 | } |
| 247 | |
| 248 | binder_status_t AIBinder_DeathRecipient::linkToDeath(AIBinder* binder, void* cookie) { |
| 249 | CHECK(binder != nullptr); |
| 250 | |
| 251 | std::lock_guard<std::mutex> l(mDeathRecipientsMutex); |
| 252 | |
| 253 | sp<TransferDeathRecipient> recipient = |
| 254 | new TransferDeathRecipient(binder->getBinder(), cookie, mOnDied); |
| 255 | |
| 256 | binder_status_t status = binder->getBinder()->linkToDeath(recipient, cookie, 0 /*flags*/); |
| 257 | if (status != EX_NONE) { |
| 258 | return status; |
| 259 | } |
| 260 | |
| 261 | mDeathRecipients.push_back(recipient); |
| 262 | return EX_NONE; |
| 263 | } |
| 264 | |
| 265 | binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* cookie) { |
| 266 | CHECK(binder != nullptr); |
| 267 | |
| 268 | std::lock_guard<std::mutex> l(mDeathRecipientsMutex); |
| 269 | |
| 270 | for (auto it = mDeathRecipients.rbegin(); it != mDeathRecipients.rend(); ++it) { |
| 271 | sp<TransferDeathRecipient> recipient = *it; |
| 272 | |
| 273 | if (recipient->getCookie() == cookie && |
| 274 | |
| 275 | recipient->getWho() == binder->getBinder()) { |
| 276 | mDeathRecipients.erase(it.base() - 1); |
| 277 | |
| 278 | binder_status_t status = |
| 279 | binder->getBinder()->unlinkToDeath(recipient, cookie, 0 /*flags*/); |
| 280 | if (status != EX_NONE) { |
| 281 | LOG(ERROR) << __func__ |
| 282 | << ": removed reference to death recipient but unlink failed."; |
| 283 | } |
| 284 | return status; |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | return -ENOENT; |
| 289 | } |
| 290 | |
| 291 | // start of C-API methods |
| 292 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 293 | AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) { |
| 294 | if (clazz == nullptr) { |
| 295 | LOG(ERROR) << __func__ << ": Must provide class to construct local binder."; |
| 296 | return nullptr; |
| 297 | } |
| 298 | |
| 299 | void* userData = clazz->onCreate(args); |
| 300 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 301 | sp<AIBinder> ret = new ABBinder(clazz, userData); |
| 302 | ABBinderTag::attach(ret->getBinder()); |
| 303 | |
| 304 | AIBinder_incStrong(ret.get()); |
| 305 | return ret.get(); |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 306 | } |
| 307 | |
Steven Moreland | 5ea54da | 2018-09-04 13:29:55 -0700 | [diff] [blame] | 308 | bool AIBinder_isRemote(const AIBinder* binder) { |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 309 | if (binder == nullptr) { |
| 310 | return true; |
| 311 | } |
| 312 | |
| 313 | return binder->isRemote(); |
| 314 | } |
| 315 | |
Steven Moreland | 65867d7 | 2018-09-04 14:22:26 -0700 | [diff] [blame] | 316 | bool AIBinder_isAlive(const AIBinder* binder) { |
| 317 | if (binder == nullptr) { |
| 318 | return false; |
| 319 | } |
| 320 | |
| 321 | return const_cast<AIBinder*>(binder)->getBinder()->isBinderAlive(); |
| 322 | } |
| 323 | |
| 324 | binder_status_t AIBinder_ping(AIBinder* binder) { |
| 325 | if (binder == nullptr) { |
| 326 | return EX_NULL_POINTER; |
| 327 | } |
| 328 | |
| 329 | return binder->getBinder()->pingBinder(); |
| 330 | } |
| 331 | |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 332 | binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, |
| 333 | void* cookie) { |
| 334 | if (binder == nullptr || recipient == nullptr) { |
| 335 | LOG(ERROR) << __func__ << ": Must provide binder and recipient."; |
| 336 | return EX_NULL_POINTER; |
| 337 | } |
| 338 | |
| 339 | return recipient->linkToDeath(binder, cookie); |
| 340 | } |
| 341 | |
| 342 | binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, |
| 343 | void* cookie) { |
| 344 | if (binder == nullptr || recipient == nullptr) { |
| 345 | LOG(ERROR) << __func__ << ": Must provide binder and recipient."; |
| 346 | return EX_NULL_POINTER; |
| 347 | } |
| 348 | |
| 349 | return recipient->unlinkToDeath(binder, cookie); |
| 350 | } |
| 351 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 352 | void AIBinder_incStrong(AIBinder* binder) { |
| 353 | if (binder == nullptr) { |
| 354 | LOG(ERROR) << __func__ << ": on null binder"; |
| 355 | return; |
| 356 | } |
| 357 | |
| 358 | binder->incStrong(nullptr); |
| 359 | } |
| 360 | void AIBinder_decStrong(AIBinder* binder) { |
| 361 | if (binder == nullptr) { |
| 362 | LOG(ERROR) << __func__ << ": on null binder"; |
| 363 | return; |
| 364 | } |
| 365 | |
| 366 | binder->decStrong(nullptr); |
| 367 | } |
| 368 | int32_t AIBinder_debugGetRefCount(AIBinder* binder) { |
| 369 | if (binder == nullptr) { |
| 370 | LOG(ERROR) << __func__ << ": on null binder"; |
| 371 | return -1; |
| 372 | } |
| 373 | |
| 374 | return binder->getStrongCount(); |
| 375 | } |
| 376 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 377 | bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) { |
| 378 | if (binder == nullptr) { |
| 379 | return false; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 380 | } |
| 381 | |
Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 382 | return binder->associateClass(clazz); |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 383 | } |
| 384 | |
| 385 | const AIBinder_Class* AIBinder_getClass(AIBinder* binder) { |
| 386 | if (binder == nullptr) { |
| 387 | return nullptr; |
| 388 | } |
| 389 | |
| 390 | return binder->getClass(); |
| 391 | } |
| 392 | |
| 393 | void* AIBinder_getUserData(AIBinder* binder) { |
| 394 | if (binder == nullptr) { |
| 395 | return nullptr; |
| 396 | } |
| 397 | |
| 398 | ABBinder* bBinder = binder->asABBinder(); |
| 399 | if (bBinder == nullptr) { |
| 400 | return nullptr; |
| 401 | } |
| 402 | |
| 403 | return bBinder->getUserData(); |
| 404 | } |
| 405 | |
| 406 | binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) { |
| 407 | if (binder == nullptr || in == nullptr) { |
| 408 | LOG(ERROR) << __func__ << ": requires non-null parameters."; |
| 409 | return EX_NULL_POINTER; |
| 410 | } |
| 411 | const AIBinder_Class* clazz = binder->getClass(); |
| 412 | if (clazz == nullptr) { |
| 413 | LOG(ERROR) << __func__ |
| 414 | << ": Class must be defined for a remote binder transaction. See " |
| 415 | "AIBinder_associateClass."; |
| 416 | return EX_ILLEGAL_STATE; |
| 417 | } |
| 418 | |
Steven Moreland | 3527c2e | 2018-09-05 17:07:14 -0700 | [diff] [blame] | 419 | if (!binder->isRemote()) { |
Steven Moreland | 74521c8 | 2018-09-07 14:50:40 -0700 | [diff] [blame] | 420 | LOG(WARNING) << "A binder object at " << binder |
| 421 | << " is being transacted on, however, this object is in the same process as " |
| 422 | "its proxy. Transacting with this binder is expensive compared to just " |
| 423 | "calling the corresponding functionality in the same process."; |
Steven Moreland | 3527c2e | 2018-09-05 17:07:14 -0700 | [diff] [blame] | 424 | } |
| 425 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 426 | *in = new AParcel(binder); |
| 427 | binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor()); |
| 428 | if (status != EX_NONE) { |
| 429 | delete *in; |
| 430 | *in = nullptr; |
| 431 | } |
| 432 | |
| 433 | return status; |
| 434 | } |
| 435 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 436 | binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in, |
| 437 | AParcel** out, binder_flags_t flags) { |
| 438 | if (in == nullptr) { |
| 439 | LOG(ERROR) << __func__ << ": requires non-null in parameter"; |
| 440 | return EX_NULL_POINTER; |
| 441 | } |
| 442 | |
Steven Moreland | caa776c | 2018-09-04 13:48:11 -0700 | [diff] [blame] | 443 | using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 444 | // This object is the input to the transaction. This function takes ownership of it and deletes |
| 445 | // it. |
Steven Moreland | caa776c | 2018-09-04 13:48:11 -0700 | [diff] [blame] | 446 | AutoParcelDestroyer forIn(in, AParcel_delete); |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 447 | |
| 448 | if (!isUserCommand(code)) { |
| 449 | LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK."; |
| 450 | return EX_UNSUPPORTED_OPERATION; |
| 451 | } |
| 452 | |
| 453 | if ((flags & ~FLAG_ONEWAY) != 0) { |
| 454 | LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags; |
| 455 | return EX_ILLEGAL_ARGUMENT; |
| 456 | } |
| 457 | |
| 458 | if (binder == nullptr || *in == nullptr || out == nullptr) { |
| 459 | LOG(ERROR) << __func__ << ": requires non-null parameters."; |
| 460 | return EX_NULL_POINTER; |
| 461 | } |
| 462 | |
| 463 | if ((*in)->getBinder() != binder) { |
| 464 | LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder |
| 465 | << " but called with " << (*in)->getBinder(); |
| 466 | return EX_ILLEGAL_STATE; |
| 467 | } |
| 468 | |
| 469 | *out = new AParcel(binder); |
| 470 | |
| 471 | binder_status_t parcelStatus = |
| 472 | binder->getBinder()->transact(code, *(*in)->operator->(), (*out)->operator->(), flags); |
| 473 | |
| 474 | if (parcelStatus != EX_NONE) { |
| 475 | delete *out; |
| 476 | *out = nullptr; |
| 477 | } |
| 478 | |
| 479 | return parcelStatus; |
| 480 | } |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 481 | |
| 482 | AIBinder_DeathRecipient* AIBinder_DeathRecipient_new( |
| 483 | AIBinder_DeathRecipient_onBinderDied onBinderDied) { |
| 484 | if (onBinderDied == nullptr) { |
| 485 | LOG(ERROR) << __func__ << ": requires non-null onBinderDied parameter."; |
| 486 | return nullptr; |
| 487 | } |
| 488 | return new AIBinder_DeathRecipient(onBinderDied); |
| 489 | } |
| 490 | |
| 491 | void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient) { |
| 492 | if (recipient == nullptr) { |
| 493 | return; |
| 494 | } |
| 495 | |
| 496 | delete *recipient; |
| 497 | *recipient = nullptr; |
| 498 | } |