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