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