android_util_Binder.cpp revision 076357b8567458d4b6dfdcf839ef751634cd2bfb
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 1227 int realMode = S_IRWXU|S_IRWXG; 1228 if (mode&0x00000001) realMode |= S_IROTH; 1229 if (mode&0x00000002) realMode |= S_IWOTH; 1230 1231 int fd = open(name8.string(), flags, realMode); 1232 if (fd < 0) { 1233 jniThrowException(env, "java/io/FileNotFoundException", NULL); 1234 return NULL; 1235 } 1236 jobject object = newFileDescriptor(env, fd); 1237 if (object == NULL) { 1238 close(fd); 1239 } 1240 return object; 1241} 1242 1243static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1244{ 1245 int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1246 if (fd >= 0) { 1247 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1); 1248 //LOGI("Closing ParcelFileDescriptor %d\n", fd); 1249 close(fd); 1250 } 1251} 1252 1253static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz) 1254{ 1255 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1256 if (own) { 1257 Parcel* parcel = parcelForJavaObject(env, clazz); 1258 if (parcel != NULL) { 1259 //LOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel); 1260 parcel->freeData(); 1261 } 1262 } 1263} 1264 1265static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt) 1266{ 1267 Parcel* parcel = (Parcel*)parcelInt; 1268 int own = 0; 1269 if (!parcel) { 1270 //LOGI("Initializing obj %p: creating new Parcel\n", clazz); 1271 own = 1; 1272 parcel = new Parcel; 1273 } else { 1274 //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel); 1275 } 1276 if (parcel == NULL) { 1277 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1278 return; 1279 } 1280 //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own); 1281 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own); 1282 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel); 1283} 1284 1285static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz) 1286{ 1287 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1288 if (own) { 1289 Parcel* parcel = parcelForJavaObject(env, clazz); 1290 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1291 //LOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel); 1292 delete parcel; 1293 } else { 1294 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1295 //LOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz); 1296 } 1297} 1298 1299static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz) 1300{ 1301 Parcel* parcel = parcelForJavaObject(env, clazz); 1302 if (parcel == NULL) { 1303 return NULL; 1304 } 1305 1306 // do not marshall if there are binder objects in the parcel 1307 if (parcel->objectsCount()) 1308 { 1309 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); 1310 return NULL; 1311 } 1312 1313 jbyteArray ret = env->NewByteArray(parcel->dataSize()); 1314 1315 if (ret != NULL) 1316 { 1317 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1318 if (array != NULL) 1319 { 1320 memcpy(array, parcel->data(), parcel->dataSize()); 1321 env->ReleasePrimitiveArrayCritical(ret, array, 0); 1322 } 1323 } 1324 1325 return ret; 1326} 1327 1328static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length) 1329{ 1330 Parcel* parcel = parcelForJavaObject(env, clazz); 1331 if (parcel == NULL || length < 0) { 1332 return; 1333 } 1334 1335 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0); 1336 if (array) 1337 { 1338 parcel->setDataSize(length); 1339 parcel->setDataPosition(0); 1340 1341 void* raw = parcel->writeInplace(length); 1342 memcpy(raw, (array + offset), length); 1343 1344 env->ReleasePrimitiveArrayCritical(data, array, 0); 1345 } 1346} 1347 1348static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length) 1349{ 1350 Parcel* thisParcel = parcelForJavaObject(env, clazz); 1351 if (thisParcel == NULL) { 1352 return; 1353 } 1354 Parcel* otherParcel = parcelForJavaObject(env, parcel); 1355 if (otherParcel == NULL) { 1356 return; 1357 } 1358 1359 (void) thisParcel->appendFrom(otherParcel, offset, length); 1360} 1361 1362static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz) 1363{ 1364 jboolean ret = JNI_FALSE; 1365 Parcel* parcel = parcelForJavaObject(env, clazz); 1366 if (parcel != NULL) { 1367 if (parcel->hasFileDescriptors()) { 1368 ret = JNI_TRUE; 1369 } 1370 } 1371 return ret; 1372} 1373 1374static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name) 1375{ 1376 Parcel* parcel = parcelForJavaObject(env, clazz); 1377 if (parcel != NULL) { 1378 // In the current implementation, the token is just the serialized interface name that 1379 // the caller expects to be invoking 1380 const jchar* str = env->GetStringCritical(name, 0); 1381 if (str != NULL) { 1382 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 1383 env->ReleaseStringCritical(name, str); 1384 } 1385 } 1386} 1387 1388static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name) 1389{ 1390 jboolean ret = JNI_FALSE; 1391 1392 Parcel* parcel = parcelForJavaObject(env, clazz); 1393 if (parcel != NULL) { 1394 const jchar* str = env->GetStringCritical(name, 0); 1395 if (str) { 1396 bool isValid = parcel->enforceInterface(String16(str, env->GetStringLength(name))); 1397 env->ReleaseStringCritical(name, str); 1398 if (isValid) { 1399 return; // everything was correct -> return silently 1400 } 1401 } 1402 } 1403 1404 // all error conditions wind up here 1405 jniThrowException(env, "java/lang/SecurityException", 1406 "Binder invocation to an incorrect interface"); 1407} 1408 1409// ---------------------------------------------------------------------------- 1410 1411static const JNINativeMethod gParcelMethods[] = { 1412 {"dataSize", "()I", (void*)android_os_Parcel_dataSize}, 1413 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail}, 1414 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition}, 1415 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity}, 1416 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize}, 1417 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition}, 1418 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity}, 1419 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative}, 1420 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt}, 1421 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong}, 1422 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat}, 1423 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble}, 1424 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString}, 1425 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, 1426 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor}, 1427 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray}, 1428 {"readInt", "()I", (void*)android_os_Parcel_readInt}, 1429 {"readLong", "()J", (void*)android_os_Parcel_readLong}, 1430 {"readFloat", "()F", (void*)android_os_Parcel_readFloat}, 1431 {"readDouble", "()D", (void*)android_os_Parcel_readDouble}, 1432 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString}, 1433 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, 1434 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor}, 1435 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor}, 1436 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor}, 1437 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer}, 1438 {"init", "(I)V", (void*)android_os_Parcel_init}, 1439 {"destroy", "()V", (void*)android_os_Parcel_destroy}, 1440 {"marshall", "()[B", (void*)android_os_Parcel_marshall}, 1441 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall}, 1442 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom}, 1443 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors}, 1444 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken}, 1445 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface}, 1446}; 1447 1448const char* const kParcelPathName = "android/os/Parcel"; 1449 1450static int int_register_android_os_Parcel(JNIEnv* env) 1451{ 1452 jclass clazz; 1453 1454 clazz = env->FindClass("android/util/Log"); 1455 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log"); 1456 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1457 gLogOffsets.mLogE = env->GetStaticMethodID( 1458 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I"); 1459 assert(gLogOffsets.mLogE); 1460 1461 clazz = env->FindClass("java/io/FileDescriptor"); 1462 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); 1463 gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1464 gFileDescriptorOffsets.mConstructor 1465 = env->GetMethodID(clazz, "<init>", "()V"); 1466 gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); 1467 LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, 1468 "Unable to find descriptor field in java.io.FileDescriptor"); 1469 1470 clazz = env->FindClass("android/os/ParcelFileDescriptor"); 1471 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 1472 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1473 gParcelFileDescriptorOffsets.mConstructor 1474 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 1475 1476 clazz = env->FindClass(kParcelPathName); 1477 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel"); 1478 1479 gParcelOffsets.mObject 1480 = env->GetFieldID(clazz, "mObject", "I"); 1481 gParcelOffsets.mOwnObject 1482 = env->GetFieldID(clazz, "mOwnObject", "I"); 1483 1484 return AndroidRuntime::registerNativeMethods( 1485 env, kParcelPathName, 1486 gParcelMethods, NELEM(gParcelMethods)); 1487} 1488 1489int register_android_os_Binder(JNIEnv* env) 1490{ 1491 if (int_register_android_os_Binder(env) < 0) 1492 return -1; 1493 if (int_register_android_os_BinderInternal(env) < 0) 1494 return -1; 1495 if (int_register_android_os_BinderProxy(env) < 0) 1496 return -1; 1497 if (int_register_android_os_Parcel(env) < 0) 1498 return -1; 1499 return 0; 1500} 1501 1502namespace android { 1503 1504// Returns the Unix file descriptor for a ParcelFileDescriptor object 1505int getParcelFileDescriptorFD(JNIEnv* env, jobject object) 1506{ 1507 return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1508} 1509 1510} 1511