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