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