android_util_Binder.cpp revision 0234376503ce421c4b871d5d811c541f5094301a
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 45using namespace android; 46 47// ---------------------------------------------------------------------------- 48 49static 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 62static struct binderinternal_offsets_t 63{ 64 // Class state. 65 jclass mClass; 66 jmethodID mForceGc; 67 68} gBinderInternalOffsets; 69 70// ---------------------------------------------------------------------------- 71 72static struct debug_offsets_t 73{ 74 // Class state. 75 jclass mClass; 76 77} gDebugOffsets; 78 79// ---------------------------------------------------------------------------- 80 81static struct weakreference_offsets_t 82{ 83 // Class state. 84 jclass mClass; 85 jmethodID mGet; 86 87} gWeakReferenceOffsets; 88 89static struct error_offsets_t 90{ 91 jclass mClass; 92} gErrorOffsets; 93 94// ---------------------------------------------------------------------------- 95 96static 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 111static struct parcel_offsets_t 112{ 113 jfieldID mObject; 114 jfieldID mOwnObject; 115} gParcelOffsets; 116 117static struct log_offsets_t 118{ 119 // Class state. 120 jclass mClass; 121 jmethodID mLogE; 122} gLogOffsets; 123 124static struct file_descriptor_offsets_t 125{ 126 jclass mClass; 127 jmethodID mConstructor; 128 jfieldID mDescriptor; 129} gFileDescriptorOffsets; 130 131static struct parcel_file_descriptor_offsets_t 132{ 133 jclass mClass; 134 jmethodID mConstructor; 135} gParcelFileDescriptorOffsets; 136 137static struct strict_mode_callback_offsets_t 138{ 139 jclass mClass; 140 jmethodID mCallback; 141} gStrictModeCallbackOffsets; 142 143// **************************************************************************** 144// **************************************************************************** 145// **************************************************************************** 146 147static volatile int32_t gNumRefsCreated = 0; 148static volatile int32_t gNumProxyRefs = 0; 149static volatile int32_t gNumLocalRefs = 0; 150static volatile int32_t gNumDeathRefs = 0; 151 152static 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 164static JavaVM* jnienv_to_javavm(JNIEnv* env) 165{ 166 JavaVM* vm; 167 return env->GetJavaVM(&vm) >= 0 ? vm : NULL; 168} 169 170static 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 176static 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 217bail: 218 /* discard local refs created for us by VM */ 219 env->DeleteLocalRef(tagstr); 220 env->DeleteLocalRef(msgstr); 221} 222 223static 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 232class JavaBBinderHolder; 233 234class JavaBBinder : public BBinder 235{ 236public: 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 255protected: 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 315private: 316 JavaVM* const mVM; 317 jobject const mObject; 318}; 319 320// ---------------------------------------------------------------------------- 321 322class JavaBBinderHolder : public RefBase 323{ 324public: 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 355private: 356 Mutex mLock; 357 jobject mObject; 358 wp<JavaBBinder> mBinder; 359}; 360 361// ---------------------------------------------------------------------------- 362 363class JavaDeathRecipient : public IBinder::DeathRecipient 364{ 365public: 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 406protected: 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 415private: 416 JavaVM* const mVM; 417 jobject const mObject; 418 Mutex mLock; 419 bool mHoldsRef; 420}; 421 422// ---------------------------------------------------------------------------- 423 424namespace android { 425 426static 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 433static Mutex mProxyLock; 434 435jobject 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 486sp<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 505Parcel* 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 517jobject 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 528jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc) 529{ 530 return env->NewObject( 531 gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc); 532} 533 534void 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 589static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz) 590{ 591 return IPCThreadState::self()->getCallingPid(); 592} 593 594static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz) 595{ 596 return IPCThreadState::self()->getCallingUid(); 597} 598 599static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz) 600{ 601 return IPCThreadState::self()->clearCallingIdentity(); 602} 603 604static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token) 605{ 606 IPCThreadState::self()->restoreCallingIdentity(token); 607} 608 609static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask) 610{ 611 IPCThreadState::self()->setStrictModePolicy(policyMask); 612} 613 614static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz) 615{ 616 return IPCThreadState::self()->getStrictModePolicy(); 617} 618 619static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz) 620{ 621 IPCThreadState::self()->flushCommands(); 622} 623 624static void android_os_Binder_init(JNIEnv* env, jobject clazz) 625{ 626 JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz); 627 if (jbh == NULL) { 628 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 629 return; 630 } 631 LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh); 632 jbh->incStrong(clazz); 633 env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh); 634} 635 636static void android_os_Binder_destroy(JNIEnv* env, jobject clazz) 637{ 638 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 639 env->GetIntField(clazz, gBinderOffsets.mObject); 640 if (jbh != NULL) { 641 env->SetIntField(clazz, gBinderOffsets.mObject, 0); 642 LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh); 643 jbh->decStrong(clazz); 644 } else { 645 // Encountering an uninitialized binder is harmless. All it means is that 646 // the Binder was only partially initialized when its finalizer ran and called 647 // destroy(). The Binder could be partially initialized for several reasons. 648 // For example, a Binder subclass constructor might have thrown an exception before 649 // it could delegate to its superclass's constructor. Consequently init() would 650 // not have been called and the holder pointer would remain NULL. 651 LOGV("Java Binder %p: ignoring uninitialized binder", clazz); 652 } 653} 654 655// ---------------------------------------------------------------------------- 656 657static const JNINativeMethod gBinderMethods[] = { 658 /* name, signature, funcPtr */ 659 { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, 660 { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, 661 { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, 662 { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, 663 { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, 664 { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, 665 { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, 666 { "init", "()V", (void*)android_os_Binder_init }, 667 { "destroy", "()V", (void*)android_os_Binder_destroy } 668}; 669 670const char* const kBinderPathName = "android/os/Binder"; 671 672static int int_register_android_os_Binder(JNIEnv* env) 673{ 674 jclass clazz; 675 676 clazz = env->FindClass(kBinderPathName); 677 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder"); 678 679 gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 680 gBinderOffsets.mExecTransact 681 = env->GetMethodID(clazz, "execTransact", "(IIII)Z"); 682 assert(gBinderOffsets.mExecTransact); 683 684 gBinderOffsets.mObject 685 = env->GetFieldID(clazz, "mObject", "I"); 686 assert(gBinderOffsets.mObject); 687 688 return AndroidRuntime::registerNativeMethods( 689 env, kBinderPathName, 690 gBinderMethods, NELEM(gBinderMethods)); 691} 692 693// **************************************************************************** 694// **************************************************************************** 695// **************************************************************************** 696 697namespace android { 698 699jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz) 700{ 701 return gNumLocalRefs; 702} 703 704jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz) 705{ 706 return gNumProxyRefs; 707} 708 709jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz) 710{ 711 return gNumDeathRefs; 712} 713 714} 715 716// **************************************************************************** 717// **************************************************************************** 718// **************************************************************************** 719 720static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) 721{ 722 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 723 return javaObjectForIBinder(env, b); 724} 725 726static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz) 727{ 728 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 729 android::IPCThreadState::self()->joinThreadPool(); 730} 731 732static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env, 733 jobject clazz, jboolean disable) 734{ 735 IPCThreadState::disableBackgroundScheduling(disable ? true : false); 736} 737 738static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz) 739{ 740 LOGV("Gc has executed, clearing binder ops"); 741 android_atomic_and(0, &gNumRefsCreated); 742} 743 744// ---------------------------------------------------------------------------- 745 746static const JNINativeMethod gBinderInternalMethods[] = { 747 /* name, signature, funcPtr */ 748 { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject }, 749 { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool }, 750 { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling }, 751 { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc } 752}; 753 754const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal"; 755 756static int int_register_android_os_BinderInternal(JNIEnv* env) 757{ 758 jclass clazz; 759 760 clazz = env->FindClass(kBinderInternalPathName); 761 LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal"); 762 763 gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 764 gBinderInternalOffsets.mForceGc 765 = env->GetStaticMethodID(clazz, "forceBinderGc", "()V"); 766 assert(gBinderInternalOffsets.mForceGc); 767 768 return AndroidRuntime::registerNativeMethods( 769 env, kBinderInternalPathName, 770 gBinderInternalMethods, NELEM(gBinderInternalMethods)); 771} 772 773// **************************************************************************** 774// **************************************************************************** 775// **************************************************************************** 776 777static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj) 778{ 779 IBinder* target = (IBinder*) 780 env->GetIntField(obj, gBinderProxyOffsets.mObject); 781 if (target == NULL) { 782 return JNI_FALSE; 783 } 784 status_t err = target->pingBinder(); 785 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; 786} 787 788static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj) 789{ 790 IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject); 791 if (target != NULL) { 792 const String16& desc = target->getInterfaceDescriptor(); 793 return env->NewString(desc.string(), desc.size()); 794 } 795 jniThrowException(env, "java/lang/RuntimeException", 796 "No binder found for object"); 797 return NULL; 798} 799 800static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj) 801{ 802 IBinder* target = (IBinder*) 803 env->GetIntField(obj, gBinderProxyOffsets.mObject); 804 if (target == NULL) { 805 return JNI_FALSE; 806 } 807 bool alive = target->isBinderAlive(); 808 return alive ? JNI_TRUE : JNI_FALSE; 809} 810 811static int getprocname(pid_t pid, char *buf, size_t len) { 812 char filename[20]; 813 FILE *f; 814 815 sprintf(filename, "/proc/%d/cmdline", pid); 816 f = fopen(filename, "r"); 817 if (!f) { *buf = '\0'; return 1; } 818 if (!fgets(buf, len, f)) { *buf = '\0'; return 2; } 819 fclose(f); 820 return 0; 821} 822 823static bool push_eventlog_string(char** pos, const char* end, const char* str) { 824 jint len = strlen(str); 825 int space_needed = 1 + sizeof(len) + len; 826 if (end - *pos < space_needed) { 827 LOGW("not enough space for string. remain=%d; needed=%d", 828 (end - *pos), space_needed); 829 return false; 830 } 831 **pos = EVENT_TYPE_STRING; 832 (*pos)++; 833 memcpy(*pos, &len, sizeof(len)); 834 *pos += sizeof(len); 835 memcpy(*pos, str, len); 836 *pos += len; 837 return true; 838} 839 840static bool push_eventlog_int(char** pos, const char* end, jint val) { 841 int space_needed = 1 + sizeof(val); 842 if (end - *pos < space_needed) { 843 LOGW("not enough space for int. remain=%d; needed=%d", 844 (end - *pos), space_needed); 845 return false; 846 } 847 **pos = EVENT_TYPE_INT; 848 (*pos)++; 849 memcpy(*pos, &val, sizeof(val)); 850 *pos += sizeof(val); 851 return true; 852} 853 854// From frameworks/base/core/java/android/content/EventLogTags.logtags: 855#define LOGTAG_BINDER_OPERATION 52004 856 857static void conditionally_log_binder_call(int64_t start_millis, 858 IBinder* target, jint code) { 859 int duration_ms = static_cast<int>(uptimeMillis() - start_millis); 860 861 int sample_percent; 862 if (duration_ms >= 500) { 863 sample_percent = 100; 864 } else { 865 sample_percent = 100 * duration_ms / 500; 866 if (sample_percent == 0) { 867 return; 868 } 869 if (sample_percent < (random() % 100 + 1)) { 870 return; 871 } 872 } 873 874 char process_name[40]; 875 getprocname(getpid(), process_name, sizeof(process_name)); 876 String8 desc(target->getInterfaceDescriptor()); 877 878 char buf[LOGGER_ENTRY_MAX_PAYLOAD]; 879 buf[0] = EVENT_TYPE_LIST; 880 buf[1] = 5; 881 char* pos = &buf[2]; 882 char* end = &buf[LOGGER_ENTRY_MAX_PAYLOAD - 1]; // leave room for final \n 883 if (!push_eventlog_string(&pos, end, desc.string())) return; 884 if (!push_eventlog_int(&pos, end, code)) return; 885 if (!push_eventlog_int(&pos, end, duration_ms)) return; 886 if (!push_eventlog_string(&pos, end, process_name)) return; 887 if (!push_eventlog_int(&pos, end, sample_percent)) return; 888 *(pos++) = '\n'; // conventional with EVENT_TYPE_LIST apparently. 889 android_bWriteLog(LOGTAG_BINDER_OPERATION, buf, pos - buf); 890} 891 892// We only measure binder call durations to potentially log them if 893// we're on the main thread. Unfortunately sim-eng doesn't seem to 894// have gettid, so we just ignore this and don't log if we can't 895// get the thread id. 896static bool should_time_binder_calls() { 897#ifdef HAVE_GETTID 898 return (getpid() == androidGetTid()); 899#else 900#warning no gettid(), so not logging Binder calls... 901 return false; 902#endif 903} 904 905static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, 906 jint code, jobject dataObj, 907 jobject replyObj, jint flags) 908{ 909 if (dataObj == NULL) { 910 jniThrowException(env, "java/lang/NullPointerException", NULL); 911 return JNI_FALSE; 912 } 913 914 Parcel* data = parcelForJavaObject(env, dataObj); 915 if (data == NULL) { 916 return JNI_FALSE; 917 } 918 Parcel* reply = parcelForJavaObject(env, replyObj); 919 if (reply == NULL && replyObj != NULL) { 920 return JNI_FALSE; 921 } 922 923 IBinder* target = (IBinder*) 924 env->GetIntField(obj, gBinderProxyOffsets.mObject); 925 if (target == NULL) { 926 jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); 927 return JNI_FALSE; 928 } 929 930 LOGV("Java code calling transact on %p in Java object %p with code %d\n", 931 target, obj, code); 932 933 // Only log the binder call duration for things on the Java-level main thread. 934 // But if we don't 935 const bool time_binder_calls = should_time_binder_calls(); 936 937 int64_t start_millis; 938 if (time_binder_calls) { 939 start_millis = uptimeMillis(); 940 } 941 //printf("Transact from Java code to %p sending: ", target); data->print(); 942 status_t err = target->transact(code, *data, reply, flags); 943 //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); 944 if (time_binder_calls) { 945 conditionally_log_binder_call(start_millis, target, code); 946 } 947 948 if (err == NO_ERROR) { 949 return JNI_TRUE; 950 } else if (err == UNKNOWN_TRANSACTION) { 951 return JNI_FALSE; 952 } 953 954 signalExceptionForError(env, obj, err); 955 return JNI_FALSE; 956} 957 958static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, 959 jobject recipient, jint flags) 960{ 961 if (recipient == NULL) { 962 jniThrowException(env, "java/lang/NullPointerException", NULL); 963 return; 964 } 965 966 IBinder* target = (IBinder*) 967 env->GetIntField(obj, gBinderProxyOffsets.mObject); 968 if (target == NULL) { 969 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 970 assert(false); 971 } 972 973 LOGV("linkToDeath: binder=%p recipient=%p\n", target, recipient); 974 975 if (!target->localBinder()) { 976 sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient); 977 status_t err = target->linkToDeath(jdr, recipient, flags); 978 if (err != NO_ERROR) { 979 // Failure adding the death recipient, so clear its reference 980 // now. 981 jdr->clearReference(); 982 signalExceptionForError(env, obj, err); 983 } 984 } 985} 986 987static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, 988 jobject recipient, jint flags) 989{ 990 jboolean res = JNI_FALSE; 991 if (recipient == NULL) { 992 jniThrowException(env, "java/lang/NullPointerException", NULL); 993 return res; 994 } 995 996 IBinder* target = (IBinder*) 997 env->GetIntField(obj, gBinderProxyOffsets.mObject); 998 if (target == NULL) { 999 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 1000 return JNI_FALSE; 1001 } 1002 1003 LOGV("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); 1004 1005 if (!target->localBinder()) { 1006 wp<IBinder::DeathRecipient> dr; 1007 status_t err = target->unlinkToDeath(NULL, recipient, flags, &dr); 1008 if (err == NO_ERROR && dr != NULL) { 1009 sp<IBinder::DeathRecipient> sdr = dr.promote(); 1010 JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get()); 1011 if (jdr != NULL) { 1012 jdr->clearReference(); 1013 } 1014 } 1015 if (err == NO_ERROR || err == DEAD_OBJECT) { 1016 res = JNI_TRUE; 1017 } else { 1018 jniThrowException(env, "java/util/NoSuchElementException", 1019 "Death link does not exist"); 1020 } 1021 } 1022 1023 return res; 1024} 1025 1026static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) 1027{ 1028 IBinder* b = (IBinder*) 1029 env->GetIntField(obj, gBinderProxyOffsets.mObject); 1030 LOGV("Destroying BinderProxy %p: binder=%p\n", obj, b); 1031 env->SetIntField(obj, gBinderProxyOffsets.mObject, 0); 1032 b->decStrong(obj); 1033 IPCThreadState::self()->flushCommands(); 1034} 1035 1036// ---------------------------------------------------------------------------- 1037 1038static const JNINativeMethod gBinderProxyMethods[] = { 1039 /* name, signature, funcPtr */ 1040 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, 1041 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, 1042 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, 1043 {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, 1044 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, 1045 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, 1046 {"destroy", "()V", (void*)android_os_BinderProxy_destroy}, 1047}; 1048 1049const char* const kBinderProxyPathName = "android/os/BinderProxy"; 1050 1051static int int_register_android_os_BinderProxy(JNIEnv* env) 1052{ 1053 jclass clazz; 1054 1055 clazz = env->FindClass("java/lang/ref/WeakReference"); 1056 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.ref.WeakReference"); 1057 gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1058 gWeakReferenceOffsets.mGet 1059 = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;"); 1060 assert(gWeakReferenceOffsets.mGet); 1061 1062 clazz = env->FindClass("java/lang/Error"); 1063 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error"); 1064 gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1065 1066 clazz = env->FindClass(kBinderProxyPathName); 1067 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy"); 1068 1069 gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1070 gBinderProxyOffsets.mConstructor 1071 = env->GetMethodID(clazz, "<init>", "()V"); 1072 assert(gBinderProxyOffsets.mConstructor); 1073 gBinderProxyOffsets.mSendDeathNotice 1074 = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); 1075 assert(gBinderProxyOffsets.mSendDeathNotice); 1076 1077 gBinderProxyOffsets.mObject 1078 = env->GetFieldID(clazz, "mObject", "I"); 1079 assert(gBinderProxyOffsets.mObject); 1080 gBinderProxyOffsets.mSelf 1081 = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;"); 1082 assert(gBinderProxyOffsets.mSelf); 1083 1084 return AndroidRuntime::registerNativeMethods( 1085 env, kBinderProxyPathName, 1086 gBinderProxyMethods, NELEM(gBinderProxyMethods)); 1087} 1088 1089// **************************************************************************** 1090// **************************************************************************** 1091// **************************************************************************** 1092 1093static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz) 1094{ 1095 Parcel* parcel = parcelForJavaObject(env, clazz); 1096 return parcel ? parcel->dataSize() : 0; 1097} 1098 1099static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz) 1100{ 1101 Parcel* parcel = parcelForJavaObject(env, clazz); 1102 return parcel ? parcel->dataAvail() : 0; 1103} 1104 1105static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz) 1106{ 1107 Parcel* parcel = parcelForJavaObject(env, clazz); 1108 return parcel ? parcel->dataPosition() : 0; 1109} 1110 1111static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz) 1112{ 1113 Parcel* parcel = parcelForJavaObject(env, clazz); 1114 return parcel ? parcel->dataCapacity() : 0; 1115} 1116 1117static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size) 1118{ 1119 Parcel* parcel = parcelForJavaObject(env, clazz); 1120 if (parcel != NULL) { 1121 const status_t err = parcel->setDataSize(size); 1122 if (err != NO_ERROR) { 1123 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1124 } 1125 } 1126} 1127 1128static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos) 1129{ 1130 Parcel* parcel = parcelForJavaObject(env, clazz); 1131 if (parcel != NULL) { 1132 parcel->setDataPosition(pos); 1133 } 1134} 1135 1136static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size) 1137{ 1138 Parcel* parcel = parcelForJavaObject(env, clazz); 1139 if (parcel != NULL) { 1140 const status_t err = parcel->setDataCapacity(size); 1141 if (err != NO_ERROR) { 1142 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1143 } 1144 } 1145} 1146 1147static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz, 1148 jobject data, jint offset, 1149 jint length) 1150{ 1151 Parcel* parcel = parcelForJavaObject(env, clazz); 1152 if (parcel == NULL) { 1153 return; 1154 } 1155 void *dest; 1156 1157 const status_t err = parcel->writeInt32(length); 1158 if (err != NO_ERROR) { 1159 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1160 } 1161 1162 dest = parcel->writeInplace(length); 1163 1164 if (dest == NULL) { 1165 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1166 return; 1167 } 1168 1169 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0); 1170 if (ar) { 1171 memcpy(dest, ar, length); 1172 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); 1173 } 1174} 1175 1176 1177static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val) 1178{ 1179 Parcel* parcel = parcelForJavaObject(env, clazz); 1180 if (parcel != NULL) { 1181 const status_t err = parcel->writeInt32(val); 1182 if (err != NO_ERROR) { 1183 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1184 } 1185 } 1186} 1187 1188static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val) 1189{ 1190 Parcel* parcel = parcelForJavaObject(env, clazz); 1191 if (parcel != NULL) { 1192 const status_t err = parcel->writeInt64(val); 1193 if (err != NO_ERROR) { 1194 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1195 } 1196 } 1197} 1198 1199static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val) 1200{ 1201 Parcel* parcel = parcelForJavaObject(env, clazz); 1202 if (parcel != NULL) { 1203 const status_t err = parcel->writeFloat(val); 1204 if (err != NO_ERROR) { 1205 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1206 } 1207 } 1208} 1209 1210static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val) 1211{ 1212 Parcel* parcel = parcelForJavaObject(env, clazz); 1213 if (parcel != NULL) { 1214 const status_t err = parcel->writeDouble(val); 1215 if (err != NO_ERROR) { 1216 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1217 } 1218 } 1219} 1220 1221static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val) 1222{ 1223 Parcel* parcel = parcelForJavaObject(env, clazz); 1224 if (parcel != NULL) { 1225 status_t err = NO_MEMORY; 1226 if (val) { 1227 const jchar* str = env->GetStringCritical(val, 0); 1228 if (str) { 1229 err = parcel->writeString16(str, env->GetStringLength(val)); 1230 env->ReleaseStringCritical(val, str); 1231 } 1232 } else { 1233 err = parcel->writeString16(NULL, 0); 1234 } 1235 if (err != NO_ERROR) { 1236 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1237 } 1238 } 1239} 1240 1241static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object) 1242{ 1243 Parcel* parcel = parcelForJavaObject(env, clazz); 1244 if (parcel != NULL) { 1245 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 1246 if (err != NO_ERROR) { 1247 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1248 } 1249 } 1250} 1251 1252static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1253{ 1254 Parcel* parcel = parcelForJavaObject(env, clazz); 1255 if (parcel != NULL) { 1256 const status_t err = parcel->writeDupFileDescriptor( 1257 env->GetIntField(object, gFileDescriptorOffsets.mDescriptor)); 1258 if (err != NO_ERROR) { 1259 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1260 } 1261 } 1262} 1263 1264static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz) 1265{ 1266 jbyteArray ret = NULL; 1267 1268 Parcel* parcel = parcelForJavaObject(env, clazz); 1269 if (parcel != NULL) { 1270 int32_t len = parcel->readInt32(); 1271 1272 // sanity check the stored length against the true data size 1273 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) { 1274 ret = env->NewByteArray(len); 1275 1276 if (ret != NULL) { 1277 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1278 if (a2) { 1279 const void* data = parcel->readInplace(len); 1280 memcpy(a2, data, len); 1281 env->ReleasePrimitiveArrayCritical(ret, a2, 0); 1282 } 1283 } 1284 } 1285 } 1286 1287 return ret; 1288} 1289 1290static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz) 1291{ 1292 Parcel* parcel = parcelForJavaObject(env, clazz); 1293 if (parcel != NULL) { 1294 return parcel->readInt32(); 1295 } 1296 return 0; 1297} 1298 1299static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz) 1300{ 1301 Parcel* parcel = parcelForJavaObject(env, clazz); 1302 if (parcel != NULL) { 1303 return parcel->readInt64(); 1304 } 1305 return 0; 1306} 1307 1308static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz) 1309{ 1310 Parcel* parcel = parcelForJavaObject(env, clazz); 1311 if (parcel != NULL) { 1312 return parcel->readFloat(); 1313 } 1314 return 0; 1315} 1316 1317static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz) 1318{ 1319 Parcel* parcel = parcelForJavaObject(env, clazz); 1320 if (parcel != NULL) { 1321 return parcel->readDouble(); 1322 } 1323 return 0; 1324} 1325 1326static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz) 1327{ 1328 Parcel* parcel = parcelForJavaObject(env, clazz); 1329 if (parcel != NULL) { 1330 size_t len; 1331 const char16_t* str = parcel->readString16Inplace(&len); 1332 if (str) { 1333 return env->NewString(str, len); 1334 } 1335 return NULL; 1336 } 1337 return NULL; 1338} 1339 1340static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz) 1341{ 1342 Parcel* parcel = parcelForJavaObject(env, clazz); 1343 if (parcel != NULL) { 1344 return javaObjectForIBinder(env, parcel->readStrongBinder()); 1345 } 1346 return NULL; 1347} 1348 1349static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz) 1350{ 1351 Parcel* parcel = parcelForJavaObject(env, clazz); 1352 if (parcel != NULL) { 1353 int fd = parcel->readFileDescriptor(); 1354 if (fd < 0) return NULL; 1355 fd = dup(fd); 1356 if (fd < 0) return NULL; 1357 jobject object = env->NewObject( 1358 gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); 1359 if (object != NULL) { 1360 //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd); 1361 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd); 1362 } 1363 return object; 1364 } 1365 return NULL; 1366} 1367 1368static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz, 1369 jstring name, jint mode) 1370{ 1371 if (name == NULL) { 1372 jniThrowException(env, "java/lang/NullPointerException", NULL); 1373 return NULL; 1374 } 1375 const jchar* str = env->GetStringCritical(name, 0); 1376 if (str == NULL) { 1377 // Whatever, whatever. 1378 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1379 return NULL; 1380 } 1381 String8 name8(str, env->GetStringLength(name)); 1382 env->ReleaseStringCritical(name, str); 1383 int flags=0; 1384 switch (mode&0x30000000) { 1385 case 0: 1386 case 0x10000000: 1387 flags = O_RDONLY; 1388 break; 1389 case 0x20000000: 1390 flags = O_WRONLY; 1391 break; 1392 case 0x30000000: 1393 flags = O_RDWR; 1394 break; 1395 } 1396 1397 if (mode&0x08000000) flags |= O_CREAT; 1398 if (mode&0x04000000) flags |= O_TRUNC; 1399 if (mode&0x02000000) flags |= O_APPEND; 1400 1401 int realMode = S_IRWXU|S_IRWXG; 1402 if (mode&0x00000001) realMode |= S_IROTH; 1403 if (mode&0x00000002) realMode |= S_IWOTH; 1404 1405 int fd = open(name8.string(), flags, realMode); 1406 if (fd < 0) { 1407 jniThrowException(env, "java/io/FileNotFoundException", NULL); 1408 return NULL; 1409 } 1410 jobject object = newFileDescriptor(env, fd); 1411 if (object == NULL) { 1412 close(fd); 1413 } 1414 return object; 1415} 1416 1417static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1418{ 1419 int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1420 if (fd >= 0) { 1421 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1); 1422 //LOGI("Closing ParcelFileDescriptor %d\n", fd); 1423 close(fd); 1424 } 1425} 1426 1427static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz) 1428{ 1429 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1430 if (own) { 1431 Parcel* parcel = parcelForJavaObject(env, clazz); 1432 if (parcel != NULL) { 1433 //LOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel); 1434 parcel->freeData(); 1435 } 1436 } 1437} 1438 1439static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt) 1440{ 1441 Parcel* parcel = (Parcel*)parcelInt; 1442 int own = 0; 1443 if (!parcel) { 1444 //LOGI("Initializing obj %p: creating new Parcel\n", clazz); 1445 own = 1; 1446 parcel = new Parcel; 1447 } else { 1448 //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel); 1449 } 1450 if (parcel == NULL) { 1451 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1452 return; 1453 } 1454 //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own); 1455 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own); 1456 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel); 1457} 1458 1459static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz) 1460{ 1461 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1462 if (own) { 1463 Parcel* parcel = parcelForJavaObject(env, clazz); 1464 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1465 //LOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel); 1466 delete parcel; 1467 } else { 1468 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1469 //LOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz); 1470 } 1471} 1472 1473static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz) 1474{ 1475 Parcel* parcel = parcelForJavaObject(env, clazz); 1476 if (parcel == NULL) { 1477 return NULL; 1478 } 1479 1480 // do not marshall if there are binder objects in the parcel 1481 if (parcel->objectsCount()) 1482 { 1483 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); 1484 return NULL; 1485 } 1486 1487 jbyteArray ret = env->NewByteArray(parcel->dataSize()); 1488 1489 if (ret != NULL) 1490 { 1491 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1492 if (array != NULL) 1493 { 1494 memcpy(array, parcel->data(), parcel->dataSize()); 1495 env->ReleasePrimitiveArrayCritical(ret, array, 0); 1496 } 1497 } 1498 1499 return ret; 1500} 1501 1502static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length) 1503{ 1504 Parcel* parcel = parcelForJavaObject(env, clazz); 1505 if (parcel == NULL || length < 0) { 1506 return; 1507 } 1508 1509 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0); 1510 if (array) 1511 { 1512 parcel->setDataSize(length); 1513 parcel->setDataPosition(0); 1514 1515 void* raw = parcel->writeInplace(length); 1516 memcpy(raw, (array + offset), length); 1517 1518 env->ReleasePrimitiveArrayCritical(data, array, 0); 1519 } 1520} 1521 1522static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length) 1523{ 1524 Parcel* thisParcel = parcelForJavaObject(env, clazz); 1525 if (thisParcel == NULL) { 1526 return; 1527 } 1528 Parcel* otherParcel = parcelForJavaObject(env, parcel); 1529 if (otherParcel == NULL) { 1530 return; 1531 } 1532 1533 (void) thisParcel->appendFrom(otherParcel, offset, length); 1534} 1535 1536static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz) 1537{ 1538 jboolean ret = JNI_FALSE; 1539 Parcel* parcel = parcelForJavaObject(env, clazz); 1540 if (parcel != NULL) { 1541 if (parcel->hasFileDescriptors()) { 1542 ret = JNI_TRUE; 1543 } 1544 } 1545 return ret; 1546} 1547 1548static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name) 1549{ 1550 Parcel* parcel = parcelForJavaObject(env, clazz); 1551 if (parcel != NULL) { 1552 // In the current implementation, the token is just the serialized interface name that 1553 // the caller expects to be invoking 1554 const jchar* str = env->GetStringCritical(name, 0); 1555 if (str != NULL) { 1556 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 1557 env->ReleaseStringCritical(name, str); 1558 } 1559 } 1560} 1561 1562static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name) 1563{ 1564 jboolean ret = JNI_FALSE; 1565 1566 Parcel* parcel = parcelForJavaObject(env, clazz); 1567 if (parcel != NULL) { 1568 const jchar* str = env->GetStringCritical(name, 0); 1569 if (str) { 1570 IPCThreadState* threadState = IPCThreadState::self(); 1571 const int32_t oldPolicy = threadState->getStrictModePolicy(); 1572 const bool isValid = parcel->enforceInterface( 1573 String16(str, env->GetStringLength(name)), 1574 threadState); 1575 env->ReleaseStringCritical(name, str); 1576 if (isValid) { 1577 const int32_t newPolicy = threadState->getStrictModePolicy(); 1578 if (oldPolicy != newPolicy) { 1579 // Need to keep the Java-level thread-local strict 1580 // mode policy in sync for the libcore 1581 // enforcements, which involves an upcall back 1582 // into Java. (We can't modify the 1583 // Parcel.enforceInterface signature, as it's 1584 // pseudo-public, and used via AIDL 1585 // auto-generation...) 1586 set_dalvik_blockguard_policy(env, newPolicy); 1587 } 1588 return; // everything was correct -> return silently 1589 } 1590 } 1591 } 1592 1593 // all error conditions wind up here 1594 jniThrowException(env, "java/lang/SecurityException", 1595 "Binder invocation to an incorrect interface"); 1596} 1597 1598// ---------------------------------------------------------------------------- 1599 1600static const JNINativeMethod gParcelMethods[] = { 1601 {"dataSize", "()I", (void*)android_os_Parcel_dataSize}, 1602 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail}, 1603 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition}, 1604 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity}, 1605 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize}, 1606 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition}, 1607 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity}, 1608 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative}, 1609 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt}, 1610 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong}, 1611 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat}, 1612 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble}, 1613 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString}, 1614 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, 1615 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor}, 1616 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray}, 1617 {"readInt", "()I", (void*)android_os_Parcel_readInt}, 1618 {"readLong", "()J", (void*)android_os_Parcel_readLong}, 1619 {"readFloat", "()F", (void*)android_os_Parcel_readFloat}, 1620 {"readDouble", "()D", (void*)android_os_Parcel_readDouble}, 1621 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString}, 1622 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, 1623 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor}, 1624 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor}, 1625 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor}, 1626 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer}, 1627 {"init", "(I)V", (void*)android_os_Parcel_init}, 1628 {"destroy", "()V", (void*)android_os_Parcel_destroy}, 1629 {"marshall", "()[B", (void*)android_os_Parcel_marshall}, 1630 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall}, 1631 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom}, 1632 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors}, 1633 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken}, 1634 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface}, 1635}; 1636 1637const char* const kParcelPathName = "android/os/Parcel"; 1638 1639static int int_register_android_os_Parcel(JNIEnv* env) 1640{ 1641 jclass clazz; 1642 1643 clazz = env->FindClass("android/util/Log"); 1644 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log"); 1645 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1646 gLogOffsets.mLogE = env->GetStaticMethodID( 1647 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I"); 1648 assert(gLogOffsets.mLogE); 1649 1650 clazz = env->FindClass("java/io/FileDescriptor"); 1651 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); 1652 gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1653 gFileDescriptorOffsets.mConstructor 1654 = env->GetMethodID(clazz, "<init>", "()V"); 1655 gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); 1656 LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, 1657 "Unable to find descriptor field in java.io.FileDescriptor"); 1658 1659 clazz = env->FindClass("android/os/ParcelFileDescriptor"); 1660 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 1661 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1662 gParcelFileDescriptorOffsets.mConstructor 1663 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 1664 1665 clazz = env->FindClass(kParcelPathName); 1666 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel"); 1667 1668 gParcelOffsets.mObject 1669 = env->GetFieldID(clazz, "mObject", "I"); 1670 gParcelOffsets.mOwnObject 1671 = env->GetFieldID(clazz, "mOwnObject", "I"); 1672 1673 clazz = env->FindClass("android/os/StrictMode"); 1674 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode"); 1675 gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1676 gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID( 1677 clazz, "onBinderStrictModePolicyChange", "(I)V"); 1678 LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL, 1679 "Unable to find strict mode callback."); 1680 1681 return AndroidRuntime::registerNativeMethods( 1682 env, kParcelPathName, 1683 gParcelMethods, NELEM(gParcelMethods)); 1684} 1685 1686int register_android_os_Binder(JNIEnv* env) 1687{ 1688 if (int_register_android_os_Binder(env) < 0) 1689 return -1; 1690 if (int_register_android_os_BinderInternal(env) < 0) 1691 return -1; 1692 if (int_register_android_os_BinderProxy(env) < 0) 1693 return -1; 1694 if (int_register_android_os_Parcel(env) < 0) 1695 return -1; 1696 return 0; 1697} 1698 1699namespace android { 1700 1701// Returns the Unix file descriptor for a ParcelFileDescriptor object 1702int getParcelFileDescriptorFD(JNIEnv* env, jobject object) 1703{ 1704 return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1705} 1706 1707} 1708