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