android_util_Binder.cpp revision 5b6da1aee884d32d8140e27c5b5b4d16ea4a37c8
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_os_Parcel.h" 21#include "android_util_Binder.h" 22 23#include "JNIHelp.h" 24 25#include <fcntl.h> 26#include <inttypes.h> 27#include <stdio.h> 28#include <sys/stat.h> 29#include <sys/types.h> 30#include <unistd.h> 31 32#include <utils/Atomic.h> 33#include <binder/IInterface.h> 34#include <binder/IPCThreadState.h> 35#include <utils/Log.h> 36#include <utils/SystemClock.h> 37#include <utils/List.h> 38#include <utils/KeyedVector.h> 39#include <log/logger.h> 40#include <binder/Parcel.h> 41#include <binder/ProcessState.h> 42#include <binder/IServiceManager.h> 43#include <utils/threads.h> 44#include <utils/String8.h> 45 46#include <ScopedUtfChars.h> 47#include <ScopedLocalRef.h> 48 49#include <android_runtime/AndroidRuntime.h> 50 51//#undef ALOGV 52//#define ALOGV(...) fprintf(stderr, __VA_ARGS__) 53 54#define DEBUG_DEATH 0 55#if DEBUG_DEATH 56#define LOGDEATH ALOGD 57#else 58#define LOGDEATH ALOGV 59#endif 60 61using namespace android; 62 63// ---------------------------------------------------------------------------- 64 65static struct bindernative_offsets_t 66{ 67 // Class state. 68 jclass mClass; 69 jmethodID mExecTransact; 70 71 // Object state. 72 jfieldID mObject; 73 74} gBinderOffsets; 75 76// ---------------------------------------------------------------------------- 77 78static struct binderinternal_offsets_t 79{ 80 // Class state. 81 jclass mClass; 82 jmethodID mForceGc; 83 84} gBinderInternalOffsets; 85 86// ---------------------------------------------------------------------------- 87 88static struct debug_offsets_t 89{ 90 // Class state. 91 jclass mClass; 92 93} gDebugOffsets; 94 95// ---------------------------------------------------------------------------- 96 97static struct error_offsets_t 98{ 99 jclass mClass; 100} gErrorOffsets; 101 102// ---------------------------------------------------------------------------- 103 104static struct binderproxy_offsets_t 105{ 106 // Class state. 107 jclass mClass; 108 jmethodID mConstructor; 109 jmethodID mSendDeathNotice; 110 111 // Object state. 112 jfieldID mObject; 113 jfieldID mSelf; 114 jfieldID mOrgue; 115 116} gBinderProxyOffsets; 117 118static struct class_offsets_t 119{ 120 jmethodID mGetName; 121} gClassOffsets; 122 123// ---------------------------------------------------------------------------- 124 125static struct log_offsets_t 126{ 127 // Class state. 128 jclass mClass; 129 jmethodID mLogE; 130} gLogOffsets; 131 132static struct parcel_file_descriptor_offsets_t 133{ 134 jclass mClass; 135 jmethodID mConstructor; 136} gParcelFileDescriptorOffsets; 137 138static struct strict_mode_callback_offsets_t 139{ 140 jclass mClass; 141 jmethodID mCallback; 142} gStrictModeCallbackOffsets; 143 144// **************************************************************************** 145// **************************************************************************** 146// **************************************************************************** 147 148static volatile int32_t gNumRefsCreated = 0; 149static volatile int32_t gNumProxyRefs = 0; 150static volatile int32_t gNumLocalRefs = 0; 151static volatile int32_t gNumDeathRefs = 0; 152 153static void incRefsCreated(JNIEnv* env) 154{ 155 int old = android_atomic_inc(&gNumRefsCreated); 156 if (old == 200) { 157 android_atomic_and(0, &gNumRefsCreated); 158 env->CallStaticVoidMethod(gBinderInternalOffsets.mClass, 159 gBinderInternalOffsets.mForceGc); 160 } else { 161 ALOGV("Now have %d binder ops", old); 162 } 163} 164 165static JavaVM* jnienv_to_javavm(JNIEnv* env) 166{ 167 JavaVM* vm; 168 return env->GetJavaVM(&vm) >= 0 ? vm : NULL; 169} 170 171static JNIEnv* javavm_to_jnienv(JavaVM* vm) 172{ 173 JNIEnv* env; 174 return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL; 175} 176 177static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) 178{ 179 env->ExceptionClear(); 180 181 jstring tagstr = env->NewStringUTF(LOG_TAG); 182 jstring msgstr = env->NewStringUTF(msg); 183 184 if ((tagstr == NULL) || (msgstr == NULL)) { 185 env->ExceptionClear(); /* assume exception (OOM?) was thrown */ 186 ALOGE("Unable to call Log.e()\n"); 187 ALOGE("%s", msg); 188 goto bail; 189 } 190 191 env->CallStaticIntMethod( 192 gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep); 193 if (env->ExceptionCheck()) { 194 /* attempting to log the failure has failed */ 195 ALOGW("Failed trying to log exception, msg='%s'\n", msg); 196 env->ExceptionClear(); 197 } 198 199 if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { 200 /* 201 * It's an Error: Reraise the exception, detach this thread, and 202 * wait for the fireworks. Die even more blatantly after a minute 203 * if the gentler attempt doesn't do the trick. 204 * 205 * The GetJavaVM function isn't on the "approved" list of JNI calls 206 * that can be made while an exception is pending, so we want to 207 * get the VM ptr, throw the exception, and then detach the thread. 208 */ 209 JavaVM* vm = jnienv_to_javavm(env); 210 env->Throw(excep); 211 vm->DetachCurrentThread(); 212 sleep(60); 213 ALOGE("Forcefully exiting"); 214 exit(1); 215 *((int *) 1) = 1; 216 } 217 218bail: 219 /* discard local refs created for us by VM */ 220 env->DeleteLocalRef(tagstr); 221 env->DeleteLocalRef(msgstr); 222} 223 224class JavaBBinderHolder; 225 226class JavaBBinder : public BBinder 227{ 228public: 229 JavaBBinder(JNIEnv* env, jobject object) 230 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) 231 { 232 ALOGV("Creating JavaBBinder %p\n", this); 233 android_atomic_inc(&gNumLocalRefs); 234 incRefsCreated(env); 235 } 236 237 bool checkSubclass(const void* subclassID) const 238 { 239 return subclassID == &gBinderOffsets; 240 } 241 242 jobject object() const 243 { 244 return mObject; 245 } 246 247protected: 248 virtual ~JavaBBinder() 249 { 250 ALOGV("Destroying JavaBBinder %p\n", this); 251 android_atomic_dec(&gNumLocalRefs); 252 JNIEnv* env = javavm_to_jnienv(mVM); 253 env->DeleteGlobalRef(mObject); 254 } 255 256 virtual status_t onTransact( 257 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) 258 { 259 JNIEnv* env = javavm_to_jnienv(mVM); 260 261 ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); 262 263 IPCThreadState* thread_state = IPCThreadState::self(); 264 const int strict_policy_before = thread_state->getStrictModePolicy(); 265 thread_state->setLastTransactionBinderFlags(flags); 266 267 //printf("Transact from %p to Java code sending: ", this); 268 //data.print(); 269 //printf("\n"); 270 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, 271 code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); 272 jthrowable excep = env->ExceptionOccurred(); 273 274 if (excep) { 275 report_exception(env, excep, 276 "*** Uncaught remote exception! " 277 "(Exceptions are not yet supported across processes.)"); 278 res = JNI_FALSE; 279 280 /* clean up JNI local ref -- we don't return to Java code */ 281 env->DeleteLocalRef(excep); 282 } 283 284 // Restore the Java binder thread's state if it changed while 285 // processing a call (as it would if the Parcel's header had a 286 // new policy mask and Parcel.enforceInterface() changed 287 // it...) 288 const int strict_policy_after = thread_state->getStrictModePolicy(); 289 if (strict_policy_after != strict_policy_before) { 290 // Our thread-local... 291 thread_state->setStrictModePolicy(strict_policy_before); 292 // And the Java-level thread-local... 293 set_dalvik_blockguard_policy(env, strict_policy_before); 294 } 295 296 jthrowable excep2 = env->ExceptionOccurred(); 297 if (excep2) { 298 report_exception(env, excep2, 299 "*** Uncaught exception in onBinderStrictModePolicyChange"); 300 /* clean up JNI local ref -- we don't return to Java code */ 301 env->DeleteLocalRef(excep2); 302 } 303 304 // Need to always call through the native implementation of 305 // SYSPROPS_TRANSACTION. 306 if (code == SYSPROPS_TRANSACTION) { 307 BBinder::onTransact(code, data, reply, flags); 308 } 309 310 //aout << "onTransact to Java code; result=" << res << endl 311 // << "Transact from " << this << " to Java code returning " 312 // << reply << ": " << *reply << endl; 313 return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; 314 } 315 316 virtual status_t dump(int fd, const Vector<String16>& args) 317 { 318 return 0; 319 } 320 321private: 322 JavaVM* const mVM; 323 jobject const mObject; 324}; 325 326// ---------------------------------------------------------------------------- 327 328class JavaBBinderHolder : public RefBase 329{ 330public: 331 sp<JavaBBinder> get(JNIEnv* env, jobject obj) 332 { 333 AutoMutex _l(mLock); 334 sp<JavaBBinder> b = mBinder.promote(); 335 if (b == NULL) { 336 b = new JavaBBinder(env, obj); 337 mBinder = b; 338 ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n", 339 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount()); 340 } 341 342 return b; 343 } 344 345 sp<JavaBBinder> getExisting() 346 { 347 AutoMutex _l(mLock); 348 return mBinder.promote(); 349 } 350 351private: 352 Mutex mLock; 353 wp<JavaBBinder> mBinder; 354}; 355 356// ---------------------------------------------------------------------------- 357 358// Per-IBinder death recipient bookkeeping. This is how we reconcile local jobject 359// death recipient references passed in through JNI with the permanent corresponding 360// JavaDeathRecipient objects. 361 362class JavaDeathRecipient; 363 364class DeathRecipientList : public RefBase { 365 List< sp<JavaDeathRecipient> > mList; 366 Mutex mLock; 367 368public: 369 DeathRecipientList(); 370 ~DeathRecipientList(); 371 372 void add(const sp<JavaDeathRecipient>& recipient); 373 void remove(const sp<JavaDeathRecipient>& recipient); 374 sp<JavaDeathRecipient> find(jobject recipient); 375}; 376 377// ---------------------------------------------------------------------------- 378 379class JavaDeathRecipient : public IBinder::DeathRecipient 380{ 381public: 382 JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list) 383 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), 384 mObjectWeak(NULL), mList(list) 385 { 386 // These objects manage their own lifetimes so are responsible for final bookkeeping. 387 // The list holds a strong reference to this object. 388 LOGDEATH("Adding JDR %p to DRL %p", this, list.get()); 389 list->add(this); 390 391 android_atomic_inc(&gNumDeathRefs); 392 incRefsCreated(env); 393 } 394 395 void binderDied(const wp<IBinder>& who) 396 { 397 LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this); 398 if (mObject != NULL) { 399 JNIEnv* env = javavm_to_jnienv(mVM); 400 401 env->CallStaticVoidMethod(gBinderProxyOffsets.mClass, 402 gBinderProxyOffsets.mSendDeathNotice, mObject); 403 jthrowable excep = env->ExceptionOccurred(); 404 if (excep) { 405 report_exception(env, excep, 406 "*** Uncaught exception returned from death notification!"); 407 } 408 409 // Demote from strong ref to weak after binderDied() has been delivered, 410 // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed. 411 mObjectWeak = env->NewWeakGlobalRef(mObject); 412 env->DeleteGlobalRef(mObject); 413 mObject = NULL; 414 } 415 } 416 417 void clearReference() 418 { 419 sp<DeathRecipientList> list = mList.promote(); 420 if (list != NULL) { 421 LOGDEATH("Removing JDR %p from DRL %p", this, list.get()); 422 list->remove(this); 423 } else { 424 LOGDEATH("clearReference() on JDR %p but DRL wp purged", this); 425 } 426 } 427 428 bool matches(jobject obj) { 429 bool result; 430 JNIEnv* env = javavm_to_jnienv(mVM); 431 432 if (mObject != NULL) { 433 result = env->IsSameObject(obj, mObject); 434 } else { 435 jobject me = env->NewLocalRef(mObjectWeak); 436 result = env->IsSameObject(obj, me); 437 env->DeleteLocalRef(me); 438 } 439 return result; 440 } 441 442 void warnIfStillLive() { 443 if (mObject != NULL) { 444 // Okay, something is wrong -- we have a hard reference to a live death 445 // recipient on the VM side, but the list is being torn down. 446 JNIEnv* env = javavm_to_jnienv(mVM); 447 ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject)); 448 ScopedLocalRef<jstring> nameRef(env, 449 (jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName)); 450 ScopedUtfChars nameUtf(env, nameRef.get()); 451 if (nameUtf.c_str() != NULL) { 452 ALOGW("BinderProxy is being destroyed but the application did not call " 453 "unlinkToDeath to unlink all of its death recipients beforehand. " 454 "Releasing leaked death recipient: %s", nameUtf.c_str()); 455 } else { 456 ALOGW("BinderProxy being destroyed; unable to get DR object name"); 457 env->ExceptionClear(); 458 } 459 } 460 } 461 462protected: 463 virtual ~JavaDeathRecipient() 464 { 465 //ALOGI("Removing death ref: recipient=%p\n", mObject); 466 android_atomic_dec(&gNumDeathRefs); 467 JNIEnv* env = javavm_to_jnienv(mVM); 468 if (mObject != NULL) { 469 env->DeleteGlobalRef(mObject); 470 } else { 471 env->DeleteWeakGlobalRef(mObjectWeak); 472 } 473 } 474 475private: 476 JavaVM* const mVM; 477 jobject mObject; 478 jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied() 479 wp<DeathRecipientList> mList; 480}; 481 482// ---------------------------------------------------------------------------- 483 484DeathRecipientList::DeathRecipientList() { 485 LOGDEATH("New DRL @ %p", this); 486} 487 488DeathRecipientList::~DeathRecipientList() { 489 LOGDEATH("Destroy DRL @ %p", this); 490 AutoMutex _l(mLock); 491 492 // Should never happen -- the JavaDeathRecipient objects that have added themselves 493 // to the list are holding references on the list object. Only when they are torn 494 // down can the list header be destroyed. 495 if (mList.size() > 0) { 496 List< sp<JavaDeathRecipient> >::iterator iter; 497 for (iter = mList.begin(); iter != mList.end(); iter++) { 498 (*iter)->warnIfStillLive(); 499 } 500 } 501} 502 503void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) { 504 AutoMutex _l(mLock); 505 506 LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get()); 507 mList.push_back(recipient); 508} 509 510void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) { 511 AutoMutex _l(mLock); 512 513 List< sp<JavaDeathRecipient> >::iterator iter; 514 for (iter = mList.begin(); iter != mList.end(); iter++) { 515 if (*iter == recipient) { 516 LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get()); 517 mList.erase(iter); 518 return; 519 } 520 } 521} 522 523sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) { 524 AutoMutex _l(mLock); 525 526 List< sp<JavaDeathRecipient> >::iterator iter; 527 for (iter = mList.begin(); iter != mList.end(); iter++) { 528 if ((*iter)->matches(recipient)) { 529 return *iter; 530 } 531 } 532 return NULL; 533} 534 535// ---------------------------------------------------------------------------- 536 537namespace android { 538 539static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie) 540{ 541 android_atomic_dec(&gNumProxyRefs); 542 JNIEnv* env = javavm_to_jnienv((JavaVM*)cleanupCookie); 543 env->DeleteGlobalRef((jobject)obj); 544} 545 546static Mutex mProxyLock; 547 548jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) 549{ 550 if (val == NULL) return NULL; 551 552 if (val->checkSubclass(&gBinderOffsets)) { 553 // One of our own! 554 jobject object = static_cast<JavaBBinder*>(val.get())->object(); 555 LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object); 556 return object; 557 } 558 559 // For the rest of the function we will hold this lock, to serialize 560 // looking/creation of Java proxies for native Binder proxies. 561 AutoMutex _l(mProxyLock); 562 563 // Someone else's... do we know about it? 564 jobject object = (jobject)val->findObject(&gBinderProxyOffsets); 565 if (object != NULL) { 566 jobject res = jniGetReferent(env, object); 567 if (res != NULL) { 568 ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res); 569 return res; 570 } 571 LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); 572 android_atomic_dec(&gNumProxyRefs); 573 val->detachObject(&gBinderProxyOffsets); 574 env->DeleteGlobalRef(object); 575 } 576 577 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); 578 if (object != NULL) { 579 LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object); 580 // The proxy holds a reference to the native object. 581 env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get()); 582 val->incStrong((void*)javaObjectForIBinder); 583 584 // The native object needs to hold a weak reference back to the 585 // proxy, so we can retrieve the same proxy if it is still active. 586 jobject refObject = env->NewGlobalRef( 587 env->GetObjectField(object, gBinderProxyOffsets.mSelf)); 588 val->attachObject(&gBinderProxyOffsets, refObject, 589 jnienv_to_javavm(env), proxy_cleanup); 590 591 // Also remember the death recipients registered on this proxy 592 sp<DeathRecipientList> drl = new DeathRecipientList; 593 drl->incStrong((void*)javaObjectForIBinder); 594 env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get())); 595 596 // Note that a new object reference has been created. 597 android_atomic_inc(&gNumProxyRefs); 598 incRefsCreated(env); 599 } 600 601 return object; 602} 603 604sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) 605{ 606 if (obj == NULL) return NULL; 607 608 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { 609 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 610 env->GetLongField(obj, gBinderOffsets.mObject); 611 return jbh != NULL ? jbh->get(env, obj) : NULL; 612 } 613 614 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { 615 return (IBinder*) 616 env->GetLongField(obj, gBinderProxyOffsets.mObject); 617 } 618 619 ALOGW("ibinderForJavaObject: %p is not a Binder object", obj); 620 return NULL; 621} 622 623jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc) 624{ 625 return env->NewObject( 626 gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc); 627} 628 629void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy) 630{ 631 // Call back into android.os.StrictMode#onBinderStrictModePolicyChange 632 // to sync our state back to it. See the comments in StrictMode.java. 633 env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass, 634 gStrictModeCallbackOffsets.mCallback, 635 strict_policy); 636} 637 638void signalExceptionForError(JNIEnv* env, jobject obj, status_t err, 639 bool canThrowRemoteException) 640{ 641 switch (err) { 642 case UNKNOWN_ERROR: 643 jniThrowException(env, "java/lang/RuntimeException", "Unknown error"); 644 break; 645 case NO_MEMORY: 646 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 647 break; 648 case INVALID_OPERATION: 649 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL); 650 break; 651 case BAD_VALUE: 652 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 653 break; 654 case BAD_INDEX: 655 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 656 break; 657 case BAD_TYPE: 658 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 659 break; 660 case NAME_NOT_FOUND: 661 jniThrowException(env, "java/util/NoSuchElementException", NULL); 662 break; 663 case PERMISSION_DENIED: 664 jniThrowException(env, "java/lang/SecurityException", NULL); 665 break; 666 case NOT_ENOUGH_DATA: 667 jniThrowException(env, "android/os/ParcelFormatException", "Not enough data"); 668 break; 669 case NO_INIT: 670 jniThrowException(env, "java/lang/RuntimeException", "Not initialized"); 671 break; 672 case ALREADY_EXISTS: 673 jniThrowException(env, "java/lang/RuntimeException", "Item already exists"); 674 break; 675 case DEAD_OBJECT: 676 // DeadObjectException is a checked exception, only throw from certain methods. 677 jniThrowException(env, canThrowRemoteException 678 ? "android/os/DeadObjectException" 679 : "java/lang/RuntimeException", NULL); 680 break; 681 case UNKNOWN_TRANSACTION: 682 jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code"); 683 break; 684 case FAILED_TRANSACTION: 685 ALOGE("!!! FAILED BINDER TRANSACTION !!!"); 686 // TransactionTooLargeException is a checked exception, only throw from certain methods. 687 // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION 688 // but it is not the only one. The Binder driver can return BR_FAILED_REPLY 689 // for other reasons also, such as if the transaction is malformed or 690 // refers to an FD that has been closed. We should change the driver 691 // to enable us to distinguish these cases in the future. 692 jniThrowException(env, canThrowRemoteException 693 ? "android/os/TransactionTooLargeException" 694 : "java/lang/RuntimeException", NULL); 695 break; 696 case FDS_NOT_ALLOWED: 697 jniThrowException(env, "java/lang/RuntimeException", 698 "Not allowed to write file descriptors here"); 699 break; 700 default: 701 ALOGE("Unknown binder error code. 0x%" PRIx32, err); 702 String8 msg; 703 msg.appendFormat("Unknown binder error code. 0x%" PRIx32, err); 704 // RemoteException is a checked exception, only throw from certain methods. 705 jniThrowException(env, canThrowRemoteException 706 ? "android/os/RemoteException" : "java/lang/RuntimeException", msg.string()); 707 break; 708 } 709} 710 711} 712 713// ---------------------------------------------------------------------------- 714 715static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz) 716{ 717 return IPCThreadState::self()->getCallingPid(); 718} 719 720static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz) 721{ 722 return IPCThreadState::self()->getCallingUid(); 723} 724 725static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz) 726{ 727 return IPCThreadState::self()->clearCallingIdentity(); 728} 729 730static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token) 731{ 732 // XXX temporary sanity check to debug crashes. 733 int uid = (int)(token>>32); 734 if (uid > 0 && uid < 999) { 735 // In Android currently there are no uids in this range. 736 char buf[128]; 737 sprintf(buf, "Restoring bad calling ident: 0x%" PRIx64, token); 738 jniThrowException(env, "java/lang/IllegalStateException", buf); 739 return; 740 } 741 IPCThreadState::self()->restoreCallingIdentity(token); 742} 743 744static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask) 745{ 746 IPCThreadState::self()->setStrictModePolicy(policyMask); 747} 748 749static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz) 750{ 751 return IPCThreadState::self()->getStrictModePolicy(); 752} 753 754static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz) 755{ 756 IPCThreadState::self()->flushCommands(); 757} 758 759static void android_os_Binder_init(JNIEnv* env, jobject obj) 760{ 761 JavaBBinderHolder* jbh = new JavaBBinderHolder(); 762 if (jbh == NULL) { 763 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 764 return; 765 } 766 ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh); 767 jbh->incStrong((void*)android_os_Binder_init); 768 env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh); 769} 770 771static void android_os_Binder_destroy(JNIEnv* env, jobject obj) 772{ 773 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 774 env->GetLongField(obj, gBinderOffsets.mObject); 775 if (jbh != NULL) { 776 env->SetLongField(obj, gBinderOffsets.mObject, 0); 777 ALOGV("Java Binder %p: removing ref on holder %p", obj, jbh); 778 jbh->decStrong((void*)android_os_Binder_init); 779 } else { 780 // Encountering an uninitialized binder is harmless. All it means is that 781 // the Binder was only partially initialized when its finalizer ran and called 782 // destroy(). The Binder could be partially initialized for several reasons. 783 // For example, a Binder subclass constructor might have thrown an exception before 784 // it could delegate to its superclass's constructor. Consequently init() would 785 // not have been called and the holder pointer would remain NULL. 786 ALOGV("Java Binder %p: ignoring uninitialized binder", obj); 787 } 788} 789 790// ---------------------------------------------------------------------------- 791 792static const JNINativeMethod gBinderMethods[] = { 793 /* name, signature, funcPtr */ 794 { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, 795 { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, 796 { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, 797 { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, 798 { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, 799 { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, 800 { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, 801 { "init", "()V", (void*)android_os_Binder_init }, 802 { "destroy", "()V", (void*)android_os_Binder_destroy } 803}; 804 805const char* const kBinderPathName = "android/os/Binder"; 806 807static int int_register_android_os_Binder(JNIEnv* env) 808{ 809 jclass clazz; 810 811 clazz = env->FindClass(kBinderPathName); 812 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder"); 813 814 gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 815 gBinderOffsets.mExecTransact 816 = env->GetMethodID(clazz, "execTransact", "(IJJI)Z"); 817 assert(gBinderOffsets.mExecTransact); 818 819 gBinderOffsets.mObject 820 = env->GetFieldID(clazz, "mObject", "J"); 821 assert(gBinderOffsets.mObject); 822 823 return AndroidRuntime::registerNativeMethods( 824 env, kBinderPathName, 825 gBinderMethods, NELEM(gBinderMethods)); 826} 827 828// **************************************************************************** 829// **************************************************************************** 830// **************************************************************************** 831 832namespace android { 833 834jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz) 835{ 836 return gNumLocalRefs; 837} 838 839jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz) 840{ 841 return gNumProxyRefs; 842} 843 844jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz) 845{ 846 return gNumDeathRefs; 847} 848 849} 850 851// **************************************************************************** 852// **************************************************************************** 853// **************************************************************************** 854 855static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) 856{ 857 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 858 return javaObjectForIBinder(env, b); 859} 860 861static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz) 862{ 863 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 864 android::IPCThreadState::self()->joinThreadPool(); 865} 866 867static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env, 868 jobject clazz, jboolean disable) 869{ 870 IPCThreadState::disableBackgroundScheduling(disable ? true : false); 871} 872 873static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz) 874{ 875 ALOGV("Gc has executed, clearing binder ops"); 876 android_atomic_and(0, &gNumRefsCreated); 877} 878 879// ---------------------------------------------------------------------------- 880 881static const JNINativeMethod gBinderInternalMethods[] = { 882 /* name, signature, funcPtr */ 883 { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject }, 884 { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool }, 885 { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling }, 886 { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc } 887}; 888 889const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal"; 890 891static int int_register_android_os_BinderInternal(JNIEnv* env) 892{ 893 jclass clazz; 894 895 clazz = env->FindClass(kBinderInternalPathName); 896 LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal"); 897 898 gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 899 gBinderInternalOffsets.mForceGc 900 = env->GetStaticMethodID(clazz, "forceBinderGc", "()V"); 901 assert(gBinderInternalOffsets.mForceGc); 902 903 return AndroidRuntime::registerNativeMethods( 904 env, kBinderInternalPathName, 905 gBinderInternalMethods, NELEM(gBinderInternalMethods)); 906} 907 908// **************************************************************************** 909// **************************************************************************** 910// **************************************************************************** 911 912static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj) 913{ 914 IBinder* target = (IBinder*) 915 env->GetLongField(obj, gBinderProxyOffsets.mObject); 916 if (target == NULL) { 917 return JNI_FALSE; 918 } 919 status_t err = target->pingBinder(); 920 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; 921} 922 923static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj) 924{ 925 IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); 926 if (target != NULL) { 927 const String16& desc = target->getInterfaceDescriptor(); 928 return env->NewString(desc.string(), desc.size()); 929 } 930 jniThrowException(env, "java/lang/RuntimeException", 931 "No binder found for object"); 932 return NULL; 933} 934 935static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj) 936{ 937 IBinder* target = (IBinder*) 938 env->GetLongField(obj, gBinderProxyOffsets.mObject); 939 if (target == NULL) { 940 return JNI_FALSE; 941 } 942 bool alive = target->isBinderAlive(); 943 return alive ? JNI_TRUE : JNI_FALSE; 944} 945 946static int getprocname(pid_t pid, char *buf, size_t len) { 947 char filename[32]; 948 FILE *f; 949 950 snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid); 951 f = fopen(filename, "r"); 952 if (!f) { 953 *buf = '\0'; 954 return 1; 955 } 956 if (!fgets(buf, len, f)) { 957 *buf = '\0'; 958 fclose(f); 959 return 2; 960 } 961 fclose(f); 962 return 0; 963} 964 965static bool push_eventlog_string(char** pos, const char* end, const char* str) { 966 jint len = strlen(str); 967 int space_needed = 1 + sizeof(len) + len; 968 if (end - *pos < space_needed) { 969 ALOGW("not enough space for string. remain=%" PRIdPTR "; needed=%d", 970 end - *pos, space_needed); 971 return false; 972 } 973 **pos = EVENT_TYPE_STRING; 974 (*pos)++; 975 memcpy(*pos, &len, sizeof(len)); 976 *pos += sizeof(len); 977 memcpy(*pos, str, len); 978 *pos += len; 979 return true; 980} 981 982static bool push_eventlog_int(char** pos, const char* end, jint val) { 983 int space_needed = 1 + sizeof(val); 984 if (end - *pos < space_needed) { 985 ALOGW("not enough space for int. remain=%" PRIdPTR "; needed=%d", 986 end - *pos, space_needed); 987 return false; 988 } 989 **pos = EVENT_TYPE_INT; 990 (*pos)++; 991 memcpy(*pos, &val, sizeof(val)); 992 *pos += sizeof(val); 993 return true; 994} 995 996// From frameworks/base/core/java/android/content/EventLogTags.logtags: 997#define ENABLE_BINDER_SAMPLE 0 998#define LOGTAG_BINDER_OPERATION 52004 999 1000static void conditionally_log_binder_call(int64_t start_millis, 1001 IBinder* target, jint code) { 1002 int duration_ms = static_cast<int>(uptimeMillis() - start_millis); 1003 1004 int sample_percent; 1005 if (duration_ms >= 500) { 1006 sample_percent = 100; 1007 } else { 1008 sample_percent = 100 * duration_ms / 500; 1009 if (sample_percent == 0) { 1010 return; 1011 } 1012 if (sample_percent < (random() % 100 + 1)) { 1013 return; 1014 } 1015 } 1016 1017 char process_name[40]; 1018 getprocname(getpid(), process_name, sizeof(process_name)); 1019 String8 desc(target->getInterfaceDescriptor()); 1020 1021 char buf[LOGGER_ENTRY_MAX_PAYLOAD]; 1022 buf[0] = EVENT_TYPE_LIST; 1023 buf[1] = 5; 1024 char* pos = &buf[2]; 1025 char* end = &buf[LOGGER_ENTRY_MAX_PAYLOAD - 1]; // leave room for final \n 1026 if (!push_eventlog_string(&pos, end, desc.string())) return; 1027 if (!push_eventlog_int(&pos, end, code)) return; 1028 if (!push_eventlog_int(&pos, end, duration_ms)) return; 1029 if (!push_eventlog_string(&pos, end, process_name)) return; 1030 if (!push_eventlog_int(&pos, end, sample_percent)) return; 1031 *(pos++) = '\n'; // conventional with EVENT_TYPE_LIST apparently. 1032 android_bWriteLog(LOGTAG_BINDER_OPERATION, buf, pos - buf); 1033} 1034 1035// We only measure binder call durations to potentially log them if 1036// we're on the main thread. Unfortunately sim-eng doesn't seem to 1037// have gettid, so we just ignore this and don't log if we can't 1038// get the thread id. 1039static bool should_time_binder_calls() { 1040#ifdef HAVE_GETTID 1041 return (getpid() == androidGetTid()); 1042#else 1043#warning no gettid(), so not logging Binder calls... 1044 return false; 1045#endif 1046} 1047 1048static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, 1049 jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException 1050{ 1051 if (dataObj == NULL) { 1052 jniThrowNullPointerException(env, NULL); 1053 return JNI_FALSE; 1054 } 1055 1056 Parcel* data = parcelForJavaObject(env, dataObj); 1057 if (data == NULL) { 1058 return JNI_FALSE; 1059 } 1060 Parcel* reply = parcelForJavaObject(env, replyObj); 1061 if (reply == NULL && replyObj != NULL) { 1062 return JNI_FALSE; 1063 } 1064 1065 IBinder* target = (IBinder*) 1066 env->GetLongField(obj, gBinderProxyOffsets.mObject); 1067 if (target == NULL) { 1068 jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); 1069 return JNI_FALSE; 1070 } 1071 1072 ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n", 1073 target, obj, code); 1074 1075#if ENABLE_BINDER_SAMPLE 1076 // Only log the binder call duration for things on the Java-level main thread. 1077 // But if we don't 1078 const bool time_binder_calls = should_time_binder_calls(); 1079 1080 int64_t start_millis; 1081 if (time_binder_calls) { 1082 start_millis = uptimeMillis(); 1083 } 1084#endif 1085 //printf("Transact from Java code to %p sending: ", target); data->print(); 1086 status_t err = target->transact(code, *data, reply, flags); 1087 //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); 1088#if ENABLE_BINDER_SAMPLE 1089 if (time_binder_calls) { 1090 conditionally_log_binder_call(start_millis, target, code); 1091 } 1092#endif 1093 1094 if (err == NO_ERROR) { 1095 return JNI_TRUE; 1096 } else if (err == UNKNOWN_TRANSACTION) { 1097 return JNI_FALSE; 1098 } 1099 1100 signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/); 1101 return JNI_FALSE; 1102} 1103 1104static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, 1105 jobject recipient, jint flags) // throws RemoteException 1106{ 1107 if (recipient == NULL) { 1108 jniThrowNullPointerException(env, NULL); 1109 return; 1110 } 1111 1112 IBinder* target = (IBinder*) 1113 env->GetLongField(obj, gBinderProxyOffsets.mObject); 1114 if (target == NULL) { 1115 ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 1116 assert(false); 1117 } 1118 1119 LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient); 1120 1121 if (!target->localBinder()) { 1122 DeathRecipientList* list = (DeathRecipientList*) 1123 env->GetLongField(obj, gBinderProxyOffsets.mOrgue); 1124 sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list); 1125 status_t err = target->linkToDeath(jdr, NULL, flags); 1126 if (err != NO_ERROR) { 1127 // Failure adding the death recipient, so clear its reference 1128 // now. 1129 jdr->clearReference(); 1130 signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/); 1131 } 1132 } 1133} 1134 1135static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, 1136 jobject recipient, jint flags) 1137{ 1138 jboolean res = JNI_FALSE; 1139 if (recipient == NULL) { 1140 jniThrowNullPointerException(env, NULL); 1141 return res; 1142 } 1143 1144 IBinder* target = (IBinder*) 1145 env->GetLongField(obj, gBinderProxyOffsets.mObject); 1146 if (target == NULL) { 1147 ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 1148 return JNI_FALSE; 1149 } 1150 1151 LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); 1152 1153 if (!target->localBinder()) { 1154 status_t err = NAME_NOT_FOUND; 1155 1156 // If we find the matching recipient, proceed to unlink using that 1157 DeathRecipientList* list = (DeathRecipientList*) 1158 env->GetLongField(obj, gBinderProxyOffsets.mOrgue); 1159 sp<JavaDeathRecipient> origJDR = list->find(recipient); 1160 LOGDEATH(" unlink found list %p and JDR %p", list, origJDR.get()); 1161 if (origJDR != NULL) { 1162 wp<IBinder::DeathRecipient> dr; 1163 err = target->unlinkToDeath(origJDR, NULL, flags, &dr); 1164 if (err == NO_ERROR && dr != NULL) { 1165 sp<IBinder::DeathRecipient> sdr = dr.promote(); 1166 JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get()); 1167 if (jdr != NULL) { 1168 jdr->clearReference(); 1169 } 1170 } 1171 } 1172 1173 if (err == NO_ERROR || err == DEAD_OBJECT) { 1174 res = JNI_TRUE; 1175 } else { 1176 jniThrowException(env, "java/util/NoSuchElementException", 1177 "Death link does not exist"); 1178 } 1179 } 1180 1181 return res; 1182} 1183 1184static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) 1185{ 1186 IBinder* b = (IBinder*) 1187 env->GetLongField(obj, gBinderProxyOffsets.mObject); 1188 DeathRecipientList* drl = (DeathRecipientList*) 1189 env->GetLongField(obj, gBinderProxyOffsets.mOrgue); 1190 1191 LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl); 1192 env->SetLongField(obj, gBinderProxyOffsets.mObject, 0); 1193 env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0); 1194 drl->decStrong((void*)javaObjectForIBinder); 1195 b->decStrong((void*)javaObjectForIBinder); 1196 1197 IPCThreadState::self()->flushCommands(); 1198} 1199 1200// ---------------------------------------------------------------------------- 1201 1202static const JNINativeMethod gBinderProxyMethods[] = { 1203 /* name, signature, funcPtr */ 1204 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, 1205 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, 1206 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, 1207 {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, 1208 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, 1209 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, 1210 {"destroy", "()V", (void*)android_os_BinderProxy_destroy}, 1211}; 1212 1213const char* const kBinderProxyPathName = "android/os/BinderProxy"; 1214 1215static int int_register_android_os_BinderProxy(JNIEnv* env) 1216{ 1217 jclass clazz; 1218 1219 clazz = env->FindClass("java/lang/Error"); 1220 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error"); 1221 gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1222 1223 clazz = env->FindClass(kBinderProxyPathName); 1224 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy"); 1225 1226 gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1227 gBinderProxyOffsets.mConstructor 1228 = env->GetMethodID(clazz, "<init>", "()V"); 1229 assert(gBinderProxyOffsets.mConstructor); 1230 gBinderProxyOffsets.mSendDeathNotice 1231 = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); 1232 assert(gBinderProxyOffsets.mSendDeathNotice); 1233 1234 gBinderProxyOffsets.mObject 1235 = env->GetFieldID(clazz, "mObject", "J"); 1236 assert(gBinderProxyOffsets.mObject); 1237 gBinderProxyOffsets.mSelf 1238 = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;"); 1239 assert(gBinderProxyOffsets.mSelf); 1240 gBinderProxyOffsets.mOrgue 1241 = env->GetFieldID(clazz, "mOrgue", "J"); 1242 assert(gBinderProxyOffsets.mOrgue); 1243 1244 clazz = env->FindClass("java/lang/Class"); 1245 LOG_FATAL_IF(clazz == NULL, "Unable to find java.lang.Class"); 1246 gClassOffsets.mGetName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;"); 1247 assert(gClassOffsets.mGetName); 1248 1249 return AndroidRuntime::registerNativeMethods( 1250 env, kBinderProxyPathName, 1251 gBinderProxyMethods, NELEM(gBinderProxyMethods)); 1252} 1253 1254// **************************************************************************** 1255// **************************************************************************** 1256// **************************************************************************** 1257 1258int register_android_os_Binder(JNIEnv* env) 1259{ 1260 if (int_register_android_os_Binder(env) < 0) 1261 return -1; 1262 if (int_register_android_os_BinderInternal(env) < 0) 1263 return -1; 1264 if (int_register_android_os_BinderProxy(env) < 0) 1265 return -1; 1266 1267 jclass clazz; 1268 1269 clazz = env->FindClass("android/util/Log"); 1270 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log"); 1271 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1272 gLogOffsets.mLogE = env->GetStaticMethodID( 1273 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I"); 1274 assert(gLogOffsets.mLogE); 1275 1276 clazz = env->FindClass("android/os/ParcelFileDescriptor"); 1277 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 1278 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1279 gParcelFileDescriptorOffsets.mConstructor 1280 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 1281 1282 clazz = env->FindClass("android/os/StrictMode"); 1283 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode"); 1284 gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1285 gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID( 1286 clazz, "onBinderStrictModePolicyChange", "(I)V"); 1287 LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL, 1288 "Unable to find strict mode callback."); 1289 1290 return 0; 1291} 1292