android_util_Binder.cpp revision a28b83ee04ca25100781f37a50665d6e1b05e3a2
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 1156 const status_t err = parcel->writeInt32(length); 1157 if (err != NO_ERROR) { 1158 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1159 } 1160 1161 void* dest = parcel->writeInplace(length); 1162 if (dest == NULL) { 1163 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1164 return; 1165 } 1166 1167 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0); 1168 if (ar) { 1169 memcpy(dest, ar + offset, length); 1170 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); 1171 } 1172} 1173 1174 1175static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val) 1176{ 1177 Parcel* parcel = parcelForJavaObject(env, clazz); 1178 if (parcel != NULL) { 1179 const status_t err = parcel->writeInt32(val); 1180 if (err != NO_ERROR) { 1181 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1182 } 1183 } 1184} 1185 1186static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val) 1187{ 1188 Parcel* parcel = parcelForJavaObject(env, clazz); 1189 if (parcel != NULL) { 1190 const status_t err = parcel->writeInt64(val); 1191 if (err != NO_ERROR) { 1192 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1193 } 1194 } 1195} 1196 1197static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val) 1198{ 1199 Parcel* parcel = parcelForJavaObject(env, clazz); 1200 if (parcel != NULL) { 1201 const status_t err = parcel->writeFloat(val); 1202 if (err != NO_ERROR) { 1203 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1204 } 1205 } 1206} 1207 1208static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val) 1209{ 1210 Parcel* parcel = parcelForJavaObject(env, clazz); 1211 if (parcel != NULL) { 1212 const status_t err = parcel->writeDouble(val); 1213 if (err != NO_ERROR) { 1214 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1215 } 1216 } 1217} 1218 1219static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val) 1220{ 1221 Parcel* parcel = parcelForJavaObject(env, clazz); 1222 if (parcel != NULL) { 1223 status_t err = NO_MEMORY; 1224 if (val) { 1225 const jchar* str = env->GetStringCritical(val, 0); 1226 if (str) { 1227 err = parcel->writeString16(str, env->GetStringLength(val)); 1228 env->ReleaseStringCritical(val, str); 1229 } 1230 } else { 1231 err = parcel->writeString16(NULL, 0); 1232 } 1233 if (err != NO_ERROR) { 1234 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1235 } 1236 } 1237} 1238 1239static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object) 1240{ 1241 Parcel* parcel = parcelForJavaObject(env, clazz); 1242 if (parcel != NULL) { 1243 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 1244 if (err != NO_ERROR) { 1245 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1246 } 1247 } 1248} 1249 1250static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1251{ 1252 Parcel* parcel = parcelForJavaObject(env, clazz); 1253 if (parcel != NULL) { 1254 const status_t err = parcel->writeDupFileDescriptor( 1255 env->GetIntField(object, gFileDescriptorOffsets.mDescriptor)); 1256 if (err != NO_ERROR) { 1257 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1258 } 1259 } 1260} 1261 1262static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz) 1263{ 1264 jbyteArray ret = NULL; 1265 1266 Parcel* parcel = parcelForJavaObject(env, clazz); 1267 if (parcel != NULL) { 1268 int32_t len = parcel->readInt32(); 1269 1270 // sanity check the stored length against the true data size 1271 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) { 1272 ret = env->NewByteArray(len); 1273 1274 if (ret != NULL) { 1275 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1276 if (a2) { 1277 const void* data = parcel->readInplace(len); 1278 memcpy(a2, data, len); 1279 env->ReleasePrimitiveArrayCritical(ret, a2, 0); 1280 } 1281 } 1282 } 1283 } 1284 1285 return ret; 1286} 1287 1288static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz) 1289{ 1290 Parcel* parcel = parcelForJavaObject(env, clazz); 1291 if (parcel != NULL) { 1292 return parcel->readInt32(); 1293 } 1294 return 0; 1295} 1296 1297static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz) 1298{ 1299 Parcel* parcel = parcelForJavaObject(env, clazz); 1300 if (parcel != NULL) { 1301 return parcel->readInt64(); 1302 } 1303 return 0; 1304} 1305 1306static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz) 1307{ 1308 Parcel* parcel = parcelForJavaObject(env, clazz); 1309 if (parcel != NULL) { 1310 return parcel->readFloat(); 1311 } 1312 return 0; 1313} 1314 1315static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz) 1316{ 1317 Parcel* parcel = parcelForJavaObject(env, clazz); 1318 if (parcel != NULL) { 1319 return parcel->readDouble(); 1320 } 1321 return 0; 1322} 1323 1324static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz) 1325{ 1326 Parcel* parcel = parcelForJavaObject(env, clazz); 1327 if (parcel != NULL) { 1328 size_t len; 1329 const char16_t* str = parcel->readString16Inplace(&len); 1330 if (str) { 1331 return env->NewString(str, len); 1332 } 1333 return NULL; 1334 } 1335 return NULL; 1336} 1337 1338static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz) 1339{ 1340 Parcel* parcel = parcelForJavaObject(env, clazz); 1341 if (parcel != NULL) { 1342 return javaObjectForIBinder(env, parcel->readStrongBinder()); 1343 } 1344 return NULL; 1345} 1346 1347static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz) 1348{ 1349 Parcel* parcel = parcelForJavaObject(env, clazz); 1350 if (parcel != NULL) { 1351 int fd = parcel->readFileDescriptor(); 1352 if (fd < 0) return NULL; 1353 fd = dup(fd); 1354 if (fd < 0) return NULL; 1355 jobject object = env->NewObject( 1356 gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); 1357 if (object != NULL) { 1358 //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd); 1359 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd); 1360 } 1361 return object; 1362 } 1363 return NULL; 1364} 1365 1366static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz, 1367 jstring name, jint mode) 1368{ 1369 if (name == NULL) { 1370 jniThrowException(env, "java/lang/NullPointerException", NULL); 1371 return NULL; 1372 } 1373 const jchar* str = env->GetStringCritical(name, 0); 1374 if (str == NULL) { 1375 // Whatever, whatever. 1376 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1377 return NULL; 1378 } 1379 String8 name8(str, env->GetStringLength(name)); 1380 env->ReleaseStringCritical(name, str); 1381 int flags=0; 1382 switch (mode&0x30000000) { 1383 case 0: 1384 case 0x10000000: 1385 flags = O_RDONLY; 1386 break; 1387 case 0x20000000: 1388 flags = O_WRONLY; 1389 break; 1390 case 0x30000000: 1391 flags = O_RDWR; 1392 break; 1393 } 1394 1395 if (mode&0x08000000) flags |= O_CREAT; 1396 if (mode&0x04000000) flags |= O_TRUNC; 1397 if (mode&0x02000000) flags |= O_APPEND; 1398 1399 int realMode = S_IRWXU|S_IRWXG; 1400 if (mode&0x00000001) realMode |= S_IROTH; 1401 if (mode&0x00000002) realMode |= S_IWOTH; 1402 1403 int fd = open(name8.string(), flags, realMode); 1404 if (fd < 0) { 1405 jniThrowException(env, "java/io/FileNotFoundException", NULL); 1406 return NULL; 1407 } 1408 jobject object = newFileDescriptor(env, fd); 1409 if (object == NULL) { 1410 close(fd); 1411 } 1412 return object; 1413} 1414 1415static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1416{ 1417 int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1418 if (fd >= 0) { 1419 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1); 1420 //LOGI("Closing ParcelFileDescriptor %d\n", fd); 1421 close(fd); 1422 } 1423} 1424 1425static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz) 1426{ 1427 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1428 if (own) { 1429 Parcel* parcel = parcelForJavaObject(env, clazz); 1430 if (parcel != NULL) { 1431 //LOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel); 1432 parcel->freeData(); 1433 } 1434 } 1435} 1436 1437static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt) 1438{ 1439 Parcel* parcel = (Parcel*)parcelInt; 1440 int own = 0; 1441 if (!parcel) { 1442 //LOGI("Initializing obj %p: creating new Parcel\n", clazz); 1443 own = 1; 1444 parcel = new Parcel; 1445 } else { 1446 //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel); 1447 } 1448 if (parcel == NULL) { 1449 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1450 return; 1451 } 1452 //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own); 1453 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own); 1454 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel); 1455} 1456 1457static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz) 1458{ 1459 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1460 if (own) { 1461 Parcel* parcel = parcelForJavaObject(env, clazz); 1462 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1463 //LOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel); 1464 delete parcel; 1465 } else { 1466 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1467 //LOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz); 1468 } 1469} 1470 1471static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz) 1472{ 1473 Parcel* parcel = parcelForJavaObject(env, clazz); 1474 if (parcel == NULL) { 1475 return NULL; 1476 } 1477 1478 // do not marshall if there are binder objects in the parcel 1479 if (parcel->objectsCount()) 1480 { 1481 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); 1482 return NULL; 1483 } 1484 1485 jbyteArray ret = env->NewByteArray(parcel->dataSize()); 1486 1487 if (ret != NULL) 1488 { 1489 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1490 if (array != NULL) 1491 { 1492 memcpy(array, parcel->data(), parcel->dataSize()); 1493 env->ReleasePrimitiveArrayCritical(ret, array, 0); 1494 } 1495 } 1496 1497 return ret; 1498} 1499 1500static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length) 1501{ 1502 Parcel* parcel = parcelForJavaObject(env, clazz); 1503 if (parcel == NULL || length < 0) { 1504 return; 1505 } 1506 1507 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0); 1508 if (array) 1509 { 1510 parcel->setDataSize(length); 1511 parcel->setDataPosition(0); 1512 1513 void* raw = parcel->writeInplace(length); 1514 memcpy(raw, (array + offset), length); 1515 1516 env->ReleasePrimitiveArrayCritical(data, array, 0); 1517 } 1518} 1519 1520static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length) 1521{ 1522 Parcel* thisParcel = parcelForJavaObject(env, clazz); 1523 if (thisParcel == NULL) { 1524 return; 1525 } 1526 Parcel* otherParcel = parcelForJavaObject(env, parcel); 1527 if (otherParcel == NULL) { 1528 return; 1529 } 1530 1531 (void) thisParcel->appendFrom(otherParcel, offset, length); 1532} 1533 1534static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz) 1535{ 1536 jboolean ret = JNI_FALSE; 1537 Parcel* parcel = parcelForJavaObject(env, clazz); 1538 if (parcel != NULL) { 1539 if (parcel->hasFileDescriptors()) { 1540 ret = JNI_TRUE; 1541 } 1542 } 1543 return ret; 1544} 1545 1546static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name) 1547{ 1548 Parcel* parcel = parcelForJavaObject(env, clazz); 1549 if (parcel != NULL) { 1550 // In the current implementation, the token is just the serialized interface name that 1551 // the caller expects to be invoking 1552 const jchar* str = env->GetStringCritical(name, 0); 1553 if (str != NULL) { 1554 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 1555 env->ReleaseStringCritical(name, str); 1556 } 1557 } 1558} 1559 1560static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name) 1561{ 1562 jboolean ret = JNI_FALSE; 1563 1564 Parcel* parcel = parcelForJavaObject(env, clazz); 1565 if (parcel != NULL) { 1566 const jchar* str = env->GetStringCritical(name, 0); 1567 if (str) { 1568 IPCThreadState* threadState = IPCThreadState::self(); 1569 const int32_t oldPolicy = threadState->getStrictModePolicy(); 1570 const bool isValid = parcel->enforceInterface( 1571 String16(str, env->GetStringLength(name)), 1572 threadState); 1573 env->ReleaseStringCritical(name, str); 1574 if (isValid) { 1575 const int32_t newPolicy = threadState->getStrictModePolicy(); 1576 if (oldPolicy != newPolicy) { 1577 // Need to keep the Java-level thread-local strict 1578 // mode policy in sync for the libcore 1579 // enforcements, which involves an upcall back 1580 // into Java. (We can't modify the 1581 // Parcel.enforceInterface signature, as it's 1582 // pseudo-public, and used via AIDL 1583 // auto-generation...) 1584 set_dalvik_blockguard_policy(env, newPolicy); 1585 } 1586 return; // everything was correct -> return silently 1587 } 1588 } 1589 } 1590 1591 // all error conditions wind up here 1592 jniThrowException(env, "java/lang/SecurityException", 1593 "Binder invocation to an incorrect interface"); 1594} 1595 1596// ---------------------------------------------------------------------------- 1597 1598static const JNINativeMethod gParcelMethods[] = { 1599 {"dataSize", "()I", (void*)android_os_Parcel_dataSize}, 1600 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail}, 1601 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition}, 1602 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity}, 1603 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize}, 1604 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition}, 1605 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity}, 1606 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative}, 1607 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt}, 1608 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong}, 1609 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat}, 1610 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble}, 1611 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString}, 1612 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, 1613 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor}, 1614 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray}, 1615 {"readInt", "()I", (void*)android_os_Parcel_readInt}, 1616 {"readLong", "()J", (void*)android_os_Parcel_readLong}, 1617 {"readFloat", "()F", (void*)android_os_Parcel_readFloat}, 1618 {"readDouble", "()D", (void*)android_os_Parcel_readDouble}, 1619 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString}, 1620 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, 1621 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor}, 1622 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor}, 1623 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor}, 1624 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer}, 1625 {"init", "(I)V", (void*)android_os_Parcel_init}, 1626 {"destroy", "()V", (void*)android_os_Parcel_destroy}, 1627 {"marshall", "()[B", (void*)android_os_Parcel_marshall}, 1628 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall}, 1629 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom}, 1630 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors}, 1631 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken}, 1632 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface}, 1633}; 1634 1635const char* const kParcelPathName = "android/os/Parcel"; 1636 1637static int int_register_android_os_Parcel(JNIEnv* env) 1638{ 1639 jclass clazz; 1640 1641 clazz = env->FindClass("android/util/Log"); 1642 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log"); 1643 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1644 gLogOffsets.mLogE = env->GetStaticMethodID( 1645 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I"); 1646 assert(gLogOffsets.mLogE); 1647 1648 clazz = env->FindClass("java/io/FileDescriptor"); 1649 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); 1650 gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1651 gFileDescriptorOffsets.mConstructor 1652 = env->GetMethodID(clazz, "<init>", "()V"); 1653 gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); 1654 LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, 1655 "Unable to find descriptor field in java.io.FileDescriptor"); 1656 1657 clazz = env->FindClass("android/os/ParcelFileDescriptor"); 1658 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 1659 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1660 gParcelFileDescriptorOffsets.mConstructor 1661 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 1662 1663 clazz = env->FindClass(kParcelPathName); 1664 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel"); 1665 1666 gParcelOffsets.mObject 1667 = env->GetFieldID(clazz, "mObject", "I"); 1668 gParcelOffsets.mOwnObject 1669 = env->GetFieldID(clazz, "mOwnObject", "I"); 1670 1671 clazz = env->FindClass("android/os/StrictMode"); 1672 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode"); 1673 gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1674 gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID( 1675 clazz, "onBinderStrictModePolicyChange", "(I)V"); 1676 LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL, 1677 "Unable to find strict mode callback."); 1678 1679 return AndroidRuntime::registerNativeMethods( 1680 env, kParcelPathName, 1681 gParcelMethods, NELEM(gParcelMethods)); 1682} 1683 1684int register_android_os_Binder(JNIEnv* env) 1685{ 1686 if (int_register_android_os_Binder(env) < 0) 1687 return -1; 1688 if (int_register_android_os_BinderInternal(env) < 0) 1689 return -1; 1690 if (int_register_android_os_BinderProxy(env) < 0) 1691 return -1; 1692 if (int_register_android_os_Parcel(env) < 0) 1693 return -1; 1694 return 0; 1695} 1696 1697namespace android { 1698 1699// Returns the Unix file descriptor for a ParcelFileDescriptor object 1700int getParcelFileDescriptorFD(JNIEnv* env, jobject object) 1701{ 1702 return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1703} 1704 1705} 1706