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