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