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