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