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