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