1 /* 2 * Copyright (C) 2006 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 #define LOG_TAG "JavaBinder" 18 //#define LOG_NDEBUG 0 19 20 #include "android_util_Binder.h" 21 #include "JNIHelp.h" 22 23 #include <fcntl.h> 24 #include <stdio.h> 25 #include <sys/stat.h> 26 #include <sys/types.h> 27 #include <unistd.h> 28 29 #include <utils/Atomic.h> 30 #include <binder/IInterface.h> 31 #include <binder/IPCThreadState.h> 32 #include <utils/Log.h> 33 #include <utils/SystemClock.h> 34 #include <cutils/logger.h> 35 #include <binder/Parcel.h> 36 #include <binder/ProcessState.h> 37 #include <binder/IServiceManager.h> 38 #include <utils/threads.h> 39 40 #include <android_runtime/AndroidRuntime.h> 41 42 //#undef LOGV 43 //#define LOGV(...) fprintf(stderr, __VA_ARGS__) 44 45 using namespace android; 46 47 // ---------------------------------------------------------------------------- 48 49 static struct bindernative_offsets_t 50 { 51 // Class state. 52 jclass mClass; 53 jmethodID mExecTransact; 54 55 // Object state. 56 jfieldID mObject; 57 58 } gBinderOffsets; 59 60 // ---------------------------------------------------------------------------- 61 62 static struct binderinternal_offsets_t 63 { 64 // Class state. 65 jclass mClass; 66 jmethodID mForceGc; 67 68 } gBinderInternalOffsets; 69 70 // ---------------------------------------------------------------------------- 71 72 static struct debug_offsets_t 73 { 74 // Class state. 75 jclass mClass; 76 77 } gDebugOffsets; 78 79 // ---------------------------------------------------------------------------- 80 81 static struct weakreference_offsets_t 82 { 83 // Class state. 84 jclass mClass; 85 jmethodID mGet; 86 87 } gWeakReferenceOffsets; 88 89 static struct error_offsets_t 90 { 91 jclass mClass; 92 } gErrorOffsets; 93 94 // ---------------------------------------------------------------------------- 95 96 static struct binderproxy_offsets_t 97 { 98 // Class state. 99 jclass mClass; 100 jmethodID mConstructor; 101 jmethodID mSendDeathNotice; 102 103 // Object state. 104 jfieldID mObject; 105 jfieldID mSelf; 106 107 } gBinderProxyOffsets; 108 109 // ---------------------------------------------------------------------------- 110 111 static struct parcel_offsets_t 112 { 113 jfieldID mObject; 114 jfieldID mOwnObject; 115 } gParcelOffsets; 116 117 static struct log_offsets_t 118 { 119 // Class state. 120 jclass mClass; 121 jmethodID mLogE; 122 } gLogOffsets; 123 124 static struct file_descriptor_offsets_t 125 { 126 jclass mClass; 127 jmethodID mConstructor; 128 jfieldID mDescriptor; 129 } gFileDescriptorOffsets; 130 131 static struct parcel_file_descriptor_offsets_t 132 { 133 jclass mClass; 134 jmethodID mConstructor; 135 } gParcelFileDescriptorOffsets; 136 137 // **************************************************************************** 138 // **************************************************************************** 139 // **************************************************************************** 140 141 static volatile int32_t gNumRefsCreated = 0; 142 static volatile int32_t gNumProxyRefs = 0; 143 static volatile int32_t gNumLocalRefs = 0; 144 static volatile int32_t gNumDeathRefs = 0; 145 146 static void incRefsCreated(JNIEnv* env) 147 { 148 int old = android_atomic_inc(&gNumRefsCreated); 149 if (old == 200) { 150 android_atomic_and(0, &gNumRefsCreated); 151 env->CallStaticVoidMethod(gBinderInternalOffsets.mClass, 152 gBinderInternalOffsets.mForceGc); 153 } else { 154 LOGV("Now have %d binder ops", old); 155 } 156 } 157 158 static JavaVM* jnienv_to_javavm(JNIEnv* env) 159 { 160 JavaVM* vm; 161 return env->GetJavaVM(&vm) >= 0 ? vm : NULL; 162 } 163 164 static JNIEnv* javavm_to_jnienv(JavaVM* vm) 165 { 166 JNIEnv* env; 167 return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL; 168 } 169 170 static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) 171 { 172 env->ExceptionClear(); 173 174 jstring tagstr = env->NewStringUTF(LOG_TAG); 175 jstring msgstr = env->NewStringUTF(msg); 176 177 if ((tagstr == NULL) || (msgstr == NULL)) { 178 env->ExceptionClear(); /* assume exception (OOM?) was thrown */ 179 LOGE("Unable to call Log.e()\n"); 180 LOGE("%s", msg); 181 goto bail; 182 } 183 184 env->CallStaticIntMethod( 185 gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep); 186 if (env->ExceptionCheck()) { 187 /* attempting to log the failure has failed */ 188 LOGW("Failed trying to log exception, msg='%s'\n", msg); 189 env->ExceptionClear(); 190 } 191 192 if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { 193 /* 194 * It's an Error: Reraise the exception, detach this thread, and 195 * wait for the fireworks. Die even more blatantly after a minute 196 * if the gentler attempt doesn't do the trick. 197 * 198 * The GetJavaVM function isn't on the "approved" list of JNI calls 199 * that can be made while an exception is pending, so we want to 200 * get the VM ptr, throw the exception, and then detach the thread. 201 */ 202 JavaVM* vm = jnienv_to_javavm(env); 203 env->Throw(excep); 204 vm->DetachCurrentThread(); 205 sleep(60); 206 LOGE("Forcefully exiting"); 207 exit(1); 208 *((int *) 1) = 1; 209 } 210 211 bail: 212 /* discard local refs created for us by VM */ 213 env->DeleteLocalRef(tagstr); 214 env->DeleteLocalRef(msgstr); 215 } 216 217 class JavaBBinderHolder; 218 219 class JavaBBinder : public BBinder 220 { 221 public: 222 JavaBBinder(JNIEnv* env, jobject object) 223 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) 224 { 225 LOGV("Creating JavaBBinder %p\n", this); 226 android_atomic_inc(&gNumLocalRefs); 227 incRefsCreated(env); 228 } 229 230 bool checkSubclass(const void* subclassID) const 231 { 232 return subclassID == &gBinderOffsets; 233 } 234 235 jobject object() const 236 { 237 return mObject; 238 } 239 240 protected: 241 virtual ~JavaBBinder() 242 { 243 LOGV("Destroying JavaBBinder %p\n", this); 244 android_atomic_dec(&gNumLocalRefs); 245 JNIEnv* env = javavm_to_jnienv(mVM); 246 env->DeleteGlobalRef(mObject); 247 } 248 249 virtual status_t onTransact( 250 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) 251 { 252 JNIEnv* env = javavm_to_jnienv(mVM); 253 254 LOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); 255 256 //printf("Transact from %p to Java code sending: ", this); 257 //data.print(); 258 //printf("\n"); 259 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, 260 code, (int32_t)&data, (int32_t)reply, flags); 261 jthrowable excep = env->ExceptionOccurred(); 262 if (excep) { 263 report_exception(env, excep, 264 "*** Uncaught remote exception! " 265 "(Exceptions are not yet supported across processes.)"); 266 res = JNI_FALSE; 267 268 /* clean up JNI local ref -- we don't return to Java code */ 269 env->DeleteLocalRef(excep); 270 } 271 272 //aout << "onTransact to Java code; result=" << res << endl 273 // << "Transact from " << this << " to Java code returning " 274 // << reply << ": " << *reply << endl; 275 return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; 276 } 277 278 virtual status_t dump(int fd, const Vector<String16>& args) 279 { 280 return 0; 281 } 282 283 private: 284 JavaVM* const mVM; 285 jobject const mObject; 286 }; 287 288 // ---------------------------------------------------------------------------- 289 290 class JavaBBinderHolder : public RefBase 291 { 292 public: 293 JavaBBinderHolder(JNIEnv* env, jobject object) 294 : mObject(object) 295 { 296 LOGV("Creating JavaBBinderHolder for Object %p\n", object); 297 } 298 ~JavaBBinderHolder() 299 { 300 LOGV("Destroying JavaBBinderHolder for Object %p\n", mObject); 301 } 302 303 sp<JavaBBinder> get(JNIEnv* env) 304 { 305 AutoMutex _l(mLock); 306 sp<JavaBBinder> b = mBinder.promote(); 307 if (b == NULL) { 308 b = new JavaBBinder(env, mObject); 309 mBinder = b; 310 LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n", 311 b.get(), b->getWeakRefs(), mObject, b->getWeakRefs()->getWeakCount()); 312 } 313 314 return b; 315 } 316 317 sp<JavaBBinder> getExisting() 318 { 319 AutoMutex _l(mLock); 320 return mBinder.promote(); 321 } 322 323 private: 324 Mutex mLock; 325 jobject mObject; 326 wp<JavaBBinder> mBinder; 327 }; 328 329 // ---------------------------------------------------------------------------- 330 331 class JavaDeathRecipient : public IBinder::DeathRecipient 332 { 333 public: 334 JavaDeathRecipient(JNIEnv* env, jobject object) 335 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), 336 mHoldsRef(true) 337 { 338 incStrong(this); 339 android_atomic_inc(&gNumDeathRefs); 340 incRefsCreated(env); 341 } 342 343 void binderDied(const wp<IBinder>& who) 344 { 345 JNIEnv* env = javavm_to_jnienv(mVM); 346 347 LOGV("Receiving binderDied() on JavaDeathRecipient %p\n", this); 348 349 env->CallStaticVoidMethod(gBinderProxyOffsets.mClass, 350 gBinderProxyOffsets.mSendDeathNotice, mObject); 351 jthrowable excep = env->ExceptionOccurred(); 352 if (excep) { 353 report_exception(env, excep, 354 "*** Uncaught exception returned from death notification!"); 355 } 356 357 clearReference(); 358 } 359 360 void clearReference() 361 { 362 bool release = false; 363 mLock.lock(); 364 if (mHoldsRef) { 365 mHoldsRef = false; 366 release = true; 367 } 368 mLock.unlock(); 369 if (release) { 370 decStrong(this); 371 } 372 } 373 374 protected: 375 virtual ~JavaDeathRecipient() 376 { 377 //LOGI("Removing death ref: recipient=%p\n", mObject); 378 android_atomic_dec(&gNumDeathRefs); 379 JNIEnv* env = javavm_to_jnienv(mVM); 380 env->DeleteGlobalRef(mObject); 381 } 382 383 private: 384 JavaVM* const mVM; 385 jobject const mObject; 386 Mutex mLock; 387 bool mHoldsRef; 388 }; 389 390 // ---------------------------------------------------------------------------- 391 392 namespace android { 393 394 static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie) 395 { 396 android_atomic_dec(&gNumProxyRefs); 397 JNIEnv* env = javavm_to_jnienv((JavaVM*)cleanupCookie); 398 env->DeleteGlobalRef((jobject)obj); 399 } 400 401 static Mutex mProxyLock; 402 403 jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) 404 { 405 if (val == NULL) return NULL; 406 407 if (val->checkSubclass(&gBinderOffsets)) { 408 // One of our own! 409 jobject object = static_cast<JavaBBinder*>(val.get())->object(); 410 //printf("objectForBinder %p: it's our own %p!\n", val.get(), object); 411 return object; 412 } 413 414 // For the rest of the function we will hold this lock, to serialize 415 // looking/creation of Java proxies for native Binder proxies. 416 AutoMutex _l(mProxyLock); 417 418 // Someone else's... do we know about it? 419 jobject object = (jobject)val->findObject(&gBinderProxyOffsets); 420 if (object != NULL) { 421 jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet); 422 if (res != NULL) { 423 LOGV("objectForBinder %p: found existing %p!\n", val.get(), res); 424 return res; 425 } 426 LOGV("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); 427 android_atomic_dec(&gNumProxyRefs); 428 val->detachObject(&gBinderProxyOffsets); 429 env->DeleteGlobalRef(object); 430 } 431 432 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); 433 if (object != NULL) { 434 LOGV("objectForBinder %p: created new %p!\n", val.get(), object); 435 // The proxy holds a reference to the native object. 436 env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get()); 437 val->incStrong(object); 438 439 // The native object needs to hold a weak reference back to the 440 // proxy, so we can retrieve the same proxy if it is still active. 441 jobject refObject = env->NewGlobalRef( 442 env->GetObjectField(object, gBinderProxyOffsets.mSelf)); 443 val->attachObject(&gBinderProxyOffsets, refObject, 444 jnienv_to_javavm(env), proxy_cleanup); 445 446 // Note that a new object reference has been created. 447 android_atomic_inc(&gNumProxyRefs); 448 incRefsCreated(env); 449 } 450 451 return object; 452 } 453 454 sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) 455 { 456 if (obj == NULL) return NULL; 457 458 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { 459 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 460 env->GetIntField(obj, gBinderOffsets.mObject); 461 return jbh != NULL ? jbh->get(env) : NULL; 462 } 463 464 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { 465 return (IBinder*) 466 env->GetIntField(obj, gBinderProxyOffsets.mObject); 467 } 468 469 LOGW("ibinderForJavaObject: %p is not a Binder object", obj); 470 return NULL; 471 } 472 473 Parcel* parcelForJavaObject(JNIEnv* env, jobject obj) 474 { 475 if (obj) { 476 Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mObject); 477 if (p != NULL) { 478 return p; 479 } 480 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!"); 481 } 482 return NULL; 483 } 484 485 jobject newFileDescriptor(JNIEnv* env, int fd) 486 { 487 jobject object = env->NewObject( 488 gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); 489 if (object != NULL) { 490 //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd); 491 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd); 492 } 493 return object; 494 } 495 496 jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc) 497 { 498 return env->NewObject( 499 gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc); 500 } 501 502 void signalExceptionForError(JNIEnv* env, jobject obj, status_t err) 503 { 504 switch (err) { 505 case UNKNOWN_ERROR: 506 jniThrowException(env, "java/lang/RuntimeException", "Unknown error"); 507 break; 508 case NO_MEMORY: 509 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 510 break; 511 case INVALID_OPERATION: 512 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL); 513 break; 514 case BAD_VALUE: 515 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 516 break; 517 case BAD_INDEX: 518 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 519 break; 520 case BAD_TYPE: 521 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 522 break; 523 case NAME_NOT_FOUND: 524 jniThrowException(env, "java/util/NoSuchElementException", NULL); 525 break; 526 case PERMISSION_DENIED: 527 jniThrowException(env, "java/lang/SecurityException", NULL); 528 break; 529 case NOT_ENOUGH_DATA: 530 jniThrowException(env, "android/os/ParcelFormatException", "Not enough data"); 531 break; 532 case NO_INIT: 533 jniThrowException(env, "java/lang/RuntimeException", "Not initialized"); 534 break; 535 case ALREADY_EXISTS: 536 jniThrowException(env, "java/lang/RuntimeException", "Item already exists"); 537 break; 538 case DEAD_OBJECT: 539 jniThrowException(env, "android/os/DeadObjectException", NULL); 540 break; 541 case UNKNOWN_TRANSACTION: 542 jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code"); 543 break; 544 case FAILED_TRANSACTION: 545 LOGE("!!! FAILED BINDER TRANSACTION !!!"); 546 //jniThrowException(env, "java/lang/OutOfMemoryError", "Binder transaction too large"); 547 break; 548 default: 549 LOGE("Unknown binder error code. 0x%x", err); 550 } 551 } 552 553 } 554 555 // ---------------------------------------------------------------------------- 556 557 static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz) 558 { 559 return IPCThreadState::self()->getCallingPid(); 560 } 561 562 static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz) 563 { 564 return IPCThreadState::self()->getCallingUid(); 565 } 566 567 static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz) 568 { 569 return IPCThreadState::self()->clearCallingIdentity(); 570 } 571 572 static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token) 573 { 574 IPCThreadState::self()->restoreCallingIdentity(token); 575 } 576 577 static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz) 578 { 579 IPCThreadState::self()->flushCommands(); 580 } 581 582 static void android_os_Binder_init(JNIEnv* env, jobject clazz) 583 { 584 JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz); 585 if (jbh == NULL) { 586 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 587 return; 588 } 589 LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh); 590 jbh->incStrong(clazz); 591 env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh); 592 } 593 594 static void android_os_Binder_destroy(JNIEnv* env, jobject clazz) 595 { 596 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 597 env->GetIntField(clazz, gBinderOffsets.mObject); 598 if (jbh != NULL) { 599 env->SetIntField(clazz, gBinderOffsets.mObject, 0); 600 LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh); 601 jbh->decStrong(clazz); 602 } else { 603 // Encountering an uninitialized binder is harmless. All it means is that 604 // the Binder was only partially initialized when its finalizer ran and called 605 // destroy(). The Binder could be partially initialized for several reasons. 606 // For example, a Binder subclass constructor might have thrown an exception before 607 // it could delegate to its superclass's constructor. Consequently init() would 608 // not have been called and the holder pointer would remain NULL. 609 LOGV("Java Binder %p: ignoring uninitialized binder", clazz); 610 } 611 } 612 613 // ---------------------------------------------------------------------------- 614 615 static const JNINativeMethod gBinderMethods[] = { 616 /* name, signature, funcPtr */ 617 { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, 618 { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, 619 { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, 620 { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, 621 { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, 622 { "init", "()V", (void*)android_os_Binder_init }, 623 { "destroy", "()V", (void*)android_os_Binder_destroy } 624 }; 625 626 const char* const kBinderPathName = "android/os/Binder"; 627 628 static int int_register_android_os_Binder(JNIEnv* env) 629 { 630 jclass clazz; 631 632 clazz = env->FindClass(kBinderPathName); 633 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder"); 634 635 gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 636 gBinderOffsets.mExecTransact 637 = env->GetMethodID(clazz, "execTransact", "(IIII)Z"); 638 assert(gBinderOffsets.mExecTransact); 639 640 gBinderOffsets.mObject 641 = env->GetFieldID(clazz, "mObject", "I"); 642 assert(gBinderOffsets.mObject); 643 644 return AndroidRuntime::registerNativeMethods( 645 env, kBinderPathName, 646 gBinderMethods, NELEM(gBinderMethods)); 647 } 648 649 // **************************************************************************** 650 // **************************************************************************** 651 // **************************************************************************** 652 653 namespace android { 654 655 jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz) 656 { 657 return gNumLocalRefs; 658 } 659 660 jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz) 661 { 662 return gNumProxyRefs; 663 } 664 665 jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz) 666 { 667 return gNumDeathRefs; 668 } 669 670 } 671 672 // **************************************************************************** 673 // **************************************************************************** 674 // **************************************************************************** 675 676 static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) 677 { 678 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 679 return javaObjectForIBinder(env, b); 680 } 681 682 static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz) 683 { 684 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 685 android::IPCThreadState::self()->joinThreadPool(); 686 } 687 688 static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env, 689 jobject clazz, jboolean disable) 690 { 691 IPCThreadState::disableBackgroundScheduling(disable ? true : false); 692 } 693 694 static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz) 695 { 696 LOGV("Gc has executed, clearing binder ops"); 697 android_atomic_and(0, &gNumRefsCreated); 698 } 699 700 // ---------------------------------------------------------------------------- 701 702 static const JNINativeMethod gBinderInternalMethods[] = { 703 /* name, signature, funcPtr */ 704 { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject }, 705 { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool }, 706 { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling }, 707 { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc } 708 }; 709 710 const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal"; 711 712 static int int_register_android_os_BinderInternal(JNIEnv* env) 713 { 714 jclass clazz; 715 716 clazz = env->FindClass(kBinderInternalPathName); 717 LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal"); 718 719 gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 720 gBinderInternalOffsets.mForceGc 721 = env->GetStaticMethodID(clazz, "forceBinderGc", "()V"); 722 assert(gBinderInternalOffsets.mForceGc); 723 724 return AndroidRuntime::registerNativeMethods( 725 env, kBinderInternalPathName, 726 gBinderInternalMethods, NELEM(gBinderInternalMethods)); 727 } 728 729 // **************************************************************************** 730 // **************************************************************************** 731 // **************************************************************************** 732 733 static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj) 734 { 735 IBinder* target = (IBinder*) 736 env->GetIntField(obj, gBinderProxyOffsets.mObject); 737 if (target == NULL) { 738 return JNI_FALSE; 739 } 740 status_t err = target->pingBinder(); 741 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; 742 } 743 744 static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj) 745 { 746 IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject); 747 if (target != NULL) { 748 const String16& desc = target->getInterfaceDescriptor(); 749 return env->NewString(desc.string(), desc.size()); 750 } 751 jniThrowException(env, "java/lang/RuntimeException", 752 "No binder found for object"); 753 return NULL; 754 } 755 756 static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj) 757 { 758 IBinder* target = (IBinder*) 759 env->GetIntField(obj, gBinderProxyOffsets.mObject); 760 if (target == NULL) { 761 return JNI_FALSE; 762 } 763 bool alive = target->isBinderAlive(); 764 return alive ? JNI_TRUE : JNI_FALSE; 765 } 766 767 static int getprocname(pid_t pid, char *buf, size_t len) { 768 char filename[20]; 769 FILE *f; 770 771 sprintf(filename, "/proc/%d/cmdline", pid); 772 f = fopen(filename, "r"); 773 if (!f) { *buf = '\0'; return 1; } 774 if (!fgets(buf, len, f)) { *buf = '\0'; return 2; } 775 fclose(f); 776 return 0; 777 } 778 779 static bool push_eventlog_string(char** pos, const char* end, const char* str) { 780 jint len = strlen(str); 781 int space_needed = 1 + sizeof(len) + len; 782 if (end - *pos < space_needed) { 783 LOGW("not enough space for string. remain=%d; needed=%d", 784 (end - *pos), space_needed); 785 return false; 786 } 787 **pos = EVENT_TYPE_STRING; 788 (*pos)++; 789 memcpy(*pos, &len, sizeof(len)); 790 *pos += sizeof(len); 791 memcpy(*pos, str, len); 792 *pos += len; 793 return true; 794 } 795 796 static bool push_eventlog_int(char** pos, const char* end, jint val) { 797 int space_needed = 1 + sizeof(val); 798 if (end - *pos < space_needed) { 799 LOGW("not enough space for int. remain=%d; needed=%d", 800 (end - *pos), space_needed); 801 return false; 802 } 803 **pos = EVENT_TYPE_INT; 804 (*pos)++; 805 memcpy(*pos, &val, sizeof(val)); 806 *pos += sizeof(val); 807 return true; 808 } 809 810 // From frameworks/base/core/java/android/content/EventLogTags.logtags: 811 #define LOGTAG_BINDER_OPERATION 52004 812 813 static void conditionally_log_binder_call(int64_t start_millis, 814 IBinder* target, jint code) { 815 int duration_ms = static_cast<int>(uptimeMillis() - start_millis); 816 817 int sample_percent; 818 if (duration_ms >= 500) { 819 sample_percent = 100; 820 } else { 821 sample_percent = 100 * duration_ms / 500; 822 if (sample_percent == 0) { 823 return; 824 } 825 if (sample_percent < (random() % 100 + 1)) { 826 return; 827 } 828 } 829 830 char process_name[40]; 831 getprocname(getpid(), process_name, sizeof(process_name)); 832 String8 desc(target->getInterfaceDescriptor()); 833 834 char buf[LOGGER_ENTRY_MAX_PAYLOAD]; 835 buf[0] = EVENT_TYPE_LIST; 836 buf[1] = 5; 837 char* pos = &buf[2]; 838 char* end = &buf[LOGGER_ENTRY_MAX_PAYLOAD - 1]; // leave room for final \n 839 if (!push_eventlog_string(&pos, end, desc.string())) return; 840 if (!push_eventlog_int(&pos, end, code)) return; 841 if (!push_eventlog_int(&pos, end, duration_ms)) return; 842 if (!push_eventlog_string(&pos, end, process_name)) return; 843 if (!push_eventlog_int(&pos, end, sample_percent)) return; 844 *(pos++) = '\n'; // conventional with EVENT_TYPE_LIST apparently. 845 android_bWriteLog(LOGTAG_BINDER_OPERATION, buf, pos - buf); 846 } 847 848 // We only measure binder call durations to potentially log them if 849 // we're on the main thread. Unfortunately sim-eng doesn't seem to 850 // have gettid, so we just ignore this and don't log if we can't 851 // get the thread id. 852 static bool should_time_binder_calls() { 853 #ifdef HAVE_GETTID 854 return (getpid() == androidGetTid()); 855 #else 856 #warning no gettid(), so not logging Binder calls... 857 return false; 858 #endif 859 } 860 861 static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, 862 jint code, jobject dataObj, 863 jobject replyObj, jint flags) 864 { 865 if (dataObj == NULL) { 866 jniThrowException(env, "java/lang/NullPointerException", NULL); 867 return JNI_FALSE; 868 } 869 870 Parcel* data = parcelForJavaObject(env, dataObj); 871 if (data == NULL) { 872 return JNI_FALSE; 873 } 874 Parcel* reply = parcelForJavaObject(env, replyObj); 875 if (reply == NULL && replyObj != NULL) { 876 return JNI_FALSE; 877 } 878 879 IBinder* target = (IBinder*) 880 env->GetIntField(obj, gBinderProxyOffsets.mObject); 881 if (target == NULL) { 882 jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); 883 return JNI_FALSE; 884 } 885 886 LOGV("Java code calling transact on %p in Java object %p with code %d\n", 887 target, obj, code); 888 889 // Only log the binder call duration for things on the Java-level main thread. 890 // But if we don't 891 const bool time_binder_calls = should_time_binder_calls(); 892 893 int64_t start_millis; 894 if (time_binder_calls) { 895 start_millis = uptimeMillis(); 896 } 897 //printf("Transact from Java code to %p sending: ", target); data->print(); 898 status_t err = target->transact(code, *data, reply, flags); 899 //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); 900 if (time_binder_calls) { 901 conditionally_log_binder_call(start_millis, target, code); 902 } 903 904 if (err == NO_ERROR) { 905 return JNI_TRUE; 906 } else if (err == UNKNOWN_TRANSACTION) { 907 return JNI_FALSE; 908 } 909 910 signalExceptionForError(env, obj, err); 911 return JNI_FALSE; 912 } 913 914 static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, 915 jobject recipient, jint flags) 916 { 917 if (recipient == NULL) { 918 jniThrowException(env, "java/lang/NullPointerException", NULL); 919 return; 920 } 921 922 IBinder* target = (IBinder*) 923 env->GetIntField(obj, gBinderProxyOffsets.mObject); 924 if (target == NULL) { 925 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 926 assert(false); 927 } 928 929 LOGV("linkToDeath: binder=%p recipient=%p\n", target, recipient); 930 931 if (!target->localBinder()) { 932 sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient); 933 status_t err = target->linkToDeath(jdr, recipient, flags); 934 if (err != NO_ERROR) { 935 // Failure adding the death recipient, so clear its reference 936 // now. 937 jdr->clearReference(); 938 signalExceptionForError(env, obj, err); 939 } 940 } 941 } 942 943 static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, 944 jobject recipient, jint flags) 945 { 946 jboolean res = JNI_FALSE; 947 if (recipient == NULL) { 948 jniThrowException(env, "java/lang/NullPointerException", NULL); 949 return res; 950 } 951 952 IBinder* target = (IBinder*) 953 env->GetIntField(obj, gBinderProxyOffsets.mObject); 954 if (target == NULL) { 955 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 956 return JNI_FALSE; 957 } 958 959 LOGV("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); 960 961 if (!target->localBinder()) { 962 wp<IBinder::DeathRecipient> dr; 963 status_t err = target->unlinkToDeath(NULL, recipient, flags, &dr); 964 if (err == NO_ERROR && dr != NULL) { 965 sp<IBinder::DeathRecipient> sdr = dr.promote(); 966 JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get()); 967 if (jdr != NULL) { 968 jdr->clearReference(); 969 } 970 } 971 if (err == NO_ERROR || err == DEAD_OBJECT) { 972 res = JNI_TRUE; 973 } else { 974 jniThrowException(env, "java/util/NoSuchElementException", 975 "Death link does not exist"); 976 } 977 } 978 979 return res; 980 } 981 982 static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) 983 { 984 IBinder* b = (IBinder*) 985 env->GetIntField(obj, gBinderProxyOffsets.mObject); 986 LOGV("Destroying BinderProxy %p: binder=%p\n", obj, b); 987 env->SetIntField(obj, gBinderProxyOffsets.mObject, 0); 988 b->decStrong(obj); 989 IPCThreadState::self()->flushCommands(); 990 } 991 992 // ---------------------------------------------------------------------------- 993 994 static const JNINativeMethod gBinderProxyMethods[] = { 995 /* name, signature, funcPtr */ 996 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, 997 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, 998 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, 999 {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, 1000 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, 1001 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, 1002 {"destroy", "()V", (void*)android_os_BinderProxy_destroy}, 1003 }; 1004 1005 const char* const kBinderProxyPathName = "android/os/BinderProxy"; 1006 1007 static int int_register_android_os_BinderProxy(JNIEnv* env) 1008 { 1009 jclass clazz; 1010 1011 clazz = env->FindClass("java/lang/ref/WeakReference"); 1012 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.ref.WeakReference"); 1013 gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1014 gWeakReferenceOffsets.mGet 1015 = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;"); 1016 assert(gWeakReferenceOffsets.mGet); 1017 1018 clazz = env->FindClass("java/lang/Error"); 1019 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error"); 1020 gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1021 1022 clazz = env->FindClass(kBinderProxyPathName); 1023 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy"); 1024 1025 gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1026 gBinderProxyOffsets.mConstructor 1027 = env->GetMethodID(clazz, "<init>", "()V"); 1028 assert(gBinderProxyOffsets.mConstructor); 1029 gBinderProxyOffsets.mSendDeathNotice 1030 = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); 1031 assert(gBinderProxyOffsets.mSendDeathNotice); 1032 1033 gBinderProxyOffsets.mObject 1034 = env->GetFieldID(clazz, "mObject", "I"); 1035 assert(gBinderProxyOffsets.mObject); 1036 gBinderProxyOffsets.mSelf 1037 = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;"); 1038 assert(gBinderProxyOffsets.mSelf); 1039 1040 return AndroidRuntime::registerNativeMethods( 1041 env, kBinderProxyPathName, 1042 gBinderProxyMethods, NELEM(gBinderProxyMethods)); 1043 } 1044 1045 // **************************************************************************** 1046 // **************************************************************************** 1047 // **************************************************************************** 1048 1049 static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz) 1050 { 1051 Parcel* parcel = parcelForJavaObject(env, clazz); 1052 return parcel ? parcel->dataSize() : 0; 1053 } 1054 1055 static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz) 1056 { 1057 Parcel* parcel = parcelForJavaObject(env, clazz); 1058 return parcel ? parcel->dataAvail() : 0; 1059 } 1060 1061 static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz) 1062 { 1063 Parcel* parcel = parcelForJavaObject(env, clazz); 1064 return parcel ? parcel->dataPosition() : 0; 1065 } 1066 1067 static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz) 1068 { 1069 Parcel* parcel = parcelForJavaObject(env, clazz); 1070 return parcel ? parcel->dataCapacity() : 0; 1071 } 1072 1073 static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size) 1074 { 1075 Parcel* parcel = parcelForJavaObject(env, clazz); 1076 if (parcel != NULL) { 1077 const status_t err = parcel->setDataSize(size); 1078 if (err != NO_ERROR) { 1079 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1080 } 1081 } 1082 } 1083 1084 static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos) 1085 { 1086 Parcel* parcel = parcelForJavaObject(env, clazz); 1087 if (parcel != NULL) { 1088 parcel->setDataPosition(pos); 1089 } 1090 } 1091 1092 static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size) 1093 { 1094 Parcel* parcel = parcelForJavaObject(env, clazz); 1095 if (parcel != NULL) { 1096 const status_t err = parcel->setDataCapacity(size); 1097 if (err != NO_ERROR) { 1098 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1099 } 1100 } 1101 } 1102 1103 static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz, 1104 jobject data, jint offset, 1105 jint length) 1106 { 1107 Parcel* parcel = parcelForJavaObject(env, clazz); 1108 if (parcel == NULL) { 1109 return; 1110 } 1111 void *dest; 1112 1113 const status_t err = parcel->writeInt32(length); 1114 if (err != NO_ERROR) { 1115 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1116 } 1117 1118 dest = parcel->writeInplace(length); 1119 1120 if (dest == NULL) { 1121 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1122 return; 1123 } 1124 1125 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0); 1126 if (ar) { 1127 memcpy(dest, ar, length); 1128 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); 1129 } 1130 } 1131 1132 1133 static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val) 1134 { 1135 Parcel* parcel = parcelForJavaObject(env, clazz); 1136 if (parcel != NULL) { 1137 const status_t err = parcel->writeInt32(val); 1138 if (err != NO_ERROR) { 1139 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1140 } 1141 } 1142 } 1143 1144 static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val) 1145 { 1146 Parcel* parcel = parcelForJavaObject(env, clazz); 1147 if (parcel != NULL) { 1148 const status_t err = parcel->writeInt64(val); 1149 if (err != NO_ERROR) { 1150 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1151 } 1152 } 1153 } 1154 1155 static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val) 1156 { 1157 Parcel* parcel = parcelForJavaObject(env, clazz); 1158 if (parcel != NULL) { 1159 const status_t err = parcel->writeFloat(val); 1160 if (err != NO_ERROR) { 1161 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1162 } 1163 } 1164 } 1165 1166 static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val) 1167 { 1168 Parcel* parcel = parcelForJavaObject(env, clazz); 1169 if (parcel != NULL) { 1170 const status_t err = parcel->writeDouble(val); 1171 if (err != NO_ERROR) { 1172 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1173 } 1174 } 1175 } 1176 1177 static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val) 1178 { 1179 Parcel* parcel = parcelForJavaObject(env, clazz); 1180 if (parcel != NULL) { 1181 status_t err = NO_MEMORY; 1182 if (val) { 1183 const jchar* str = env->GetStringCritical(val, 0); 1184 if (str) { 1185 err = parcel->writeString16(str, env->GetStringLength(val)); 1186 env->ReleaseStringCritical(val, str); 1187 } 1188 } else { 1189 err = parcel->writeString16(NULL, 0); 1190 } 1191 if (err != NO_ERROR) { 1192 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1193 } 1194 } 1195 } 1196 1197 static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object) 1198 { 1199 Parcel* parcel = parcelForJavaObject(env, clazz); 1200 if (parcel != NULL) { 1201 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 1202 if (err != NO_ERROR) { 1203 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1204 } 1205 } 1206 } 1207 1208 static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1209 { 1210 Parcel* parcel = parcelForJavaObject(env, clazz); 1211 if (parcel != NULL) { 1212 const status_t err = parcel->writeDupFileDescriptor( 1213 env->GetIntField(object, gFileDescriptorOffsets.mDescriptor)); 1214 if (err != NO_ERROR) { 1215 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1216 } 1217 } 1218 } 1219 1220 static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz) 1221 { 1222 jbyteArray ret = NULL; 1223 1224 Parcel* parcel = parcelForJavaObject(env, clazz); 1225 if (parcel != NULL) { 1226 int32_t len = parcel->readInt32(); 1227 1228 // sanity check the stored length against the true data size 1229 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) { 1230 ret = env->NewByteArray(len); 1231 1232 if (ret != NULL) { 1233 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1234 if (a2) { 1235 const void* data = parcel->readInplace(len); 1236 memcpy(a2, data, len); 1237 env->ReleasePrimitiveArrayCritical(ret, a2, 0); 1238 } 1239 } 1240 } 1241 } 1242 1243 return ret; 1244 } 1245 1246 static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz) 1247 { 1248 Parcel* parcel = parcelForJavaObject(env, clazz); 1249 if (parcel != NULL) { 1250 return parcel->readInt32(); 1251 } 1252 return 0; 1253 } 1254 1255 static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz) 1256 { 1257 Parcel* parcel = parcelForJavaObject(env, clazz); 1258 if (parcel != NULL) { 1259 return parcel->readInt64(); 1260 } 1261 return 0; 1262 } 1263 1264 static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz) 1265 { 1266 Parcel* parcel = parcelForJavaObject(env, clazz); 1267 if (parcel != NULL) { 1268 return parcel->readFloat(); 1269 } 1270 return 0; 1271 } 1272 1273 static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz) 1274 { 1275 Parcel* parcel = parcelForJavaObject(env, clazz); 1276 if (parcel != NULL) { 1277 return parcel->readDouble(); 1278 } 1279 return 0; 1280 } 1281 1282 static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz) 1283 { 1284 Parcel* parcel = parcelForJavaObject(env, clazz); 1285 if (parcel != NULL) { 1286 size_t len; 1287 const char16_t* str = parcel->readString16Inplace(&len); 1288 if (str) { 1289 return env->NewString(str, len); 1290 } 1291 return NULL; 1292 } 1293 return NULL; 1294 } 1295 1296 static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz) 1297 { 1298 Parcel* parcel = parcelForJavaObject(env, clazz); 1299 if (parcel != NULL) { 1300 return javaObjectForIBinder(env, parcel->readStrongBinder()); 1301 } 1302 return NULL; 1303 } 1304 1305 static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz) 1306 { 1307 Parcel* parcel = parcelForJavaObject(env, clazz); 1308 if (parcel != NULL) { 1309 int fd = parcel->readFileDescriptor(); 1310 if (fd < 0) return NULL; 1311 fd = dup(fd); 1312 if (fd < 0) return NULL; 1313 jobject object = env->NewObject( 1314 gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); 1315 if (object != NULL) { 1316 //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd); 1317 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd); 1318 } 1319 return object; 1320 } 1321 return NULL; 1322 } 1323 1324 static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz, 1325 jstring name, jint mode) 1326 { 1327 if (name == NULL) { 1328 jniThrowException(env, "java/lang/NullPointerException", NULL); 1329 return NULL; 1330 } 1331 const jchar* str = env->GetStringCritical(name, 0); 1332 if (str == NULL) { 1333 // Whatever, whatever. 1334 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1335 return NULL; 1336 } 1337 String8 name8(str, env->GetStringLength(name)); 1338 env->ReleaseStringCritical(name, str); 1339 int flags=0; 1340 switch (mode&0x30000000) { 1341 case 0: 1342 case 0x10000000: 1343 flags = O_RDONLY; 1344 break; 1345 case 0x20000000: 1346 flags = O_WRONLY; 1347 break; 1348 case 0x30000000: 1349 flags = O_RDWR; 1350 break; 1351 } 1352 1353 if (mode&0x08000000) flags |= O_CREAT; 1354 if (mode&0x04000000) flags |= O_TRUNC; 1355 if (mode&0x02000000) flags |= O_APPEND; 1356 1357 int realMode = S_IRWXU|S_IRWXG; 1358 if (mode&0x00000001) realMode |= S_IROTH; 1359 if (mode&0x00000002) realMode |= S_IWOTH; 1360 1361 int fd = open(name8.string(), flags, realMode); 1362 if (fd < 0) { 1363 jniThrowException(env, "java/io/FileNotFoundException", NULL); 1364 return NULL; 1365 } 1366 jobject object = newFileDescriptor(env, fd); 1367 if (object == NULL) { 1368 close(fd); 1369 } 1370 return object; 1371 } 1372 1373 static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1374 { 1375 int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1376 if (fd >= 0) { 1377 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1); 1378 //LOGI("Closing ParcelFileDescriptor %d\n", fd); 1379 close(fd); 1380 } 1381 } 1382 1383 static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz) 1384 { 1385 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1386 if (own) { 1387 Parcel* parcel = parcelForJavaObject(env, clazz); 1388 if (parcel != NULL) { 1389 //LOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel); 1390 parcel->freeData(); 1391 } 1392 } 1393 } 1394 1395 static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt) 1396 { 1397 Parcel* parcel = (Parcel*)parcelInt; 1398 int own = 0; 1399 if (!parcel) { 1400 //LOGI("Initializing obj %p: creating new Parcel\n", clazz); 1401 own = 1; 1402 parcel = new Parcel; 1403 } else { 1404 //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel); 1405 } 1406 if (parcel == NULL) { 1407 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1408 return; 1409 } 1410 //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own); 1411 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own); 1412 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel); 1413 } 1414 1415 static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz) 1416 { 1417 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1418 if (own) { 1419 Parcel* parcel = parcelForJavaObject(env, clazz); 1420 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1421 //LOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel); 1422 delete parcel; 1423 } else { 1424 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1425 //LOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz); 1426 } 1427 } 1428 1429 static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz) 1430 { 1431 Parcel* parcel = parcelForJavaObject(env, clazz); 1432 if (parcel == NULL) { 1433 return NULL; 1434 } 1435 1436 // do not marshall if there are binder objects in the parcel 1437 if (parcel->objectsCount()) 1438 { 1439 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); 1440 return NULL; 1441 } 1442 1443 jbyteArray ret = env->NewByteArray(parcel->dataSize()); 1444 1445 if (ret != NULL) 1446 { 1447 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1448 if (array != NULL) 1449 { 1450 memcpy(array, parcel->data(), parcel->dataSize()); 1451 env->ReleasePrimitiveArrayCritical(ret, array, 0); 1452 } 1453 } 1454 1455 return ret; 1456 } 1457 1458 static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length) 1459 { 1460 Parcel* parcel = parcelForJavaObject(env, clazz); 1461 if (parcel == NULL || length < 0) { 1462 return; 1463 } 1464 1465 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0); 1466 if (array) 1467 { 1468 parcel->setDataSize(length); 1469 parcel->setDataPosition(0); 1470 1471 void* raw = parcel->writeInplace(length); 1472 memcpy(raw, (array + offset), length); 1473 1474 env->ReleasePrimitiveArrayCritical(data, array, 0); 1475 } 1476 } 1477 1478 static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length) 1479 { 1480 Parcel* thisParcel = parcelForJavaObject(env, clazz); 1481 if (thisParcel == NULL) { 1482 return; 1483 } 1484 Parcel* otherParcel = parcelForJavaObject(env, parcel); 1485 if (otherParcel == NULL) { 1486 return; 1487 } 1488 1489 (void) thisParcel->appendFrom(otherParcel, offset, length); 1490 } 1491 1492 static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz) 1493 { 1494 jboolean ret = JNI_FALSE; 1495 Parcel* parcel = parcelForJavaObject(env, clazz); 1496 if (parcel != NULL) { 1497 if (parcel->hasFileDescriptors()) { 1498 ret = JNI_TRUE; 1499 } 1500 } 1501 return ret; 1502 } 1503 1504 static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name) 1505 { 1506 Parcel* parcel = parcelForJavaObject(env, clazz); 1507 if (parcel != NULL) { 1508 // In the current implementation, the token is just the serialized interface name that 1509 // the caller expects to be invoking 1510 const jchar* str = env->GetStringCritical(name, 0); 1511 if (str != NULL) { 1512 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 1513 env->ReleaseStringCritical(name, str); 1514 } 1515 } 1516 } 1517 1518 static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name) 1519 { 1520 jboolean ret = JNI_FALSE; 1521 1522 Parcel* parcel = parcelForJavaObject(env, clazz); 1523 if (parcel != NULL) { 1524 const jchar* str = env->GetStringCritical(name, 0); 1525 if (str) { 1526 bool isValid = parcel->enforceInterface(String16(str, env->GetStringLength(name))); 1527 env->ReleaseStringCritical(name, str); 1528 if (isValid) { 1529 return; // everything was correct -> return silently 1530 } 1531 } 1532 } 1533 1534 // all error conditions wind up here 1535 jniThrowException(env, "java/lang/SecurityException", 1536 "Binder invocation to an incorrect interface"); 1537 } 1538 1539 // ---------------------------------------------------------------------------- 1540 1541 static const JNINativeMethod gParcelMethods[] = { 1542 {"dataSize", "()I", (void*)android_os_Parcel_dataSize}, 1543 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail}, 1544 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition}, 1545 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity}, 1546 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize}, 1547 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition}, 1548 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity}, 1549 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative}, 1550 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt}, 1551 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong}, 1552 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat}, 1553 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble}, 1554 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString}, 1555 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, 1556 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor}, 1557 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray}, 1558 {"readInt", "()I", (void*)android_os_Parcel_readInt}, 1559 {"readLong", "()J", (void*)android_os_Parcel_readLong}, 1560 {"readFloat", "()F", (void*)android_os_Parcel_readFloat}, 1561 {"readDouble", "()D", (void*)android_os_Parcel_readDouble}, 1562 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString}, 1563 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, 1564 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor}, 1565 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor}, 1566 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor}, 1567 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer}, 1568 {"init", "(I)V", (void*)android_os_Parcel_init}, 1569 {"destroy", "()V", (void*)android_os_Parcel_destroy}, 1570 {"marshall", "()[B", (void*)android_os_Parcel_marshall}, 1571 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall}, 1572 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom}, 1573 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors}, 1574 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken}, 1575 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface}, 1576 }; 1577 1578 const char* const kParcelPathName = "android/os/Parcel"; 1579 1580 static int int_register_android_os_Parcel(JNIEnv* env) 1581 { 1582 jclass clazz; 1583 1584 clazz = env->FindClass("android/util/Log"); 1585 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log"); 1586 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1587 gLogOffsets.mLogE = env->GetStaticMethodID( 1588 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I"); 1589 assert(gLogOffsets.mLogE); 1590 1591 clazz = env->FindClass("java/io/FileDescriptor"); 1592 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); 1593 gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1594 gFileDescriptorOffsets.mConstructor 1595 = env->GetMethodID(clazz, "<init>", "()V"); 1596 gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); 1597 LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, 1598 "Unable to find descriptor field in java.io.FileDescriptor"); 1599 1600 clazz = env->FindClass("android/os/ParcelFileDescriptor"); 1601 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 1602 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1603 gParcelFileDescriptorOffsets.mConstructor 1604 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 1605 1606 clazz = env->FindClass(kParcelPathName); 1607 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel"); 1608 1609 gParcelOffsets.mObject 1610 = env->GetFieldID(clazz, "mObject", "I"); 1611 gParcelOffsets.mOwnObject 1612 = env->GetFieldID(clazz, "mOwnObject", "I"); 1613 1614 return AndroidRuntime::registerNativeMethods( 1615 env, kParcelPathName, 1616 gParcelMethods, NELEM(gParcelMethods)); 1617 } 1618 1619 int register_android_os_Binder(JNIEnv* env) 1620 { 1621 if (int_register_android_os_Binder(env) < 0) 1622 return -1; 1623 if (int_register_android_os_BinderInternal(env) < 0) 1624 return -1; 1625 if (int_register_android_os_BinderProxy(env) < 0) 1626 return -1; 1627 if (int_register_android_os_Parcel(env) < 0) 1628 return -1; 1629 return 0; 1630 } 1631 1632 namespace android { 1633 1634 // Returns the Unix file descriptor for a ParcelFileDescriptor object 1635 int getParcelFileDescriptorFD(JNIEnv* env, jobject object) 1636 { 1637 return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1638 } 1639 1640 } 1641