android_util_Binder.cpp revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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 <sys/stat.h> 25#include <stdio.h> 26 27#include <utils/Atomic.h> 28#include <utils/IInterface.h> 29#include <utils/IPCThreadState.h> 30#include <utils/Log.h> 31#include <utils/Parcel.h> 32#include <utils/ProcessState.h> 33#include <utils/IServiceManager.h> 34 35#include <android_runtime/AndroidRuntime.h> 36 37//#undef LOGV 38//#define LOGV(...) fprintf(stderr, __VA_ARGS__) 39 40using namespace android; 41 42// ---------------------------------------------------------------------------- 43 44static struct bindernative_offsets_t 45{ 46 // Class state. 47 jclass mClass; 48 jmethodID mExecTransact; 49 50 // Object state. 51 jfieldID mObject; 52 53} gBinderOffsets; 54 55// ---------------------------------------------------------------------------- 56 57static struct binderinternal_offsets_t 58{ 59 // Class state. 60 jclass mClass; 61 jmethodID mForceGc; 62 63} gBinderInternalOffsets; 64 65// ---------------------------------------------------------------------------- 66 67static struct debug_offsets_t 68{ 69 // Class state. 70 jclass mClass; 71 72} gDebugOffsets; 73 74// ---------------------------------------------------------------------------- 75 76static struct weakreference_offsets_t 77{ 78 // Class state. 79 jclass mClass; 80 jmethodID mGet; 81 82} gWeakReferenceOffsets; 83 84static struct error_offsets_t 85{ 86 jclass mClass; 87} gErrorOffsets; 88 89// ---------------------------------------------------------------------------- 90 91static struct binderproxy_offsets_t 92{ 93 // Class state. 94 jclass mClass; 95 jmethodID mConstructor; 96 jmethodID mSendDeathNotice; 97 98 // Object state. 99 jfieldID mObject; 100 jfieldID mSelf; 101 102} gBinderProxyOffsets; 103 104// ---------------------------------------------------------------------------- 105 106static struct parcel_offsets_t 107{ 108 jfieldID mObject; 109 jfieldID mOwnObject; 110} gParcelOffsets; 111 112static struct log_offsets_t 113{ 114 // Class state. 115 jclass mClass; 116 jmethodID mLogE; 117} gLogOffsets; 118 119static struct file_descriptor_offsets_t 120{ 121 jclass mClass; 122 jmethodID mConstructor; 123 jfieldID mDescriptor; 124} gFileDescriptorOffsets; 125 126static struct parcel_file_descriptor_offsets_t 127{ 128 jclass mClass; 129 jmethodID mConstructor; 130} gParcelFileDescriptorOffsets; 131 132// **************************************************************************** 133// **************************************************************************** 134// **************************************************************************** 135 136static volatile int32_t gNumRefsCreated = 0; 137static volatile int32_t gNumProxyRefs = 0; 138static volatile int32_t gNumLocalRefs = 0; 139static volatile int32_t gNumDeathRefs = 0; 140 141static void incRefsCreated(JNIEnv* env) 142{ 143 int old = android_atomic_inc(&gNumRefsCreated); 144 if (old == 200) { 145 android_atomic_and(0, &gNumRefsCreated); 146 env->CallStaticVoidMethod(gBinderInternalOffsets.mClass, 147 gBinderInternalOffsets.mForceGc); 148 } else { 149 LOGV("Now have %d binder ops", old); 150 } 151} 152 153static JavaVM* jnienv_to_javavm(JNIEnv* env) 154{ 155 JavaVM* vm; 156 return env->GetJavaVM(&vm) >= 0 ? vm : NULL; 157} 158 159static JNIEnv* javavm_to_jnienv(JavaVM* vm) 160{ 161 JNIEnv* env; 162 return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL; 163} 164 165static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) 166{ 167 env->ExceptionClear(); 168 169 jstring tagstr = env->NewStringUTF(LOG_TAG); 170 jstring msgstr = env->NewStringUTF(msg); 171 172 if ((tagstr == NULL) || (msgstr == NULL)) { 173 env->ExceptionClear(); /* assume exception (OOM?) was thrown */ 174 LOGE("Unable to call Log.e()\n"); 175 LOGE("%s", msg); 176 goto bail; 177 } 178 179 env->CallStaticIntMethod( 180 gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep); 181 if (env->ExceptionCheck()) { 182 /* attempting to log the failure has failed */ 183 LOGW("Failed trying to log exception, msg='%s'\n", msg); 184 env->ExceptionClear(); 185 } 186 187 if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { 188 /* 189 * It's an Error: Reraise the exception, detach this thread, and 190 * wait for the fireworks. Die even more blatantly after a minute 191 * if the gentler attempt doesn't do the trick. 192 * 193 * The GetJavaVM function isn't on the "approved" list of JNI calls 194 * that can be made while an exception is pending, so we want to 195 * get the VM ptr, throw the exception, and then detach the thread. 196 */ 197 JavaVM* vm = jnienv_to_javavm(env); 198 env->Throw(excep); 199 vm->DetachCurrentThread(); 200 sleep(60); 201 LOGE("Forcefully exiting"); 202 exit(1); 203 *((int *) 1) = 1; 204 } 205 206bail: 207 /* discard local refs created for us by VM */ 208 env->DeleteLocalRef(tagstr); 209 env->DeleteLocalRef(msgstr); 210} 211 212class JavaBBinderHolder; 213 214class JavaBBinder : public BBinder 215{ 216public: 217 JavaBBinder(JNIEnv* env, jobject object) 218 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) 219 { 220 LOGV("Creating JavaBBinder %p\n", this); 221 android_atomic_inc(&gNumLocalRefs); 222 incRefsCreated(env); 223 } 224 225 bool checkSubclass(const void* subclassID) const 226 { 227 return subclassID == &gBinderOffsets; 228 } 229 230 jobject object() const 231 { 232 return mObject; 233 } 234 235protected: 236 virtual ~JavaBBinder() 237 { 238 LOGV("Destroying JavaBBinder %p\n", this); 239 android_atomic_dec(&gNumLocalRefs); 240 JNIEnv* env = javavm_to_jnienv(mVM); 241 env->DeleteGlobalRef(mObject); 242 } 243 244 virtual status_t onTransact( 245 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) 246 { 247 JNIEnv* env = javavm_to_jnienv(mVM); 248 249 LOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); 250 251 //printf("Transact from %p to Java code sending: ", this); 252 //data.print(); 253 //printf("\n"); 254 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, 255 code, (int32_t)&data, (int32_t)reply, flags); 256 jthrowable excep = env->ExceptionOccurred(); 257 if (excep) { 258 report_exception(env, excep, 259 "*** Uncaught remote exception! " 260 "(Exceptions are not yet supported across processes.)"); 261 res = JNI_FALSE; 262 263 /* clean up JNI local ref -- we don't return to Java code */ 264 env->DeleteLocalRef(excep); 265 } 266 267 //aout << "onTransact to Java code; result=" << res << endl 268 // << "Transact from " << this << " to Java code returning " 269 // << reply << ": " << *reply << endl; 270 return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; 271 } 272 273 virtual status_t dump(int fd, const Vector<String16>& args) 274 { 275 return 0; 276 } 277 278private: 279 JavaVM* const mVM; 280 jobject const mObject; 281}; 282 283// ---------------------------------------------------------------------------- 284 285class JavaBBinderHolder : public RefBase 286{ 287public: 288 JavaBBinderHolder(JNIEnv* env, jobject object) 289 : mObject(object) 290 { 291 LOGV("Creating JavaBBinderHolder for Object %p\n", object); 292 } 293 ~JavaBBinderHolder() 294 { 295 LOGV("Destroying JavaBBinderHolder for Object %p\n", mObject); 296 } 297 298 sp<JavaBBinder> get(JNIEnv* env) 299 { 300 AutoMutex _l(mLock); 301 sp<JavaBBinder> b = mBinder.promote(); 302 if (b == NULL) { 303 b = new JavaBBinder(env, mObject); 304 mBinder = b; 305 LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n", 306 b.get(), b->getWeakRefs(), mObject, b->getWeakRefs()->getWeakCount()); 307 } 308 309 return b; 310 } 311 312 sp<JavaBBinder> getExisting() 313 { 314 AutoMutex _l(mLock); 315 return mBinder.promote(); 316 } 317 318private: 319 Mutex mLock; 320 jobject mObject; 321 wp<JavaBBinder> mBinder; 322}; 323 324// ---------------------------------------------------------------------------- 325 326class JavaDeathRecipient : public IBinder::DeathRecipient 327{ 328public: 329 JavaDeathRecipient(JNIEnv* env, jobject object) 330 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), 331 mHoldsRef(true) 332 { 333 incStrong(this); 334 android_atomic_inc(&gNumDeathRefs); 335 incRefsCreated(env); 336 } 337 338 void binderDied(const wp<IBinder>& who) 339 { 340 JNIEnv* env = javavm_to_jnienv(mVM); 341 342 LOGV("Receiving binderDied() on JavaDeathRecipient %p\n", this); 343 344 env->CallStaticVoidMethod(gBinderProxyOffsets.mClass, 345 gBinderProxyOffsets.mSendDeathNotice, mObject); 346 jthrowable excep = env->ExceptionOccurred(); 347 if (excep) { 348 report_exception(env, excep, 349 "*** Uncaught exception returned from death notification!"); 350 } 351 352 clearReference(); 353 } 354 355 void clearReference() 356 { 357 bool release = false; 358 mLock.lock(); 359 if (mHoldsRef) { 360 mHoldsRef = false; 361 release = true; 362 } 363 mLock.unlock(); 364 if (release) { 365 decStrong(this); 366 } 367 } 368 369protected: 370 virtual ~JavaDeathRecipient() 371 { 372 //LOGI("Removing death ref: recipient=%p\n", mObject); 373 android_atomic_dec(&gNumDeathRefs); 374 JNIEnv* env = javavm_to_jnienv(mVM); 375 env->DeleteGlobalRef(mObject); 376 } 377 378private: 379 JavaVM* const mVM; 380 jobject const mObject; 381 Mutex mLock; 382 bool mHoldsRef; 383}; 384 385// ---------------------------------------------------------------------------- 386 387namespace android { 388 389static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie) 390{ 391 android_atomic_dec(&gNumProxyRefs); 392 JNIEnv* env = javavm_to_jnienv((JavaVM*)cleanupCookie); 393 env->DeleteGlobalRef((jobject)obj); 394} 395 396static Mutex mProxyLock; 397 398jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) 399{ 400 if (val == NULL) return NULL; 401 402 if (val->checkSubclass(&gBinderOffsets)) { 403 // One of our own! 404 jobject object = static_cast<JavaBBinder*>(val.get())->object(); 405 //printf("objectForBinder %p: it's our own %p!\n", val.get(), object); 406 return object; 407 } 408 409 // For the rest of the function we will hold this lock, to serialize 410 // looking/creation of Java proxies for native Binder proxies. 411 AutoMutex _l(mProxyLock); 412 413 // Someone else's... do we know about it? 414 jobject object = (jobject)val->findObject(&gBinderProxyOffsets); 415 if (object != NULL) { 416 jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet); 417 if (res != NULL) { 418 LOGV("objectForBinder %p: found existing %p!\n", val.get(), res); 419 return res; 420 } 421 LOGV("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); 422 android_atomic_dec(&gNumProxyRefs); 423 val->detachObject(&gBinderProxyOffsets); 424 env->DeleteGlobalRef(object); 425 } 426 427 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); 428 if (object != NULL) { 429 LOGV("objectForBinder %p: created new %p!\n", val.get(), object); 430 // The proxy holds a reference to the native object. 431 env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get()); 432 val->incStrong(object); 433 434 // The native object needs to hold a weak reference back to the 435 // proxy, so we can retrieve the same proxy if it is still active. 436 jobject refObject = env->NewGlobalRef( 437 env->GetObjectField(object, gBinderProxyOffsets.mSelf)); 438 val->attachObject(&gBinderProxyOffsets, refObject, 439 jnienv_to_javavm(env), proxy_cleanup); 440 441 // Note that a new object reference has been created. 442 android_atomic_inc(&gNumProxyRefs); 443 incRefsCreated(env); 444 } 445 446 return object; 447} 448 449sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) 450{ 451 if (obj == NULL) return NULL; 452 453 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { 454 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 455 env->GetIntField(obj, gBinderOffsets.mObject); 456 return jbh != NULL ? jbh->get(env) : NULL; 457 } 458 459 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { 460 return (IBinder*) 461 env->GetIntField(obj, gBinderProxyOffsets.mObject); 462 } 463 464 LOGW("ibinderForJavaObject: %p is not a Binder object", obj); 465 return NULL; 466} 467 468Parcel* parcelForJavaObject(JNIEnv* env, jobject obj) 469{ 470 if (obj) { 471 Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mObject); 472 if (p != NULL) { 473 return p; 474 } 475 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!"); 476 } 477 return NULL; 478} 479 480jobject newFileDescriptor(JNIEnv* env, int fd) 481{ 482 jobject object = env->NewObject( 483 gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); 484 if (object != NULL) { 485 //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd); 486 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd); 487 } 488 return object; 489} 490 491jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc) 492{ 493 return env->NewObject( 494 gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc); 495} 496 497void signalExceptionForError(JNIEnv* env, jobject obj, status_t err) 498{ 499 switch (err) { 500 case UNKNOWN_ERROR: 501 jniThrowException(env, "java/lang/RuntimeException", "Unknown error"); 502 break; 503 case NO_MEMORY: 504 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 505 break; 506 case INVALID_OPERATION: 507 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL); 508 break; 509 case BAD_VALUE: 510 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 511 break; 512 case BAD_INDEX: 513 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 514 break; 515 case BAD_TYPE: 516 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 517 break; 518 case NAME_NOT_FOUND: 519 jniThrowException(env, "java/util/NoSuchElementException", NULL); 520 break; 521 case PERMISSION_DENIED: 522 jniThrowException(env, "java/lang/SecurityException", NULL); 523 break; 524 case NOT_ENOUGH_DATA: 525 jniThrowException(env, "android/os/ParcelFormatException", "Not enough data"); 526 break; 527 case NO_INIT: 528 jniThrowException(env, "java/lang/RuntimeException", "Not initialized"); 529 break; 530 case ALREADY_EXISTS: 531 jniThrowException(env, "java/lang/RuntimeException", "Item already exists"); 532 break; 533 case DEAD_OBJECT: 534 jniThrowException(env, "android/os/DeadObjectException", NULL); 535 break; 536 case UNKNOWN_TRANSACTION: 537 jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code"); 538 break; 539 case FAILED_TRANSACTION: 540 LOGE("!!! FAILED BINDER TRANSACTION !!!"); 541 //jniThrowException(env, "java/lang/OutOfMemoryError", "Binder transaction too large"); 542 break; 543 default: 544 LOGE("Unknown binder error code. 0x%x", err); 545 } 546} 547 548} 549 550// ---------------------------------------------------------------------------- 551 552static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz) 553{ 554 return IPCThreadState::self()->getCallingPid(); 555} 556 557static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz) 558{ 559 return IPCThreadState::self()->getCallingUid(); 560} 561 562static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz) 563{ 564 return IPCThreadState::self()->clearCallingIdentity(); 565} 566 567static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token) 568{ 569 IPCThreadState::self()->restoreCallingIdentity(token); 570} 571 572static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz) 573{ 574 IPCThreadState::self()->flushCommands(); 575} 576 577static void android_os_Binder_init(JNIEnv* env, jobject clazz) 578{ 579 JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz); 580 if (jbh == NULL) { 581 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 582 return; 583 } 584 LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh); 585 jbh->incStrong(clazz); 586 env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh); 587} 588 589static void android_os_Binder_destroy(JNIEnv* env, jobject clazz) 590{ 591 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 592 env->GetIntField(clazz, gBinderOffsets.mObject); 593 env->SetIntField(clazz, gBinderOffsets.mObject, 0); 594 LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh); 595 jbh->decStrong(clazz); 596} 597 598// ---------------------------------------------------------------------------- 599 600static const JNINativeMethod gBinderMethods[] = { 601 /* name, signature, funcPtr */ 602 { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, 603 { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, 604 { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, 605 { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, 606 { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, 607 { "init", "()V", (void*)android_os_Binder_init }, 608 { "destroy", "()V", (void*)android_os_Binder_destroy } 609}; 610 611const char* const kBinderPathName = "android/os/Binder"; 612 613static int int_register_android_os_Binder(JNIEnv* env) 614{ 615 jclass clazz; 616 617 clazz = env->FindClass(kBinderPathName); 618 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder"); 619 620 gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 621 gBinderOffsets.mExecTransact 622 = env->GetMethodID(clazz, "execTransact", "(IIII)Z"); 623 assert(gBinderOffsets.mExecTransact); 624 625 gBinderOffsets.mObject 626 = env->GetFieldID(clazz, "mObject", "I"); 627 assert(gBinderOffsets.mObject); 628 629 return AndroidRuntime::registerNativeMethods( 630 env, kBinderPathName, 631 gBinderMethods, NELEM(gBinderMethods)); 632} 633 634// **************************************************************************** 635// **************************************************************************** 636// **************************************************************************** 637 638namespace android { 639 640jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz) 641{ 642 return gNumLocalRefs; 643} 644 645jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz) 646{ 647 return gNumProxyRefs; 648} 649 650jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz) 651{ 652 return gNumDeathRefs; 653} 654 655} 656 657// **************************************************************************** 658// **************************************************************************** 659// **************************************************************************** 660 661static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) 662{ 663 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 664 return javaObjectForIBinder(env, b); 665} 666 667static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz) 668{ 669 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 670 android::IPCThreadState::self()->joinThreadPool(); 671} 672 673static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz) 674{ 675 LOGV("Gc has executed, clearing binder ops"); 676 android_atomic_and(0, &gNumRefsCreated); 677} 678 679// ---------------------------------------------------------------------------- 680 681static const JNINativeMethod gBinderInternalMethods[] = { 682 /* name, signature, funcPtr */ 683 { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject }, 684 { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool }, 685 { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc } 686}; 687 688const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal"; 689 690static int int_register_android_os_BinderInternal(JNIEnv* env) 691{ 692 jclass clazz; 693 694 clazz = env->FindClass(kBinderInternalPathName); 695 LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal"); 696 697 gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 698 gBinderInternalOffsets.mForceGc 699 = env->GetStaticMethodID(clazz, "forceBinderGc", "()V"); 700 assert(gBinderInternalOffsets.mForceGc); 701 702 return AndroidRuntime::registerNativeMethods( 703 env, kBinderInternalPathName, 704 gBinderInternalMethods, NELEM(gBinderInternalMethods)); 705} 706 707// **************************************************************************** 708// **************************************************************************** 709// **************************************************************************** 710 711static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj) 712{ 713 IBinder* target = (IBinder*) 714 env->GetIntField(obj, gBinderProxyOffsets.mObject); 715 if (target == NULL) { 716 return JNI_FALSE; 717 } 718 status_t err = target->pingBinder(); 719 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; 720} 721 722static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj) 723{ 724 IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject); 725 if (target != NULL) { 726 String16 desc = target->getInterfaceDescriptor(); 727 return env->NewString(desc.string(), desc.size()); 728 } 729 jniThrowException(env, "java/lang/RuntimeException", 730 "No binder found for object"); 731 return NULL; 732} 733 734static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj) 735{ 736 IBinder* target = (IBinder*) 737 env->GetIntField(obj, gBinderProxyOffsets.mObject); 738 if (target == NULL) { 739 return JNI_FALSE; 740 } 741 bool alive = target->isBinderAlive(); 742 return alive ? JNI_TRUE : JNI_FALSE; 743} 744 745static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, 746 jint code, jobject dataObj, 747 jobject replyObj, jint flags) 748{ 749 if (dataObj == NULL) { 750 jniThrowException(env, "java/lang/NullPointerException", NULL); 751 return JNI_FALSE; 752 } 753 754 Parcel* data = parcelForJavaObject(env, dataObj); 755 if (data == NULL) { 756 return JNI_FALSE; 757 } 758 Parcel* reply = parcelForJavaObject(env, replyObj); 759 if (reply == NULL && replyObj != NULL) { 760 return JNI_FALSE; 761 } 762 763 IBinder* target = (IBinder*) 764 env->GetIntField(obj, gBinderProxyOffsets.mObject); 765 if (target == NULL) { 766 jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); 767 return JNI_FALSE; 768 } 769 770 LOGV("Java code calling transact on %p in Java object %p with code %d\n", 771 target, obj, code); 772 //printf("Transact from Java code to %p sending: ", target); data->print(); 773 status_t err = target->transact(code, *data, reply, flags); 774 //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); 775 if (err == NO_ERROR) { 776 return JNI_TRUE; 777 } else if (err == UNKNOWN_TRANSACTION) { 778 return JNI_FALSE; 779 } 780 781 signalExceptionForError(env, obj, err); 782 return JNI_FALSE; 783} 784 785static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, 786 jobject recipient, jint flags) 787{ 788 if (recipient == NULL) { 789 jniThrowException(env, "java/lang/NullPointerException", NULL); 790 return; 791 } 792 793 IBinder* target = (IBinder*) 794 env->GetIntField(obj, gBinderProxyOffsets.mObject); 795 if (target == NULL) { 796 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 797 assert(false); 798 } 799 800 LOGV("linkToDeath: binder=%p recipient=%p\n", target, recipient); 801 802 if (!target->localBinder()) { 803 sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient); 804 status_t err = target->linkToDeath(jdr, recipient, flags); 805 if (err != NO_ERROR) { 806 // Failure adding the death recipient, so clear its reference 807 // now. 808 jdr->clearReference(); 809 signalExceptionForError(env, obj, err); 810 } 811 } 812} 813 814static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, 815 jobject recipient, jint flags) 816{ 817 jboolean res = JNI_FALSE; 818 if (recipient == NULL) { 819 jniThrowException(env, "java/lang/NullPointerException", NULL); 820 return res; 821 } 822 823 IBinder* target = (IBinder*) 824 env->GetIntField(obj, gBinderProxyOffsets.mObject); 825 if (target == NULL) { 826 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 827 return JNI_FALSE; 828 } 829 830 LOGV("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); 831 832 if (!target->localBinder()) { 833 wp<IBinder::DeathRecipient> dr; 834 status_t err = target->unlinkToDeath(NULL, recipient, flags, &dr); 835 if (err == NO_ERROR && dr != NULL) { 836 sp<IBinder::DeathRecipient> sdr = dr.promote(); 837 JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get()); 838 if (jdr != NULL) { 839 jdr->clearReference(); 840 } 841 } 842 if (err == NO_ERROR || err == DEAD_OBJECT) { 843 res = JNI_TRUE; 844 } else { 845 jniThrowException(env, "java/util/NoSuchElementException", 846 "Death link does not exist"); 847 } 848 } 849 850 return res; 851} 852 853static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) 854{ 855 IBinder* b = (IBinder*) 856 env->GetIntField(obj, gBinderProxyOffsets.mObject); 857 LOGV("Destroying BinderProxy %p: binder=%p\n", obj, b); 858 env->SetIntField(obj, gBinderProxyOffsets.mObject, 0); 859 b->decStrong(obj); 860 IPCThreadState::self()->flushCommands(); 861} 862 863// ---------------------------------------------------------------------------- 864 865static const JNINativeMethod gBinderProxyMethods[] = { 866 /* name, signature, funcPtr */ 867 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, 868 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, 869 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, 870 {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, 871 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, 872 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, 873 {"destroy", "()V", (void*)android_os_BinderProxy_destroy}, 874}; 875 876const char* const kBinderProxyPathName = "android/os/BinderProxy"; 877 878static int int_register_android_os_BinderProxy(JNIEnv* env) 879{ 880 jclass clazz; 881 882 clazz = env->FindClass("java/lang/ref/WeakReference"); 883 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.ref.WeakReference"); 884 gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 885 gWeakReferenceOffsets.mGet 886 = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;"); 887 assert(gWeakReferenceOffsets.mGet); 888 889 clazz = env->FindClass("java/lang/Error"); 890 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error"); 891 gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 892 893 clazz = env->FindClass(kBinderProxyPathName); 894 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy"); 895 896 gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 897 gBinderProxyOffsets.mConstructor 898 = env->GetMethodID(clazz, "<init>", "()V"); 899 assert(gBinderProxyOffsets.mConstructor); 900 gBinderProxyOffsets.mSendDeathNotice 901 = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); 902 assert(gBinderProxyOffsets.mSendDeathNotice); 903 904 gBinderProxyOffsets.mObject 905 = env->GetFieldID(clazz, "mObject", "I"); 906 assert(gBinderProxyOffsets.mObject); 907 gBinderProxyOffsets.mSelf 908 = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;"); 909 assert(gBinderProxyOffsets.mSelf); 910 911 return AndroidRuntime::registerNativeMethods( 912 env, kBinderProxyPathName, 913 gBinderProxyMethods, NELEM(gBinderProxyMethods)); 914} 915 916// **************************************************************************** 917// **************************************************************************** 918// **************************************************************************** 919 920static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz) 921{ 922 Parcel* parcel = parcelForJavaObject(env, clazz); 923 return parcel ? parcel->dataSize() : 0; 924} 925 926static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz) 927{ 928 Parcel* parcel = parcelForJavaObject(env, clazz); 929 return parcel ? parcel->dataAvail() : 0; 930} 931 932static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz) 933{ 934 Parcel* parcel = parcelForJavaObject(env, clazz); 935 return parcel ? parcel->dataPosition() : 0; 936} 937 938static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz) 939{ 940 Parcel* parcel = parcelForJavaObject(env, clazz); 941 return parcel ? parcel->dataCapacity() : 0; 942} 943 944static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size) 945{ 946 Parcel* parcel = parcelForJavaObject(env, clazz); 947 if (parcel != NULL) { 948 const status_t err = parcel->setDataSize(size); 949 if (err != NO_ERROR) { 950 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 951 } 952 } 953} 954 955static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos) 956{ 957 Parcel* parcel = parcelForJavaObject(env, clazz); 958 if (parcel != NULL) { 959 parcel->setDataPosition(pos); 960 } 961} 962 963static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size) 964{ 965 Parcel* parcel = parcelForJavaObject(env, clazz); 966 if (parcel != NULL) { 967 const status_t err = parcel->setDataCapacity(size); 968 if (err != NO_ERROR) { 969 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 970 } 971 } 972} 973 974static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz, 975 jobject data, jint offset, 976 jint length) 977{ 978 Parcel* parcel = parcelForJavaObject(env, clazz); 979 if (parcel == NULL) { 980 return; 981 } 982 void *dest; 983 984 const status_t err = parcel->writeInt32(length); 985 if (err != NO_ERROR) { 986 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 987 } 988 989 dest = parcel->writeInplace(length); 990 991 if (dest == NULL) { 992 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 993 return; 994 } 995 996 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0); 997 if (ar) { 998 memcpy(dest, ar, length); 999 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); 1000 } 1001} 1002 1003 1004static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val) 1005{ 1006 Parcel* parcel = parcelForJavaObject(env, clazz); 1007 if (parcel != NULL) { 1008 const status_t err = parcel->writeInt32(val); 1009 if (err != NO_ERROR) { 1010 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1011 } 1012 } 1013} 1014 1015static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val) 1016{ 1017 Parcel* parcel = parcelForJavaObject(env, clazz); 1018 if (parcel != NULL) { 1019 const status_t err = parcel->writeInt64(val); 1020 if (err != NO_ERROR) { 1021 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1022 } 1023 } 1024} 1025 1026static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val) 1027{ 1028 Parcel* parcel = parcelForJavaObject(env, clazz); 1029 if (parcel != NULL) { 1030 const status_t err = parcel->writeFloat(val); 1031 if (err != NO_ERROR) { 1032 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1033 } 1034 } 1035} 1036 1037static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val) 1038{ 1039 Parcel* parcel = parcelForJavaObject(env, clazz); 1040 if (parcel != NULL) { 1041 const status_t err = parcel->writeDouble(val); 1042 if (err != NO_ERROR) { 1043 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1044 } 1045 } 1046} 1047 1048static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val) 1049{ 1050 Parcel* parcel = parcelForJavaObject(env, clazz); 1051 if (parcel != NULL) { 1052 status_t err = NO_MEMORY; 1053 if (val) { 1054 const jchar* str = env->GetStringCritical(val, 0); 1055 if (str) { 1056 err = parcel->writeString16(str, env->GetStringLength(val)); 1057 env->ReleaseStringCritical(val, str); 1058 } 1059 } else { 1060 err = parcel->writeString16(NULL, 0); 1061 } 1062 if (err != NO_ERROR) { 1063 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1064 } 1065 } 1066} 1067 1068static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object) 1069{ 1070 Parcel* parcel = parcelForJavaObject(env, clazz); 1071 if (parcel != NULL) { 1072 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 1073 if (err != NO_ERROR) { 1074 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1075 } 1076 } 1077} 1078 1079static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1080{ 1081 Parcel* parcel = parcelForJavaObject(env, clazz); 1082 if (parcel != NULL) { 1083 const status_t err = parcel->writeDupFileDescriptor( 1084 env->GetIntField(object, gFileDescriptorOffsets.mDescriptor)); 1085 if (err != NO_ERROR) { 1086 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1087 } 1088 } 1089} 1090 1091static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz) 1092{ 1093 jbyteArray ret = NULL; 1094 1095 Parcel* parcel = parcelForJavaObject(env, clazz); 1096 if (parcel != NULL) { 1097 int32_t len = parcel->readInt32(); 1098 1099 // sanity check the stored length against the true data size 1100 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) { 1101 ret = env->NewByteArray(len); 1102 1103 if (ret != NULL) { 1104 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1105 if (a2) { 1106 const void* data = parcel->readInplace(len); 1107 memcpy(a2, data, len); 1108 env->ReleasePrimitiveArrayCritical(ret, a2, 0); 1109 } 1110 } 1111 } 1112 } 1113 1114 return ret; 1115} 1116 1117static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz) 1118{ 1119 Parcel* parcel = parcelForJavaObject(env, clazz); 1120 if (parcel != NULL) { 1121 return parcel->readInt32(); 1122 } 1123 return 0; 1124} 1125 1126static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz) 1127{ 1128 Parcel* parcel = parcelForJavaObject(env, clazz); 1129 if (parcel != NULL) { 1130 return parcel->readInt64(); 1131 } 1132 return 0; 1133} 1134 1135static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz) 1136{ 1137 Parcel* parcel = parcelForJavaObject(env, clazz); 1138 if (parcel != NULL) { 1139 return parcel->readFloat(); 1140 } 1141 return 0; 1142} 1143 1144static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz) 1145{ 1146 Parcel* parcel = parcelForJavaObject(env, clazz); 1147 if (parcel != NULL) { 1148 return parcel->readDouble(); 1149 } 1150 return 0; 1151} 1152 1153static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz) 1154{ 1155 Parcel* parcel = parcelForJavaObject(env, clazz); 1156 if (parcel != NULL) { 1157 size_t len; 1158 const char16_t* str = parcel->readString16Inplace(&len); 1159 if (str) { 1160 return env->NewString(str, len); 1161 } 1162 return NULL; 1163 } 1164 return NULL; 1165} 1166 1167static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz) 1168{ 1169 Parcel* parcel = parcelForJavaObject(env, clazz); 1170 if (parcel != NULL) { 1171 return javaObjectForIBinder(env, parcel->readStrongBinder()); 1172 } 1173 return NULL; 1174} 1175 1176static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz) 1177{ 1178 Parcel* parcel = parcelForJavaObject(env, clazz); 1179 if (parcel != NULL) { 1180 int fd = parcel->readFileDescriptor(); 1181 if (fd < 0) return NULL; 1182 fd = dup(fd); 1183 if (fd < 0) return NULL; 1184 jobject object = env->NewObject( 1185 gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); 1186 if (object != NULL) { 1187 //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd); 1188 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd); 1189 } 1190 return object; 1191 } 1192 return NULL; 1193} 1194 1195static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz, 1196 jstring name, jint mode) 1197{ 1198 if (name == NULL) { 1199 jniThrowException(env, "java/lang/NullPointerException", NULL); 1200 return NULL; 1201 } 1202 const jchar* str = env->GetStringCritical(name, 0); 1203 if (str == NULL) { 1204 // Whatever, whatever. 1205 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1206 return NULL; 1207 } 1208 String8 name8(str, env->GetStringLength(name)); 1209 env->ReleaseStringCritical(name, str); 1210 int flags=0; 1211 switch (mode&0x30000000) { 1212 case 0: 1213 case 0x10000000: 1214 flags = O_RDONLY; 1215 break; 1216 case 0x20000000: 1217 flags = O_WRONLY; 1218 break; 1219 case 0x30000000: 1220 flags = O_RDWR; 1221 break; 1222 } 1223 1224 if (mode&0x08000000) flags |= O_CREAT; 1225 if (mode&0x04000000) flags |= O_TRUNC; 1226 if (mode&0x02000000) flags |= O_APPEND; 1227 1228 int realMode = S_IRWXU|S_IRWXG; 1229 if (mode&0x00000001) realMode |= S_IROTH; 1230 if (mode&0x00000002) realMode |= S_IWOTH; 1231 1232 int fd = open(name8.string(), flags, realMode); 1233 if (fd < 0) { 1234 jniThrowException(env, "java/io/FileNotFoundException", NULL); 1235 return NULL; 1236 } 1237 jobject object = newFileDescriptor(env, fd); 1238 if (object == NULL) { 1239 close(fd); 1240 } 1241 return object; 1242} 1243 1244static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1245{ 1246 int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1247 if (fd >= 0) { 1248 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1); 1249 //LOGI("Closing ParcelFileDescriptor %d\n", fd); 1250 close(fd); 1251 } 1252} 1253 1254static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz) 1255{ 1256 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1257 if (own) { 1258 Parcel* parcel = parcelForJavaObject(env, clazz); 1259 if (parcel != NULL) { 1260 //LOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel); 1261 parcel->freeData(); 1262 } 1263 } 1264} 1265 1266static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt) 1267{ 1268 Parcel* parcel = (Parcel*)parcelInt; 1269 int own = 0; 1270 if (!parcel) { 1271 //LOGI("Initializing obj %p: creating new Parcel\n", clazz); 1272 own = 1; 1273 parcel = new Parcel; 1274 } else { 1275 //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel); 1276 } 1277 if (parcel == NULL) { 1278 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1279 return; 1280 } 1281 //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own); 1282 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own); 1283 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel); 1284} 1285 1286static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz) 1287{ 1288 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1289 if (own) { 1290 Parcel* parcel = parcelForJavaObject(env, clazz); 1291 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1292 //LOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel); 1293 delete parcel; 1294 } else { 1295 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1296 //LOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz); 1297 } 1298} 1299 1300static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz) 1301{ 1302 Parcel* parcel = parcelForJavaObject(env, clazz); 1303 if (parcel == NULL) { 1304 return NULL; 1305 } 1306 1307 // do not marshall if there are binder objects in the parcel 1308 if (parcel->objectsCount()) 1309 { 1310 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); 1311 return NULL; 1312 } 1313 1314 jbyteArray ret = env->NewByteArray(parcel->dataSize()); 1315 1316 if (ret != NULL) 1317 { 1318 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1319 if (array != NULL) 1320 { 1321 memcpy(array, parcel->data(), parcel->dataSize()); 1322 env->ReleasePrimitiveArrayCritical(ret, array, 0); 1323 } 1324 } 1325 1326 return ret; 1327} 1328 1329static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length) 1330{ 1331 Parcel* parcel = parcelForJavaObject(env, clazz); 1332 if (parcel == NULL || length < 0) { 1333 return; 1334 } 1335 1336 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0); 1337 if (array) 1338 { 1339 parcel->setDataSize(length); 1340 parcel->setDataPosition(0); 1341 1342 void* raw = parcel->writeInplace(length); 1343 memcpy(raw, (array + offset), length); 1344 1345 env->ReleasePrimitiveArrayCritical(data, array, 0); 1346 } 1347} 1348 1349static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length) 1350{ 1351 Parcel* thisParcel = parcelForJavaObject(env, clazz); 1352 if (thisParcel == NULL) { 1353 return; 1354 } 1355 Parcel* otherParcel = parcelForJavaObject(env, parcel); 1356 if (otherParcel == NULL) { 1357 return; 1358 } 1359 1360 (void) thisParcel->appendFrom(otherParcel, offset, length); 1361} 1362 1363static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz) 1364{ 1365 jboolean ret = JNI_FALSE; 1366 Parcel* parcel = parcelForJavaObject(env, clazz); 1367 if (parcel != NULL) { 1368 if (parcel->hasFileDescriptors()) { 1369 ret = JNI_TRUE; 1370 } 1371 } 1372 return ret; 1373} 1374 1375static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name) 1376{ 1377 Parcel* parcel = parcelForJavaObject(env, clazz); 1378 if (parcel != NULL) { 1379 // In the current implementation, the token is just the serialized interface name that 1380 // the caller expects to be invoking 1381 const jchar* str = env->GetStringCritical(name, 0); 1382 if (str != NULL) { 1383 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 1384 env->ReleaseStringCritical(name, str); 1385 } 1386 } 1387} 1388 1389static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name) 1390{ 1391 jboolean ret = JNI_FALSE; 1392 1393 Parcel* parcel = parcelForJavaObject(env, clazz); 1394 if (parcel != NULL) { 1395 const jchar* str = env->GetStringCritical(name, 0); 1396 if (str) { 1397 bool isValid = parcel->enforceInterface(String16(str, env->GetStringLength(name))); 1398 env->ReleaseStringCritical(name, str); 1399 if (isValid) { 1400 return; // everything was correct -> return silently 1401 } 1402 } 1403 } 1404 1405 // all error conditions wind up here 1406 jniThrowException(env, "java/lang/SecurityException", 1407 "Binder invocation to an incorrect interface"); 1408} 1409 1410// ---------------------------------------------------------------------------- 1411 1412static const JNINativeMethod gParcelMethods[] = { 1413 {"dataSize", "()I", (void*)android_os_Parcel_dataSize}, 1414 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail}, 1415 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition}, 1416 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity}, 1417 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize}, 1418 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition}, 1419 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity}, 1420 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative}, 1421 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt}, 1422 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong}, 1423 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat}, 1424 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble}, 1425 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString}, 1426 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, 1427 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor}, 1428 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray}, 1429 {"readInt", "()I", (void*)android_os_Parcel_readInt}, 1430 {"readLong", "()J", (void*)android_os_Parcel_readLong}, 1431 {"readFloat", "()F", (void*)android_os_Parcel_readFloat}, 1432 {"readDouble", "()D", (void*)android_os_Parcel_readDouble}, 1433 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString}, 1434 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, 1435 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor}, 1436 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor}, 1437 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor}, 1438 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer}, 1439 {"init", "(I)V", (void*)android_os_Parcel_init}, 1440 {"destroy", "()V", (void*)android_os_Parcel_destroy}, 1441 {"marshall", "()[B", (void*)android_os_Parcel_marshall}, 1442 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall}, 1443 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom}, 1444 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors}, 1445 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken}, 1446 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface}, 1447}; 1448 1449const char* const kParcelPathName = "android/os/Parcel"; 1450 1451static int int_register_android_os_Parcel(JNIEnv* env) 1452{ 1453 jclass clazz; 1454 1455 clazz = env->FindClass("android/util/Log"); 1456 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log"); 1457 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1458 gLogOffsets.mLogE = env->GetStaticMethodID( 1459 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I"); 1460 assert(gLogOffsets.mLogE); 1461 1462 clazz = env->FindClass("java/io/FileDescriptor"); 1463 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); 1464 gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1465 gFileDescriptorOffsets.mConstructor 1466 = env->GetMethodID(clazz, "<init>", "()V"); 1467 gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); 1468 LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, 1469 "Unable to find descriptor field in java.io.FileDescriptor"); 1470 1471 clazz = env->FindClass("android/os/ParcelFileDescriptor"); 1472 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 1473 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1474 gParcelFileDescriptorOffsets.mConstructor 1475 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 1476 1477 clazz = env->FindClass(kParcelPathName); 1478 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel"); 1479 1480 gParcelOffsets.mObject 1481 = env->GetFieldID(clazz, "mObject", "I"); 1482 gParcelOffsets.mOwnObject 1483 = env->GetFieldID(clazz, "mOwnObject", "I"); 1484 1485 return AndroidRuntime::registerNativeMethods( 1486 env, kParcelPathName, 1487 gParcelMethods, NELEM(gParcelMethods)); 1488} 1489 1490int register_android_os_Binder(JNIEnv* env) 1491{ 1492 if (int_register_android_os_Binder(env) < 0) 1493 return -1; 1494 if (int_register_android_os_BinderInternal(env) < 0) 1495 return -1; 1496 if (int_register_android_os_BinderProxy(env) < 0) 1497 return -1; 1498 if (int_register_android_os_Parcel(env) < 0) 1499 return -1; 1500 return 0; 1501} 1502 1503namespace android { 1504 1505// Returns the Unix file descriptor for a ParcelFileDescriptor object 1506int getParcelFileDescriptorFD(JNIEnv* env, jobject object) 1507{ 1508 return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1509} 1510 1511} 1512