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