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