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