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