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