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    // XXX temporary sanity check to debug crashes.
607    int uid = (int)(token>>32);
608    if (uid > 0 && uid < 999) {
609        // In Android currently there are no uids in this range.
610        char buf[128];
611        sprintf(buf, "Restoring bad calling ident: 0x%Lx", token);
612        jniThrowException(env, "java/lang/IllegalStateException", buf);
613        return;
614    }
615    IPCThreadState::self()->restoreCallingIdentity(token);
616}
617
618static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask)
619{
620    IPCThreadState::self()->setStrictModePolicy(policyMask);
621}
622
623static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz)
624{
625    return IPCThreadState::self()->getStrictModePolicy();
626}
627
628static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz)
629{
630    IPCThreadState::self()->flushCommands();
631}
632
633static void android_os_Binder_init(JNIEnv* env, jobject clazz)
634{
635    JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz);
636    if (jbh == NULL) {
637        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
638        return;
639    }
640    LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh);
641    jbh->incStrong(clazz);
642    env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh);
643}
644
645static void android_os_Binder_destroy(JNIEnv* env, jobject clazz)
646{
647    JavaBBinderHolder* jbh = (JavaBBinderHolder*)
648        env->GetIntField(clazz, gBinderOffsets.mObject);
649    if (jbh != NULL) {
650        env->SetIntField(clazz, gBinderOffsets.mObject, 0);
651        LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh);
652        jbh->decStrong(clazz);
653    } else {
654        // Encountering an uninitialized binder is harmless.  All it means is that
655        // the Binder was only partially initialized when its finalizer ran and called
656        // destroy().  The Binder could be partially initialized for several reasons.
657        // For example, a Binder subclass constructor might have thrown an exception before
658        // it could delegate to its superclass's constructor.  Consequently init() would
659        // not have been called and the holder pointer would remain NULL.
660        LOGV("Java Binder %p: ignoring uninitialized binder", clazz);
661    }
662}
663
664// ----------------------------------------------------------------------------
665
666static const JNINativeMethod gBinderMethods[] = {
667     /* name, signature, funcPtr */
668    { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
669    { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
670    { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
671    { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
672    { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
673    { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
674    { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
675    { "init", "()V", (void*)android_os_Binder_init },
676    { "destroy", "()V", (void*)android_os_Binder_destroy }
677};
678
679const char* const kBinderPathName = "android/os/Binder";
680
681static int int_register_android_os_Binder(JNIEnv* env)
682{
683    jclass clazz;
684
685    clazz = env->FindClass(kBinderPathName);
686    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");
687
688    gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
689    gBinderOffsets.mExecTransact
690        = env->GetMethodID(clazz, "execTransact", "(IIII)Z");
691    assert(gBinderOffsets.mExecTransact);
692
693    gBinderOffsets.mObject
694        = env->GetFieldID(clazz, "mObject", "I");
695    assert(gBinderOffsets.mObject);
696
697    return AndroidRuntime::registerNativeMethods(
698        env, kBinderPathName,
699        gBinderMethods, NELEM(gBinderMethods));
700}
701
702// ****************************************************************************
703// ****************************************************************************
704// ****************************************************************************
705
706namespace android {
707
708jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz)
709{
710    return gNumLocalRefs;
711}
712
713jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
714{
715    return gNumProxyRefs;
716}
717
718jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
719{
720    return gNumDeathRefs;
721}
722
723}
724
725// ****************************************************************************
726// ****************************************************************************
727// ****************************************************************************
728
729static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
730{
731    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
732    return javaObjectForIBinder(env, b);
733}
734
735static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz)
736{
737    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
738    android::IPCThreadState::self()->joinThreadPool();
739}
740
741static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env,
742        jobject clazz, jboolean disable)
743{
744    IPCThreadState::disableBackgroundScheduling(disable ? true : false);
745}
746
747static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz)
748{
749    LOGV("Gc has executed, clearing binder ops");
750    android_atomic_and(0, &gNumRefsCreated);
751}
752
753// ----------------------------------------------------------------------------
754
755static const JNINativeMethod gBinderInternalMethods[] = {
756     /* name, signature, funcPtr */
757    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
758    { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
759    { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
760    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
761};
762
763const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
764
765static int int_register_android_os_BinderInternal(JNIEnv* env)
766{
767    jclass clazz;
768
769    clazz = env->FindClass(kBinderInternalPathName);
770    LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal");
771
772    gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
773    gBinderInternalOffsets.mForceGc
774        = env->GetStaticMethodID(clazz, "forceBinderGc", "()V");
775    assert(gBinderInternalOffsets.mForceGc);
776
777    return AndroidRuntime::registerNativeMethods(
778        env, kBinderInternalPathName,
779        gBinderInternalMethods, NELEM(gBinderInternalMethods));
780}
781
782// ****************************************************************************
783// ****************************************************************************
784// ****************************************************************************
785
786static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj)
787{
788    IBinder* target = (IBinder*)
789        env->GetIntField(obj, gBinderProxyOffsets.mObject);
790    if (target == NULL) {
791        return JNI_FALSE;
792    }
793    status_t err = target->pingBinder();
794    return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
795}
796
797static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj)
798{
799    IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject);
800    if (target != NULL) {
801        const String16& desc = target->getInterfaceDescriptor();
802        return env->NewString(desc.string(), desc.size());
803    }
804    jniThrowException(env, "java/lang/RuntimeException",
805            "No binder found for object");
806    return NULL;
807}
808
809static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj)
810{
811    IBinder* target = (IBinder*)
812        env->GetIntField(obj, gBinderProxyOffsets.mObject);
813    if (target == NULL) {
814        return JNI_FALSE;
815    }
816    bool alive = target->isBinderAlive();
817    return alive ? JNI_TRUE : JNI_FALSE;
818}
819
820static int getprocname(pid_t pid, char *buf, size_t len) {
821    char filename[20];
822    FILE *f;
823
824    sprintf(filename, "/proc/%d/cmdline", pid);
825    f = fopen(filename, "r");
826    if (!f) { *buf = '\0'; return 1; }
827    if (!fgets(buf, len, f)) { *buf = '\0'; return 2; }
828    fclose(f);
829    return 0;
830}
831
832static bool push_eventlog_string(char** pos, const char* end, const char* str) {
833    jint len = strlen(str);
834    int space_needed = 1 + sizeof(len) + len;
835    if (end - *pos < space_needed) {
836        LOGW("not enough space for string. remain=%d; needed=%d",
837             (end - *pos), space_needed);
838        return false;
839    }
840    **pos = EVENT_TYPE_STRING;
841    (*pos)++;
842    memcpy(*pos, &len, sizeof(len));
843    *pos += sizeof(len);
844    memcpy(*pos, str, len);
845    *pos += len;
846    return true;
847}
848
849static bool push_eventlog_int(char** pos, const char* end, jint val) {
850    int space_needed = 1 + sizeof(val);
851    if (end - *pos < space_needed) {
852        LOGW("not enough space for int.  remain=%d; needed=%d",
853             (end - *pos), space_needed);
854        return false;
855    }
856    **pos = EVENT_TYPE_INT;
857    (*pos)++;
858    memcpy(*pos, &val, sizeof(val));
859    *pos += sizeof(val);
860    return true;
861}
862
863// From frameworks/base/core/java/android/content/EventLogTags.logtags:
864#define LOGTAG_BINDER_OPERATION 52004
865
866static void conditionally_log_binder_call(int64_t start_millis,
867                                          IBinder* target, jint code) {
868    int duration_ms = static_cast<int>(uptimeMillis() - start_millis);
869
870    int sample_percent;
871    if (duration_ms >= 500) {
872        sample_percent = 100;
873    } else {
874        sample_percent = 100 * duration_ms / 500;
875        if (sample_percent == 0) {
876            return;
877        }
878        if (sample_percent < (random() % 100 + 1)) {
879            return;
880        }
881    }
882
883    char process_name[40];
884    getprocname(getpid(), process_name, sizeof(process_name));
885    String8 desc(target->getInterfaceDescriptor());
886
887    char buf[LOGGER_ENTRY_MAX_PAYLOAD];
888    buf[0] = EVENT_TYPE_LIST;
889    buf[1] = 5;
890    char* pos = &buf[2];
891    char* end = &buf[LOGGER_ENTRY_MAX_PAYLOAD - 1];  // leave room for final \n
892    if (!push_eventlog_string(&pos, end, desc.string())) return;
893    if (!push_eventlog_int(&pos, end, code)) return;
894    if (!push_eventlog_int(&pos, end, duration_ms)) return;
895    if (!push_eventlog_string(&pos, end, process_name)) return;
896    if (!push_eventlog_int(&pos, end, sample_percent)) return;
897    *(pos++) = '\n';   // conventional with EVENT_TYPE_LIST apparently.
898    android_bWriteLog(LOGTAG_BINDER_OPERATION, buf, pos - buf);
899}
900
901// We only measure binder call durations to potentially log them if
902// we're on the main thread.  Unfortunately sim-eng doesn't seem to
903// have gettid, so we just ignore this and don't log if we can't
904// get the thread id.
905static bool should_time_binder_calls() {
906#ifdef HAVE_GETTID
907  return (getpid() == androidGetTid());
908#else
909#warning no gettid(), so not logging Binder calls...
910  return false;
911#endif
912}
913
914static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
915                                                jint code, jobject dataObj,
916                                                jobject replyObj, jint flags)
917{
918    if (dataObj == NULL) {
919        jniThrowException(env, "java/lang/NullPointerException", NULL);
920        return JNI_FALSE;
921    }
922
923    Parcel* data = parcelForJavaObject(env, dataObj);
924    if (data == NULL) {
925        return JNI_FALSE;
926    }
927    Parcel* reply = parcelForJavaObject(env, replyObj);
928    if (reply == NULL && replyObj != NULL) {
929        return JNI_FALSE;
930    }
931
932    IBinder* target = (IBinder*)
933        env->GetIntField(obj, gBinderProxyOffsets.mObject);
934    if (target == NULL) {
935        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
936        return JNI_FALSE;
937    }
938
939    LOGV("Java code calling transact on %p in Java object %p with code %d\n",
940            target, obj, code);
941
942    // Only log the binder call duration for things on the Java-level main thread.
943    // But if we don't
944    const bool time_binder_calls = should_time_binder_calls();
945
946    int64_t start_millis;
947    if (time_binder_calls) {
948        start_millis = uptimeMillis();
949    }
950    //printf("Transact from Java code to %p sending: ", target); data->print();
951    status_t err = target->transact(code, *data, reply, flags);
952    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
953    if (time_binder_calls) {
954        conditionally_log_binder_call(start_millis, target, code);
955    }
956
957    if (err == NO_ERROR) {
958        return JNI_TRUE;
959    } else if (err == UNKNOWN_TRANSACTION) {
960        return JNI_FALSE;
961    }
962
963    signalExceptionForError(env, obj, err);
964    return JNI_FALSE;
965}
966
967static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
968                                               jobject recipient, jint flags)
969{
970    if (recipient == NULL) {
971        jniThrowException(env, "java/lang/NullPointerException", NULL);
972        return;
973    }
974
975    IBinder* target = (IBinder*)
976        env->GetIntField(obj, gBinderProxyOffsets.mObject);
977    if (target == NULL) {
978        LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
979        assert(false);
980    }
981
982    LOGV("linkToDeath: binder=%p recipient=%p\n", target, recipient);
983
984    if (!target->localBinder()) {
985        sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient);
986        status_t err = target->linkToDeath(jdr, recipient, flags);
987        if (err != NO_ERROR) {
988            // Failure adding the death recipient, so clear its reference
989            // now.
990            jdr->clearReference();
991            signalExceptionForError(env, obj, err);
992        }
993    }
994}
995
996static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
997                                                 jobject recipient, jint flags)
998{
999    jboolean res = JNI_FALSE;
1000    if (recipient == NULL) {
1001        jniThrowException(env, "java/lang/NullPointerException", NULL);
1002        return res;
1003    }
1004
1005    IBinder* target = (IBinder*)
1006        env->GetIntField(obj, gBinderProxyOffsets.mObject);
1007    if (target == NULL) {
1008        LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
1009        return JNI_FALSE;
1010    }
1011
1012    LOGV("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
1013
1014    if (!target->localBinder()) {
1015        wp<IBinder::DeathRecipient> dr;
1016        status_t err = target->unlinkToDeath(NULL, recipient, flags, &dr);
1017        if (err == NO_ERROR && dr != NULL) {
1018            sp<IBinder::DeathRecipient> sdr = dr.promote();
1019            JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get());
1020            if (jdr != NULL) {
1021                jdr->clearReference();
1022            }
1023        }
1024        if (err == NO_ERROR || err == DEAD_OBJECT) {
1025            res = JNI_TRUE;
1026        } else {
1027            jniThrowException(env, "java/util/NoSuchElementException",
1028                              "Death link does not exist");
1029        }
1030    }
1031
1032    return res;
1033}
1034
1035static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj)
1036{
1037    IBinder* b = (IBinder*)
1038        env->GetIntField(obj, gBinderProxyOffsets.mObject);
1039    LOGV("Destroying BinderProxy %p: binder=%p\n", obj, b);
1040    env->SetIntField(obj, gBinderProxyOffsets.mObject, 0);
1041    b->decStrong(obj);
1042    IPCThreadState::self()->flushCommands();
1043}
1044
1045// ----------------------------------------------------------------------------
1046
1047static const JNINativeMethod gBinderProxyMethods[] = {
1048     /* name, signature, funcPtr */
1049    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
1050    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
1051    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
1052    {"transact",            "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
1053    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
1054    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
1055    {"destroy",             "()V", (void*)android_os_BinderProxy_destroy},
1056};
1057
1058const char* const kBinderProxyPathName = "android/os/BinderProxy";
1059
1060static int int_register_android_os_BinderProxy(JNIEnv* env)
1061{
1062    jclass clazz;
1063
1064    clazz = env->FindClass("java/lang/ref/WeakReference");
1065    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.ref.WeakReference");
1066    gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1067    gWeakReferenceOffsets.mGet
1068        = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;");
1069    assert(gWeakReferenceOffsets.mGet);
1070
1071    clazz = env->FindClass("java/lang/Error");
1072    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error");
1073    gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1074
1075    clazz = env->FindClass(kBinderProxyPathName);
1076    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy");
1077
1078    gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1079    gBinderProxyOffsets.mConstructor
1080        = env->GetMethodID(clazz, "<init>", "()V");
1081    assert(gBinderProxyOffsets.mConstructor);
1082    gBinderProxyOffsets.mSendDeathNotice
1083        = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V");
1084    assert(gBinderProxyOffsets.mSendDeathNotice);
1085
1086    gBinderProxyOffsets.mObject
1087        = env->GetFieldID(clazz, "mObject", "I");
1088    assert(gBinderProxyOffsets.mObject);
1089    gBinderProxyOffsets.mSelf
1090        = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
1091    assert(gBinderProxyOffsets.mSelf);
1092
1093    return AndroidRuntime::registerNativeMethods(
1094        env, kBinderProxyPathName,
1095        gBinderProxyMethods, NELEM(gBinderProxyMethods));
1096}
1097
1098// ****************************************************************************
1099// ****************************************************************************
1100// ****************************************************************************
1101
1102static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz)
1103{
1104    Parcel* parcel = parcelForJavaObject(env, clazz);
1105    return parcel ? parcel->dataSize() : 0;
1106}
1107
1108static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz)
1109{
1110    Parcel* parcel = parcelForJavaObject(env, clazz);
1111    return parcel ? parcel->dataAvail() : 0;
1112}
1113
1114static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz)
1115{
1116    Parcel* parcel = parcelForJavaObject(env, clazz);
1117    return parcel ? parcel->dataPosition() : 0;
1118}
1119
1120static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz)
1121{
1122    Parcel* parcel = parcelForJavaObject(env, clazz);
1123    return parcel ? parcel->dataCapacity() : 0;
1124}
1125
1126static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size)
1127{
1128    Parcel* parcel = parcelForJavaObject(env, clazz);
1129    if (parcel != NULL) {
1130        const status_t err = parcel->setDataSize(size);
1131        if (err != NO_ERROR) {
1132            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1133        }
1134    }
1135}
1136
1137static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos)
1138{
1139    Parcel* parcel = parcelForJavaObject(env, clazz);
1140    if (parcel != NULL) {
1141        parcel->setDataPosition(pos);
1142    }
1143}
1144
1145static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size)
1146{
1147    Parcel* parcel = parcelForJavaObject(env, clazz);
1148    if (parcel != NULL) {
1149        const status_t err = parcel->setDataCapacity(size);
1150        if (err != NO_ERROR) {
1151            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1152        }
1153    }
1154}
1155
1156static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
1157                                          jobject data, jint offset,
1158                                          jint length)
1159{
1160    Parcel* parcel = parcelForJavaObject(env, clazz);
1161    if (parcel == NULL) {
1162        return;
1163    }
1164    void *dest;
1165
1166    const status_t err = parcel->writeInt32(length);
1167    if (err != NO_ERROR) {
1168        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1169    }
1170
1171    dest = parcel->writeInplace(length);
1172
1173    if (dest == NULL) {
1174        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1175        return;
1176    }
1177
1178    jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
1179    if (ar) {
1180        memcpy(dest, ar, length);
1181        env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
1182    }
1183}
1184
1185
1186static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
1187{
1188    Parcel* parcel = parcelForJavaObject(env, clazz);
1189    if (parcel != NULL) {
1190        const status_t err = parcel->writeInt32(val);
1191        if (err != NO_ERROR) {
1192            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1193        }
1194    }
1195}
1196
1197static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
1198{
1199    Parcel* parcel = parcelForJavaObject(env, clazz);
1200    if (parcel != NULL) {
1201        const status_t err = parcel->writeInt64(val);
1202        if (err != NO_ERROR) {
1203            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1204        }
1205    }
1206}
1207
1208static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
1209{
1210    Parcel* parcel = parcelForJavaObject(env, clazz);
1211    if (parcel != NULL) {
1212        const status_t err = parcel->writeFloat(val);
1213        if (err != NO_ERROR) {
1214            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1215        }
1216    }
1217}
1218
1219static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val)
1220{
1221    Parcel* parcel = parcelForJavaObject(env, clazz);
1222    if (parcel != NULL) {
1223        const status_t err = parcel->writeDouble(val);
1224        if (err != NO_ERROR) {
1225            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1226        }
1227    }
1228}
1229
1230static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val)
1231{
1232    Parcel* parcel = parcelForJavaObject(env, clazz);
1233    if (parcel != NULL) {
1234        status_t err = NO_MEMORY;
1235        if (val) {
1236            const jchar* str = env->GetStringCritical(val, 0);
1237            if (str) {
1238                err = parcel->writeString16(str, env->GetStringLength(val));
1239                env->ReleaseStringCritical(val, str);
1240            }
1241        } else {
1242            err = parcel->writeString16(NULL, 0);
1243        }
1244        if (err != NO_ERROR) {
1245            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1246        }
1247    }
1248}
1249
1250static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
1251{
1252    Parcel* parcel = parcelForJavaObject(env, clazz);
1253    if (parcel != NULL) {
1254        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
1255        if (err != NO_ERROR) {
1256            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1257        }
1258    }
1259}
1260
1261static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1262{
1263    Parcel* parcel = parcelForJavaObject(env, clazz);
1264    if (parcel != NULL) {
1265        const status_t err = parcel->writeDupFileDescriptor(
1266                env->GetIntField(object, gFileDescriptorOffsets.mDescriptor));
1267        if (err != NO_ERROR) {
1268            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1269        }
1270    }
1271}
1272
1273static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz)
1274{
1275    jbyteArray ret = NULL;
1276
1277    Parcel* parcel = parcelForJavaObject(env, clazz);
1278    if (parcel != NULL) {
1279        int32_t len = parcel->readInt32();
1280
1281        // sanity check the stored length against the true data size
1282        if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
1283            ret = env->NewByteArray(len);
1284
1285            if (ret != NULL) {
1286                jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
1287                if (a2) {
1288                    const void* data = parcel->readInplace(len);
1289                    memcpy(a2, data, len);
1290                    env->ReleasePrimitiveArrayCritical(ret, a2, 0);
1291                }
1292            }
1293        }
1294    }
1295
1296    return ret;
1297}
1298
1299static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz)
1300{
1301    Parcel* parcel = parcelForJavaObject(env, clazz);
1302    if (parcel != NULL) {
1303        return parcel->readInt32();
1304    }
1305    return 0;
1306}
1307
1308static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz)
1309{
1310    Parcel* parcel = parcelForJavaObject(env, clazz);
1311    if (parcel != NULL) {
1312        return parcel->readInt64();
1313    }
1314    return 0;
1315}
1316
1317static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz)
1318{
1319    Parcel* parcel = parcelForJavaObject(env, clazz);
1320    if (parcel != NULL) {
1321        return parcel->readFloat();
1322    }
1323    return 0;
1324}
1325
1326static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz)
1327{
1328    Parcel* parcel = parcelForJavaObject(env, clazz);
1329    if (parcel != NULL) {
1330        return parcel->readDouble();
1331    }
1332    return 0;
1333}
1334
1335static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz)
1336{
1337    Parcel* parcel = parcelForJavaObject(env, clazz);
1338    if (parcel != NULL) {
1339        size_t len;
1340        const char16_t* str = parcel->readString16Inplace(&len);
1341        if (str) {
1342            return env->NewString(str, len);
1343        }
1344        return NULL;
1345    }
1346    return NULL;
1347}
1348
1349static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
1350{
1351    Parcel* parcel = parcelForJavaObject(env, clazz);
1352    if (parcel != NULL) {
1353        return javaObjectForIBinder(env, parcel->readStrongBinder());
1354    }
1355    return NULL;
1356}
1357
1358static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz)
1359{
1360    Parcel* parcel = parcelForJavaObject(env, clazz);
1361    if (parcel != NULL) {
1362        int fd = parcel->readFileDescriptor();
1363        if (fd < 0) return NULL;
1364        fd = dup(fd);
1365        if (fd < 0) return NULL;
1366        jobject object = env->NewObject(
1367                gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor);
1368        if (object != NULL) {
1369            //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd);
1370            env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd);
1371        }
1372        return object;
1373    }
1374    return NULL;
1375}
1376
1377static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz,
1378                                                    jstring name, jint mode)
1379{
1380    if (name == NULL) {
1381        jniThrowException(env, "java/lang/NullPointerException", NULL);
1382        return NULL;
1383    }
1384    const jchar* str = env->GetStringCritical(name, 0);
1385    if (str == NULL) {
1386        // Whatever, whatever.
1387        jniThrowException(env, "java/lang/IllegalStateException", NULL);
1388        return NULL;
1389    }
1390    String8 name8(str, env->GetStringLength(name));
1391    env->ReleaseStringCritical(name, str);
1392    int flags=0;
1393    switch (mode&0x30000000) {
1394        case 0:
1395        case 0x10000000:
1396            flags = O_RDONLY;
1397            break;
1398        case 0x20000000:
1399            flags = O_WRONLY;
1400            break;
1401        case 0x30000000:
1402            flags = O_RDWR;
1403            break;
1404    }
1405
1406    if (mode&0x08000000) flags |= O_CREAT;
1407    if (mode&0x04000000) flags |= O_TRUNC;
1408    if (mode&0x02000000) flags |= O_APPEND;
1409
1410    int realMode = S_IRWXU|S_IRWXG;
1411    if (mode&0x00000001) realMode |= S_IROTH;
1412    if (mode&0x00000002) realMode |= S_IWOTH;
1413
1414    int fd = open(name8.string(), flags, realMode);
1415    if (fd < 0) {
1416        jniThrowException(env, "java/io/FileNotFoundException", NULL);
1417        return NULL;
1418    }
1419    jobject object = newFileDescriptor(env, fd);
1420    if (object == NULL) {
1421        close(fd);
1422    }
1423    return object;
1424}
1425
1426static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1427{
1428    int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
1429    if (fd >= 0) {
1430        env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1);
1431        //LOGI("Closing ParcelFileDescriptor %d\n", fd);
1432        close(fd);
1433    }
1434}
1435
1436static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz)
1437{
1438    int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
1439    if (own) {
1440        Parcel* parcel = parcelForJavaObject(env, clazz);
1441        if (parcel != NULL) {
1442            //LOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel);
1443            parcel->freeData();
1444        }
1445    }
1446}
1447
1448static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt)
1449{
1450    Parcel* parcel = (Parcel*)parcelInt;
1451    int own = 0;
1452    if (!parcel) {
1453        //LOGI("Initializing obj %p: creating new Parcel\n", clazz);
1454        own = 1;
1455        parcel = new Parcel;
1456    } else {
1457        //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel);
1458    }
1459    if (parcel == NULL) {
1460        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1461        return;
1462    }
1463    //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own);
1464    env->SetIntField(clazz, gParcelOffsets.mOwnObject, own);
1465    env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel);
1466}
1467
1468static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz)
1469{
1470    int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
1471    if (own) {
1472        Parcel* parcel = parcelForJavaObject(env, clazz);
1473        env->SetIntField(clazz, gParcelOffsets.mObject, 0);
1474        //LOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel);
1475        delete parcel;
1476    } else {
1477        env->SetIntField(clazz, gParcelOffsets.mObject, 0);
1478        //LOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz);
1479    }
1480}
1481
1482static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz)
1483{
1484    Parcel* parcel = parcelForJavaObject(env, clazz);
1485    if (parcel == NULL) {
1486       return NULL;
1487    }
1488
1489    // do not marshall if there are binder objects in the parcel
1490    if (parcel->objectsCount())
1491    {
1492        jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
1493        return NULL;
1494    }
1495
1496    jbyteArray ret = env->NewByteArray(parcel->dataSize());
1497
1498    if (ret != NULL)
1499    {
1500        jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
1501        if (array != NULL)
1502        {
1503            memcpy(array, parcel->data(), parcel->dataSize());
1504            env->ReleasePrimitiveArrayCritical(ret, array, 0);
1505        }
1506    }
1507
1508    return ret;
1509}
1510
1511static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length)
1512{
1513    Parcel* parcel = parcelForJavaObject(env, clazz);
1514    if (parcel == NULL || length < 0) {
1515       return;
1516    }
1517
1518    jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
1519    if (array)
1520    {
1521        parcel->setDataSize(length);
1522        parcel->setDataPosition(0);
1523
1524        void* raw = parcel->writeInplace(length);
1525        memcpy(raw, (array + offset), length);
1526
1527        env->ReleasePrimitiveArrayCritical(data, array, 0);
1528    }
1529}
1530
1531static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length)
1532{
1533    Parcel* thisParcel = parcelForJavaObject(env, clazz);
1534    if (thisParcel == NULL) {
1535       return;
1536    }
1537    Parcel* otherParcel = parcelForJavaObject(env, parcel);
1538    if (otherParcel == NULL) {
1539       return;
1540    }
1541
1542    (void) thisParcel->appendFrom(otherParcel, offset, length);
1543}
1544
1545static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
1546{
1547    jboolean ret = JNI_FALSE;
1548    Parcel* parcel = parcelForJavaObject(env, clazz);
1549    if (parcel != NULL) {
1550        if (parcel->hasFileDescriptors()) {
1551            ret = JNI_TRUE;
1552        }
1553    }
1554    return ret;
1555}
1556
1557static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name)
1558{
1559    Parcel* parcel = parcelForJavaObject(env, clazz);
1560    if (parcel != NULL) {
1561        // In the current implementation, the token is just the serialized interface name that
1562        // the caller expects to be invoking
1563        const jchar* str = env->GetStringCritical(name, 0);
1564        if (str != NULL) {
1565            parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
1566            env->ReleaseStringCritical(name, str);
1567        }
1568    }
1569}
1570
1571static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name)
1572{
1573    jboolean ret = JNI_FALSE;
1574
1575    Parcel* parcel = parcelForJavaObject(env, clazz);
1576    if (parcel != NULL) {
1577        const jchar* str = env->GetStringCritical(name, 0);
1578        if (str) {
1579            IPCThreadState* threadState = IPCThreadState::self();
1580            const int32_t oldPolicy = threadState->getStrictModePolicy();
1581            const bool isValid = parcel->enforceInterface(
1582                String16(str, env->GetStringLength(name)),
1583                threadState);
1584            env->ReleaseStringCritical(name, str);
1585            if (isValid) {
1586                const int32_t newPolicy = threadState->getStrictModePolicy();
1587                if (oldPolicy != newPolicy) {
1588                    // Need to keep the Java-level thread-local strict
1589                    // mode policy in sync for the libcore
1590                    // enforcements, which involves an upcall back
1591                    // into Java.  (We can't modify the
1592                    // Parcel.enforceInterface signature, as it's
1593                    // pseudo-public, and used via AIDL
1594                    // auto-generation...)
1595                    set_dalvik_blockguard_policy(env, newPolicy);
1596                }
1597                return;     // everything was correct -> return silently
1598            }
1599        }
1600    }
1601
1602    // all error conditions wind up here
1603    jniThrowException(env, "java/lang/SecurityException",
1604            "Binder invocation to an incorrect interface");
1605}
1606
1607// ----------------------------------------------------------------------------
1608
1609static const JNINativeMethod gParcelMethods[] = {
1610    {"dataSize",            "()I", (void*)android_os_Parcel_dataSize},
1611    {"dataAvail",           "()I", (void*)android_os_Parcel_dataAvail},
1612    {"dataPosition",        "()I", (void*)android_os_Parcel_dataPosition},
1613    {"dataCapacity",        "()I", (void*)android_os_Parcel_dataCapacity},
1614    {"setDataSize",         "(I)V", (void*)android_os_Parcel_setDataSize},
1615    {"setDataPosition",     "(I)V", (void*)android_os_Parcel_setDataPosition},
1616    {"setDataCapacity",     "(I)V", (void*)android_os_Parcel_setDataCapacity},
1617    {"writeNative",         "([BII)V", (void*)android_os_Parcel_writeNative},
1618    {"writeInt",            "(I)V", (void*)android_os_Parcel_writeInt},
1619    {"writeLong",           "(J)V", (void*)android_os_Parcel_writeLong},
1620    {"writeFloat",          "(F)V", (void*)android_os_Parcel_writeFloat},
1621    {"writeDouble",         "(D)V", (void*)android_os_Parcel_writeDouble},
1622    {"writeString",         "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString},
1623    {"writeStrongBinder",   "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
1624    {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
1625    {"createByteArray",     "()[B", (void*)android_os_Parcel_createByteArray},
1626    {"readInt",             "()I", (void*)android_os_Parcel_readInt},
1627    {"readLong",            "()J", (void*)android_os_Parcel_readLong},
1628    {"readFloat",           "()F", (void*)android_os_Parcel_readFloat},
1629    {"readDouble",          "()D", (void*)android_os_Parcel_readDouble},
1630    {"readString",          "()Ljava/lang/String;", (void*)android_os_Parcel_readString},
1631    {"readStrongBinder",    "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
1632    {"internalReadFileDescriptor",  "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
1633    {"openFileDescriptor",  "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
1634    {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
1635    {"freeBuffer",          "()V", (void*)android_os_Parcel_freeBuffer},
1636    {"init",                "(I)V", (void*)android_os_Parcel_init},
1637    {"destroy",             "()V", (void*)android_os_Parcel_destroy},
1638    {"marshall",            "()[B", (void*)android_os_Parcel_marshall},
1639    {"unmarshall",          "([BII)V", (void*)android_os_Parcel_unmarshall},
1640    {"appendFrom",          "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom},
1641    {"hasFileDescriptors",  "()Z", (void*)android_os_Parcel_hasFileDescriptors},
1642    {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
1643    {"enforceInterface",    "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
1644};
1645
1646const char* const kParcelPathName = "android/os/Parcel";
1647
1648static int int_register_android_os_Parcel(JNIEnv* env)
1649{
1650    jclass clazz;
1651
1652    clazz = env->FindClass("android/util/Log");
1653    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log");
1654    gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1655    gLogOffsets.mLogE = env->GetStaticMethodID(
1656        clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
1657    assert(gLogOffsets.mLogE);
1658
1659    clazz = env->FindClass("java/io/FileDescriptor");
1660    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
1661    gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1662    gFileDescriptorOffsets.mConstructor
1663        = env->GetMethodID(clazz, "<init>", "()V");
1664    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
1665    LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
1666                 "Unable to find descriptor field in java.io.FileDescriptor");
1667
1668    clazz = env->FindClass("android/os/ParcelFileDescriptor");
1669    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
1670    gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1671    gParcelFileDescriptorOffsets.mConstructor
1672        = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
1673
1674    clazz = env->FindClass(kParcelPathName);
1675    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
1676
1677    gParcelOffsets.mObject
1678        = env->GetFieldID(clazz, "mObject", "I");
1679    gParcelOffsets.mOwnObject
1680        = env->GetFieldID(clazz, "mOwnObject", "I");
1681
1682    clazz = env->FindClass("android/os/StrictMode");
1683    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
1684    gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1685    gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID(
1686        clazz, "onBinderStrictModePolicyChange", "(I)V");
1687    LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
1688                 "Unable to find strict mode callback.");
1689
1690    return AndroidRuntime::registerNativeMethods(
1691        env, kParcelPathName,
1692        gParcelMethods, NELEM(gParcelMethods));
1693}
1694
1695int register_android_os_Binder(JNIEnv* env)
1696{
1697    if (int_register_android_os_Binder(env) < 0)
1698        return -1;
1699    if (int_register_android_os_BinderInternal(env) < 0)
1700        return -1;
1701    if (int_register_android_os_BinderProxy(env) < 0)
1702        return -1;
1703    if (int_register_android_os_Parcel(env) < 0)
1704        return -1;
1705    return 0;
1706}
1707
1708namespace android {
1709
1710// Returns the Unix file descriptor for a ParcelFileDescriptor object
1711int getParcelFileDescriptorFD(JNIEnv* env, jobject object)
1712{
1713    return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
1714}
1715
1716}
1717