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_os_Parcel.h"
21#include "android_util_Binder.h"
22
23#include <nativehelper/JNIHelp.h>
24
25#include <fcntl.h>
26#include <inttypes.h>
27#include <stdio.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30#include <unistd.h>
31
32#include <android-base/stringprintf.h>
33#include <binder/IInterface.h>
34#include <binder/IServiceManager.h>
35#include <binder/IPCThreadState.h>
36#include <binder/Parcel.h>
37#include <binder/ProcessState.h>
38#include <log/log.h>
39#include <utils/Atomic.h>
40#include <utils/KeyedVector.h>
41#include <utils/List.h>
42#include <utils/Log.h>
43#include <utils/String8.h>
44#include <utils/SystemClock.h>
45#include <utils/threads.h>
46
47#include <nativehelper/ScopedUtfChars.h>
48#include <nativehelper/ScopedLocalRef.h>
49
50#include "core_jni_helpers.h"
51
52//#undef ALOGV
53//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
54
55#define DEBUG_DEATH 0
56#if DEBUG_DEATH
57#define LOGDEATH ALOGD
58#else
59#define LOGDEATH ALOGV
60#endif
61
62using namespace android;
63
64// ----------------------------------------------------------------------------
65
66static struct bindernative_offsets_t
67{
68    // Class state.
69    jclass mClass;
70    jmethodID mExecTransact;
71
72    // Object state.
73    jfieldID mObject;
74
75} gBinderOffsets;
76
77// ----------------------------------------------------------------------------
78
79static struct binderinternal_offsets_t
80{
81    // Class state.
82    jclass mClass;
83    jmethodID mForceGc;
84
85} gBinderInternalOffsets;
86
87// ----------------------------------------------------------------------------
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    jfieldID mOrgue;
107
108} gBinderProxyOffsets;
109
110static struct class_offsets_t
111{
112    jmethodID mGetName;
113} gClassOffsets;
114
115// ----------------------------------------------------------------------------
116
117static struct log_offsets_t
118{
119    // Class state.
120    jclass mClass;
121    jmethodID mLogE;
122} gLogOffsets;
123
124static struct parcel_file_descriptor_offsets_t
125{
126    jclass mClass;
127    jmethodID mConstructor;
128} gParcelFileDescriptorOffsets;
129
130static struct strict_mode_callback_offsets_t
131{
132    jclass mClass;
133    jmethodID mCallback;
134} gStrictModeCallbackOffsets;
135
136static struct thread_dispatch_offsets_t
137{
138    // Class state.
139    jclass mClass;
140    jmethodID mDispatchUncaughtException;
141    jmethodID mCurrentThread;
142} gThreadDispatchOffsets;
143
144// ****************************************************************************
145// ****************************************************************************
146// ****************************************************************************
147
148static volatile int32_t gNumRefsCreated = 0;
149static volatile int32_t gNumProxyRefs = 0;
150static volatile int32_t gNumLocalRefs = 0;
151static volatile int32_t gNumDeathRefs = 0;
152
153static void incRefsCreated(JNIEnv* env)
154{
155    int old = android_atomic_inc(&gNumRefsCreated);
156    if (old == 200) {
157        android_atomic_and(0, &gNumRefsCreated);
158        env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
159                gBinderInternalOffsets.mForceGc);
160    } else {
161        ALOGV("Now have %d binder ops", old);
162    }
163}
164
165static JavaVM* jnienv_to_javavm(JNIEnv* env)
166{
167    JavaVM* vm;
168    return env->GetJavaVM(&vm) >= 0 ? vm : NULL;
169}
170
171static JNIEnv* javavm_to_jnienv(JavaVM* vm)
172{
173    JNIEnv* env;
174    return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL;
175}
176
177// Report a java.lang.Error (or subclass). This may terminate the runtime.
178static void report_java_lang_error(JNIEnv* env, jthrowable error)
179{
180    // Try to run the uncaught exception machinery.
181    jobject thread = env->CallStaticObjectMethod(gThreadDispatchOffsets.mClass,
182            gThreadDispatchOffsets.mCurrentThread);
183    if (thread != nullptr) {
184        env->CallVoidMethod(thread, gThreadDispatchOffsets.mDispatchUncaughtException,
185                error);
186        // Should not return here, unless more errors occured.
187    }
188    // Some error occurred that meant that either dispatchUncaughtException could not be
189    // called or that it had an error itself (as this should be unreachable under normal
190    // conditions). Clear the exception.
191    env->ExceptionClear();
192}
193
194static void report_exception(JNIEnv* env, jthrowable excep, const char* msg)
195{
196    env->ExceptionClear();
197
198    jstring tagstr = env->NewStringUTF(LOG_TAG);
199    jstring msgstr = NULL;
200    if (tagstr != NULL) {
201        msgstr = env->NewStringUTF(msg);
202    }
203
204    if ((tagstr == NULL) || (msgstr == NULL)) {
205        env->ExceptionClear();      /* assume exception (OOM?) was thrown */
206        ALOGE("Unable to call Log.e()\n");
207        ALOGE("%s", msg);
208        goto bail;
209    }
210
211    env->CallStaticIntMethod(
212        gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep);
213    if (env->ExceptionCheck()) {
214        /* attempting to log the failure has failed */
215        ALOGW("Failed trying to log exception, msg='%s'\n", msg);
216        env->ExceptionClear();
217    }
218
219    if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) {
220        // Try to report the error. This should not return under normal circumstances.
221        report_java_lang_error(env, excep);
222        // The traditional handling: re-raise and abort.
223
224        /*
225         * It's an Error: Reraise the exception and ask the runtime to abort.
226         */
227
228        // Try to get the exception string. Sometimes logcat isn't available,
229        // so try to add it to the abort message.
230        std::string exc_msg = "(Unknown exception message)";
231        {
232            ScopedLocalRef<jclass> exc_class(env, env->GetObjectClass(excep));
233            jmethodID method_id = env->GetMethodID(exc_class.get(),
234                                                   "toString",
235                                                   "()Ljava/lang/String;");
236            ScopedLocalRef<jstring> jstr(
237                    env,
238                    reinterpret_cast<jstring>(
239                            env->CallObjectMethod(excep, method_id)));
240            env->ExceptionClear();  // Just for good measure.
241            if (jstr.get() != nullptr) {
242                ScopedUtfChars jstr_utf(env, jstr.get());
243                exc_msg = jstr_utf.c_str();
244            }
245        }
246
247        env->Throw(excep);
248        ALOGE("java.lang.Error thrown during binder transaction (stack trace follows) : ");
249        env->ExceptionDescribe();
250
251        std::string error_msg = base::StringPrintf(
252                "java.lang.Error thrown during binder transaction: %s",
253                exc_msg.c_str());
254        env->FatalError(error_msg.c_str());
255    }
256
257bail:
258    /* discard local refs created for us by VM */
259    env->DeleteLocalRef(tagstr);
260    env->DeleteLocalRef(msgstr);
261}
262
263class JavaBBinderHolder;
264
265class JavaBBinder : public BBinder
266{
267public:
268    JavaBBinder(JNIEnv* env, jobject object)
269        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
270    {
271        ALOGV("Creating JavaBBinder %p\n", this);
272        android_atomic_inc(&gNumLocalRefs);
273        incRefsCreated(env);
274    }
275
276    bool    checkSubclass(const void* subclassID) const
277    {
278        return subclassID == &gBinderOffsets;
279    }
280
281    jobject object() const
282    {
283        return mObject;
284    }
285
286protected:
287    virtual ~JavaBBinder()
288    {
289        ALOGV("Destroying JavaBBinder %p\n", this);
290        android_atomic_dec(&gNumLocalRefs);
291        JNIEnv* env = javavm_to_jnienv(mVM);
292        env->DeleteGlobalRef(mObject);
293    }
294
295    virtual status_t onTransact(
296        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
297    {
298        JNIEnv* env = javavm_to_jnienv(mVM);
299
300        ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
301
302        IPCThreadState* thread_state = IPCThreadState::self();
303        const int32_t strict_policy_before = thread_state->getStrictModePolicy();
304
305        //printf("Transact from %p to Java code sending: ", this);
306        //data.print();
307        //printf("\n");
308        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
309            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
310
311        if (env->ExceptionCheck()) {
312            jthrowable excep = env->ExceptionOccurred();
313            report_exception(env, excep,
314                "*** Uncaught remote exception!  "
315                "(Exceptions are not yet supported across processes.)");
316            res = JNI_FALSE;
317
318            /* clean up JNI local ref -- we don't return to Java code */
319            env->DeleteLocalRef(excep);
320        }
321
322        // Check if the strict mode state changed while processing the
323        // call.  The Binder state will be restored by the underlying
324        // Binder system in IPCThreadState, however we need to take care
325        // of the parallel Java state as well.
326        if (thread_state->getStrictModePolicy() != strict_policy_before) {
327            set_dalvik_blockguard_policy(env, strict_policy_before);
328        }
329
330        if (env->ExceptionCheck()) {
331            jthrowable excep = env->ExceptionOccurred();
332            report_exception(env, excep,
333                "*** Uncaught exception in onBinderStrictModePolicyChange");
334            /* clean up JNI local ref -- we don't return to Java code */
335            env->DeleteLocalRef(excep);
336        }
337
338        // Need to always call through the native implementation of
339        // SYSPROPS_TRANSACTION.
340        if (code == SYSPROPS_TRANSACTION) {
341            BBinder::onTransact(code, data, reply, flags);
342        }
343
344        //aout << "onTransact to Java code; result=" << res << endl
345        //    << "Transact from " << this << " to Java code returning "
346        //    << reply << ": " << *reply << endl;
347        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
348    }
349
350    virtual status_t dump(int fd, const Vector<String16>& args)
351    {
352        return 0;
353    }
354
355private:
356    JavaVM* const   mVM;
357    jobject const   mObject;
358};
359
360// ----------------------------------------------------------------------------
361
362class JavaBBinderHolder : public RefBase
363{
364public:
365    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
366    {
367        AutoMutex _l(mLock);
368        sp<JavaBBinder> b = mBinder.promote();
369        if (b == NULL) {
370            b = new JavaBBinder(env, obj);
371            mBinder = b;
372            ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
373                 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
374        }
375
376        return b;
377    }
378
379    sp<JavaBBinder> getExisting()
380    {
381        AutoMutex _l(mLock);
382        return mBinder.promote();
383    }
384
385private:
386    Mutex           mLock;
387    wp<JavaBBinder> mBinder;
388};
389
390// ----------------------------------------------------------------------------
391
392// Per-IBinder death recipient bookkeeping.  This is how we reconcile local jobject
393// death recipient references passed in through JNI with the permanent corresponding
394// JavaDeathRecipient objects.
395
396class JavaDeathRecipient;
397
398class DeathRecipientList : public RefBase {
399    List< sp<JavaDeathRecipient> > mList;
400    Mutex mLock;
401
402public:
403    DeathRecipientList();
404    ~DeathRecipientList();
405
406    void add(const sp<JavaDeathRecipient>& recipient);
407    void remove(const sp<JavaDeathRecipient>& recipient);
408    sp<JavaDeathRecipient> find(jobject recipient);
409
410    Mutex& lock();  // Use with care; specifically for mutual exclusion during binder death
411};
412
413// ----------------------------------------------------------------------------
414
415class JavaDeathRecipient : public IBinder::DeathRecipient
416{
417public:
418    JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
419        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
420          mObjectWeak(NULL), mList(list)
421    {
422        // These objects manage their own lifetimes so are responsible for final bookkeeping.
423        // The list holds a strong reference to this object.
424        LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
425        list->add(this);
426
427        android_atomic_inc(&gNumDeathRefs);
428        incRefsCreated(env);
429    }
430
431    void binderDied(const wp<IBinder>& who)
432    {
433        LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
434        if (mObject != NULL) {
435            JNIEnv* env = javavm_to_jnienv(mVM);
436
437            env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
438                    gBinderProxyOffsets.mSendDeathNotice, mObject);
439            if (env->ExceptionCheck()) {
440                jthrowable excep = env->ExceptionOccurred();
441                report_exception(env, excep,
442                        "*** Uncaught exception returned from death notification!");
443            }
444
445            // Serialize with our containing DeathRecipientList so that we can't
446            // delete the global ref on mObject while the list is being iterated.
447            sp<DeathRecipientList> list = mList.promote();
448            if (list != NULL) {
449                AutoMutex _l(list->lock());
450
451                // Demote from strong ref to weak after binderDied() has been delivered,
452                // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
453                mObjectWeak = env->NewWeakGlobalRef(mObject);
454                env->DeleteGlobalRef(mObject);
455                mObject = NULL;
456            }
457        }
458    }
459
460    void clearReference()
461    {
462        sp<DeathRecipientList> list = mList.promote();
463        if (list != NULL) {
464            LOGDEATH("Removing JDR %p from DRL %p", this, list.get());
465            list->remove(this);
466        } else {
467            LOGDEATH("clearReference() on JDR %p but DRL wp purged", this);
468        }
469    }
470
471    bool matches(jobject obj) {
472        bool result;
473        JNIEnv* env = javavm_to_jnienv(mVM);
474
475        if (mObject != NULL) {
476            result = env->IsSameObject(obj, mObject);
477        } else {
478            jobject me = env->NewLocalRef(mObjectWeak);
479            result = env->IsSameObject(obj, me);
480            env->DeleteLocalRef(me);
481        }
482        return result;
483    }
484
485    void warnIfStillLive() {
486        if (mObject != NULL) {
487            // Okay, something is wrong -- we have a hard reference to a live death
488            // recipient on the VM side, but the list is being torn down.
489            JNIEnv* env = javavm_to_jnienv(mVM);
490            ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
491            ScopedLocalRef<jstring> nameRef(env,
492                    (jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName));
493            ScopedUtfChars nameUtf(env, nameRef.get());
494            if (nameUtf.c_str() != NULL) {
495                ALOGW("BinderProxy is being destroyed but the application did not call "
496                        "unlinkToDeath to unlink all of its death recipients beforehand.  "
497                        "Releasing leaked death recipient: %s", nameUtf.c_str());
498            } else {
499                ALOGW("BinderProxy being destroyed; unable to get DR object name");
500                env->ExceptionClear();
501            }
502        }
503    }
504
505protected:
506    virtual ~JavaDeathRecipient()
507    {
508        //ALOGI("Removing death ref: recipient=%p\n", mObject);
509        android_atomic_dec(&gNumDeathRefs);
510        JNIEnv* env = javavm_to_jnienv(mVM);
511        if (mObject != NULL) {
512            env->DeleteGlobalRef(mObject);
513        } else {
514            env->DeleteWeakGlobalRef(mObjectWeak);
515        }
516    }
517
518private:
519    JavaVM* const mVM;
520    jobject mObject;
521    jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied()
522    wp<DeathRecipientList> mList;
523};
524
525// ----------------------------------------------------------------------------
526
527DeathRecipientList::DeathRecipientList() {
528    LOGDEATH("New DRL @ %p", this);
529}
530
531DeathRecipientList::~DeathRecipientList() {
532    LOGDEATH("Destroy DRL @ %p", this);
533    AutoMutex _l(mLock);
534
535    // Should never happen -- the JavaDeathRecipient objects that have added themselves
536    // to the list are holding references on the list object.  Only when they are torn
537    // down can the list header be destroyed.
538    if (mList.size() > 0) {
539        List< sp<JavaDeathRecipient> >::iterator iter;
540        for (iter = mList.begin(); iter != mList.end(); iter++) {
541            (*iter)->warnIfStillLive();
542        }
543    }
544}
545
546void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) {
547    AutoMutex _l(mLock);
548
549    LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get());
550    mList.push_back(recipient);
551}
552
553void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) {
554    AutoMutex _l(mLock);
555
556    List< sp<JavaDeathRecipient> >::iterator iter;
557    for (iter = mList.begin(); iter != mList.end(); iter++) {
558        if (*iter == recipient) {
559            LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get());
560            mList.erase(iter);
561            return;
562        }
563    }
564}
565
566sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) {
567    AutoMutex _l(mLock);
568
569    List< sp<JavaDeathRecipient> >::iterator iter;
570    for (iter = mList.begin(); iter != mList.end(); iter++) {
571        if ((*iter)->matches(recipient)) {
572            return *iter;
573        }
574    }
575    return NULL;
576}
577
578Mutex& DeathRecipientList::lock() {
579    return mLock;
580}
581
582// ----------------------------------------------------------------------------
583
584namespace android {
585
586static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie)
587{
588    android_atomic_dec(&gNumProxyRefs);
589    JNIEnv* env = javavm_to_jnienv((JavaVM*)cleanupCookie);
590    env->DeleteGlobalRef((jobject)obj);
591}
592
593static Mutex mProxyLock;
594
595jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
596{
597    if (val == NULL) return NULL;
598
599    if (val->checkSubclass(&gBinderOffsets)) {
600        // One of our own!
601        jobject object = static_cast<JavaBBinder*>(val.get())->object();
602        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
603        return object;
604    }
605
606    // For the rest of the function we will hold this lock, to serialize
607    // looking/creation/destruction of Java proxies for native Binder proxies.
608    AutoMutex _l(mProxyLock);
609
610    // Someone else's...  do we know about it?
611    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
612    if (object != NULL) {
613        jobject res = jniGetReferent(env, object);
614        if (res != NULL) {
615            ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
616            return res;
617        }
618        LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
619        android_atomic_dec(&gNumProxyRefs);
620        val->detachObject(&gBinderProxyOffsets);
621        env->DeleteGlobalRef(object);
622    }
623
624    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
625    if (object != NULL) {
626        LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
627        // The proxy holds a reference to the native object.
628        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
629        val->incStrong((void*)javaObjectForIBinder);
630
631        // The native object needs to hold a weak reference back to the
632        // proxy, so we can retrieve the same proxy if it is still active.
633        jobject refObject = env->NewGlobalRef(
634                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
635        val->attachObject(&gBinderProxyOffsets, refObject,
636                jnienv_to_javavm(env), proxy_cleanup);
637
638        // Also remember the death recipients registered on this proxy
639        sp<DeathRecipientList> drl = new DeathRecipientList;
640        drl->incStrong((void*)javaObjectForIBinder);
641        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
642
643        // Note that a new object reference has been created.
644        android_atomic_inc(&gNumProxyRefs);
645        incRefsCreated(env);
646    }
647
648    return object;
649}
650
651sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
652{
653    if (obj == NULL) return NULL;
654
655    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
656        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
657            env->GetLongField(obj, gBinderOffsets.mObject);
658        return jbh != NULL ? jbh->get(env, obj) : NULL;
659    }
660
661    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
662        return (IBinder*)
663            env->GetLongField(obj, gBinderProxyOffsets.mObject);
664    }
665
666    ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
667    return NULL;
668}
669
670jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
671{
672    return env->NewObject(
673            gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc);
674}
675
676void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy)
677{
678    // Call back into android.os.StrictMode#onBinderStrictModePolicyChange
679    // to sync our state back to it.  See the comments in StrictMode.java.
680    env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass,
681                              gStrictModeCallbackOffsets.mCallback,
682                              strict_policy);
683}
684
685void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
686        bool canThrowRemoteException, int parcelSize)
687{
688    switch (err) {
689        case UNKNOWN_ERROR:
690            jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
691            break;
692        case NO_MEMORY:
693            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
694            break;
695        case INVALID_OPERATION:
696            jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
697            break;
698        case BAD_VALUE:
699            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
700            break;
701        case BAD_INDEX:
702            jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
703            break;
704        case BAD_TYPE:
705            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
706            break;
707        case NAME_NOT_FOUND:
708            jniThrowException(env, "java/util/NoSuchElementException", NULL);
709            break;
710        case PERMISSION_DENIED:
711            jniThrowException(env, "java/lang/SecurityException", NULL);
712            break;
713        case NOT_ENOUGH_DATA:
714            jniThrowException(env, "android/os/ParcelFormatException", "Not enough data");
715            break;
716        case NO_INIT:
717            jniThrowException(env, "java/lang/RuntimeException", "Not initialized");
718            break;
719        case ALREADY_EXISTS:
720            jniThrowException(env, "java/lang/RuntimeException", "Item already exists");
721            break;
722        case DEAD_OBJECT:
723            // DeadObjectException is a checked exception, only throw from certain methods.
724            jniThrowException(env, canThrowRemoteException
725                    ? "android/os/DeadObjectException"
726                            : "java/lang/RuntimeException", NULL);
727            break;
728        case UNKNOWN_TRANSACTION:
729            jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code");
730            break;
731        case FAILED_TRANSACTION: {
732            ALOGE("!!! FAILED BINDER TRANSACTION !!!  (parcel size = %d)", parcelSize);
733            const char* exceptionToThrow;
734            char msg[128];
735            // TransactionTooLargeException is a checked exception, only throw from certain methods.
736            // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
737            //        but it is not the only one.  The Binder driver can return BR_FAILED_REPLY
738            //        for other reasons also, such as if the transaction is malformed or
739            //        refers to an FD that has been closed.  We should change the driver
740            //        to enable us to distinguish these cases in the future.
741            if (canThrowRemoteException && parcelSize > 200*1024) {
742                // bona fide large payload
743                exceptionToThrow = "android/os/TransactionTooLargeException";
744                snprintf(msg, sizeof(msg)-1, "data parcel size %d bytes", parcelSize);
745            } else {
746                // Heuristic: a payload smaller than this threshold "shouldn't" be too
747                // big, so it's probably some other, more subtle problem.  In practice
748                // it seems to always mean that the remote process died while the binder
749                // transaction was already in flight.
750                exceptionToThrow = (canThrowRemoteException)
751                        ? "android/os/DeadObjectException"
752                        : "java/lang/RuntimeException";
753                snprintf(msg, sizeof(msg)-1,
754                        "Transaction failed on small parcel; remote process probably died");
755            }
756            jniThrowException(env, exceptionToThrow, msg);
757        } break;
758        case FDS_NOT_ALLOWED:
759            jniThrowException(env, "java/lang/RuntimeException",
760                    "Not allowed to write file descriptors here");
761            break;
762        case UNEXPECTED_NULL:
763            jniThrowNullPointerException(env, NULL);
764            break;
765        case -EBADF:
766            jniThrowException(env, "java/lang/RuntimeException",
767                    "Bad file descriptor");
768            break;
769        case -ENFILE:
770            jniThrowException(env, "java/lang/RuntimeException",
771                    "File table overflow");
772            break;
773        case -EMFILE:
774            jniThrowException(env, "java/lang/RuntimeException",
775                    "Too many open files");
776            break;
777        case -EFBIG:
778            jniThrowException(env, "java/lang/RuntimeException",
779                    "File too large");
780            break;
781        case -ENOSPC:
782            jniThrowException(env, "java/lang/RuntimeException",
783                    "No space left on device");
784            break;
785        case -ESPIPE:
786            jniThrowException(env, "java/lang/RuntimeException",
787                    "Illegal seek");
788            break;
789        case -EROFS:
790            jniThrowException(env, "java/lang/RuntimeException",
791                    "Read-only file system");
792            break;
793        case -EMLINK:
794            jniThrowException(env, "java/lang/RuntimeException",
795                    "Too many links");
796            break;
797        default:
798            ALOGE("Unknown binder error code. 0x%" PRIx32, err);
799            String8 msg;
800            msg.appendFormat("Unknown binder error code. 0x%" PRIx32, err);
801            // RemoteException is a checked exception, only throw from certain methods.
802            jniThrowException(env, canThrowRemoteException
803                    ? "android/os/RemoteException" : "java/lang/RuntimeException", msg.string());
804            break;
805    }
806}
807
808}
809
810// ----------------------------------------------------------------------------
811
812static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz)
813{
814    return IPCThreadState::self()->getCallingPid();
815}
816
817static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz)
818{
819    return IPCThreadState::self()->getCallingUid();
820}
821
822static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz)
823{
824    return IPCThreadState::self()->clearCallingIdentity();
825}
826
827static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
828{
829    // XXX temporary sanity check to debug crashes.
830    int uid = (int)(token>>32);
831    if (uid > 0 && uid < 999) {
832        // In Android currently there are no uids in this range.
833        char buf[128];
834        sprintf(buf, "Restoring bad calling ident: 0x%" PRIx64, token);
835        jniThrowException(env, "java/lang/IllegalStateException", buf);
836        return;
837    }
838    IPCThreadState::self()->restoreCallingIdentity(token);
839}
840
841static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask)
842{
843    IPCThreadState::self()->setStrictModePolicy(policyMask);
844}
845
846static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz)
847{
848    return IPCThreadState::self()->getStrictModePolicy();
849}
850
851static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz)
852{
853    IPCThreadState::self()->flushCommands();
854}
855
856static void android_os_Binder_init(JNIEnv* env, jobject obj)
857{
858    JavaBBinderHolder* jbh = new JavaBBinderHolder();
859    if (jbh == NULL) {
860        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
861        return;
862    }
863    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
864    jbh->incStrong((void*)android_os_Binder_init);
865    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
866}
867
868static void android_os_Binder_destroyBinder(JNIEnv* env, jobject obj)
869{
870    JavaBBinderHolder* jbh = (JavaBBinderHolder*)
871        env->GetLongField(obj, gBinderOffsets.mObject);
872    if (jbh != NULL) {
873        env->SetLongField(obj, gBinderOffsets.mObject, 0);
874        ALOGV("Java Binder %p: removing ref on holder %p", obj, jbh);
875        jbh->decStrong((void*)android_os_Binder_init);
876    } else {
877        // Encountering an uninitialized binder is harmless.  All it means is that
878        // the Binder was only partially initialized when its finalizer ran and called
879        // destroyBinder().  The Binder could be partially initialized for several reasons.
880        // For example, a Binder subclass constructor might have thrown an exception before
881        // it could delegate to its superclass's constructor.  Consequently init() would
882        // not have been called and the holder pointer would remain NULL.
883        ALOGV("Java Binder %p: ignoring uninitialized binder", obj);
884    }
885}
886
887static void android_os_Binder_blockUntilThreadAvailable(JNIEnv* env, jobject clazz)
888{
889    return IPCThreadState::self()->blockUntilThreadAvailable();
890}
891
892// ----------------------------------------------------------------------------
893
894static const JNINativeMethod gBinderMethods[] = {
895     /* name, signature, funcPtr */
896    { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
897    { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
898    { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
899    { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
900    { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
901    { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
902    { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
903    { "init", "()V", (void*)android_os_Binder_init },
904    { "destroyBinder", "()V", (void*)android_os_Binder_destroyBinder },
905    { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
906};
907
908const char* const kBinderPathName = "android/os/Binder";
909
910static int int_register_android_os_Binder(JNIEnv* env)
911{
912    jclass clazz = FindClassOrDie(env, kBinderPathName);
913
914    gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
915    gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
916    gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
917
918    return RegisterMethodsOrDie(
919        env, kBinderPathName,
920        gBinderMethods, NELEM(gBinderMethods));
921}
922
923// ****************************************************************************
924// ****************************************************************************
925// ****************************************************************************
926
927namespace android {
928
929jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz)
930{
931    return gNumLocalRefs;
932}
933
934jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
935{
936    return gNumProxyRefs;
937}
938
939jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
940{
941    return gNumDeathRefs;
942}
943
944}
945
946// ****************************************************************************
947// ****************************************************************************
948// ****************************************************************************
949
950static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
951{
952    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
953    return javaObjectForIBinder(env, b);
954}
955
956static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz)
957{
958    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
959    android::IPCThreadState::self()->joinThreadPool();
960}
961
962static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env,
963        jobject clazz, jboolean disable)
964{
965    IPCThreadState::disableBackgroundScheduling(disable ? true : false);
966}
967
968static void android_os_BinderInternal_setMaxThreads(JNIEnv* env,
969        jobject clazz, jint maxThreads)
970{
971    ProcessState::self()->setThreadPoolMaxThreadCount(maxThreads);
972}
973
974static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz)
975{
976    ALOGV("Gc has executed, clearing binder ops");
977    android_atomic_and(0, &gNumRefsCreated);
978}
979
980// ----------------------------------------------------------------------------
981
982static const JNINativeMethod gBinderInternalMethods[] = {
983     /* name, signature, funcPtr */
984    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
985    { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
986    { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
987    { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
988    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
989};
990
991const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
992
993static int int_register_android_os_BinderInternal(JNIEnv* env)
994{
995    jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
996
997    gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
998    gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
999
1000    return RegisterMethodsOrDie(
1001        env, kBinderInternalPathName,
1002        gBinderInternalMethods, NELEM(gBinderInternalMethods));
1003}
1004
1005// ****************************************************************************
1006// ****************************************************************************
1007// ****************************************************************************
1008
1009static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj)
1010{
1011    IBinder* target = (IBinder*)
1012        env->GetLongField(obj, gBinderProxyOffsets.mObject);
1013    if (target == NULL) {
1014        return JNI_FALSE;
1015    }
1016    status_t err = target->pingBinder();
1017    return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
1018}
1019
1020static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj)
1021{
1022    IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);
1023    if (target != NULL) {
1024        const String16& desc = target->getInterfaceDescriptor();
1025        return env->NewString(reinterpret_cast<const jchar*>(desc.string()),
1026                              desc.size());
1027    }
1028    jniThrowException(env, "java/lang/RuntimeException",
1029            "No binder found for object");
1030    return NULL;
1031}
1032
1033static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj)
1034{
1035    IBinder* target = (IBinder*)
1036        env->GetLongField(obj, gBinderProxyOffsets.mObject);
1037    if (target == NULL) {
1038        return JNI_FALSE;
1039    }
1040    bool alive = target->isBinderAlive();
1041    return alive ? JNI_TRUE : JNI_FALSE;
1042}
1043
1044static int getprocname(pid_t pid, char *buf, size_t len) {
1045    char filename[32];
1046    FILE *f;
1047
1048    snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid);
1049    f = fopen(filename, "r");
1050    if (!f) {
1051        *buf = '\0';
1052        return 1;
1053    }
1054    if (!fgets(buf, len, f)) {
1055        *buf = '\0';
1056        fclose(f);
1057        return 2;
1058    }
1059    fclose(f);
1060    return 0;
1061}
1062
1063static bool push_eventlog_string(char** pos, const char* end, const char* str) {
1064    jint len = strlen(str);
1065    int space_needed = 1 + sizeof(len) + len;
1066    if (end - *pos < space_needed) {
1067        ALOGW("not enough space for string. remain=%" PRIdPTR "; needed=%d",
1068             end - *pos, space_needed);
1069        return false;
1070    }
1071    **pos = EVENT_TYPE_STRING;
1072    (*pos)++;
1073    memcpy(*pos, &len, sizeof(len));
1074    *pos += sizeof(len);
1075    memcpy(*pos, str, len);
1076    *pos += len;
1077    return true;
1078}
1079
1080static bool push_eventlog_int(char** pos, const char* end, jint val) {
1081    int space_needed = 1 + sizeof(val);
1082    if (end - *pos < space_needed) {
1083        ALOGW("not enough space for int.  remain=%" PRIdPTR "; needed=%d",
1084             end - *pos, space_needed);
1085        return false;
1086    }
1087    **pos = EVENT_TYPE_INT;
1088    (*pos)++;
1089    memcpy(*pos, &val, sizeof(val));
1090    *pos += sizeof(val);
1091    return true;
1092}
1093
1094// From frameworks/base/core/java/android/content/EventLogTags.logtags:
1095
1096static const bool kEnableBinderSample = false;
1097
1098#define LOGTAG_BINDER_OPERATION 52004
1099
1100static void conditionally_log_binder_call(int64_t start_millis,
1101                                          IBinder* target, jint code) {
1102    int duration_ms = static_cast<int>(uptimeMillis() - start_millis);
1103
1104    int sample_percent;
1105    if (duration_ms >= 500) {
1106        sample_percent = 100;
1107    } else {
1108        sample_percent = 100 * duration_ms / 500;
1109        if (sample_percent == 0) {
1110            return;
1111        }
1112        if (sample_percent < (random() % 100 + 1)) {
1113            return;
1114        }
1115    }
1116
1117    char process_name[40];
1118    getprocname(getpid(), process_name, sizeof(process_name));
1119    String8 desc(target->getInterfaceDescriptor());
1120
1121    char buf[LOGGER_ENTRY_MAX_PAYLOAD];
1122    buf[0] = EVENT_TYPE_LIST;
1123    buf[1] = 5;
1124    char* pos = &buf[2];
1125    char* end = &buf[LOGGER_ENTRY_MAX_PAYLOAD - 1];  // leave room for final \n
1126    if (!push_eventlog_string(&pos, end, desc.string())) return;
1127    if (!push_eventlog_int(&pos, end, code)) return;
1128    if (!push_eventlog_int(&pos, end, duration_ms)) return;
1129    if (!push_eventlog_string(&pos, end, process_name)) return;
1130    if (!push_eventlog_int(&pos, end, sample_percent)) return;
1131    *(pos++) = '\n';   // conventional with EVENT_TYPE_LIST apparently.
1132    android_bWriteLog(LOGTAG_BINDER_OPERATION, buf, pos - buf);
1133}
1134
1135// We only measure binder call durations to potentially log them if
1136// we're on the main thread.
1137static bool should_time_binder_calls() {
1138  return (getpid() == gettid());
1139}
1140
1141static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
1142        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
1143{
1144    if (dataObj == NULL) {
1145        jniThrowNullPointerException(env, NULL);
1146        return JNI_FALSE;
1147    }
1148
1149    Parcel* data = parcelForJavaObject(env, dataObj);
1150    if (data == NULL) {
1151        return JNI_FALSE;
1152    }
1153    Parcel* reply = parcelForJavaObject(env, replyObj);
1154    if (reply == NULL && replyObj != NULL) {
1155        return JNI_FALSE;
1156    }
1157
1158    IBinder* target = (IBinder*)
1159        env->GetLongField(obj, gBinderProxyOffsets.mObject);
1160    if (target == NULL) {
1161        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
1162        return JNI_FALSE;
1163    }
1164
1165    ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
1166            target, obj, code);
1167
1168
1169    bool time_binder_calls;
1170    int64_t start_millis;
1171    if (kEnableBinderSample) {
1172        // Only log the binder call duration for things on the Java-level main thread.
1173        // But if we don't
1174        time_binder_calls = should_time_binder_calls();
1175
1176        if (time_binder_calls) {
1177            start_millis = uptimeMillis();
1178        }
1179    }
1180
1181    //printf("Transact from Java code to %p sending: ", target); data->print();
1182    status_t err = target->transact(code, *data, reply, flags);
1183    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
1184
1185    if (kEnableBinderSample) {
1186        if (time_binder_calls) {
1187            conditionally_log_binder_call(start_millis, target, code);
1188        }
1189    }
1190
1191    if (err == NO_ERROR) {
1192        return JNI_TRUE;
1193    } else if (err == UNKNOWN_TRANSACTION) {
1194        return JNI_FALSE;
1195    }
1196
1197    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
1198    return JNI_FALSE;
1199}
1200
1201static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
1202        jobject recipient, jint flags) // throws RemoteException
1203{
1204    if (recipient == NULL) {
1205        jniThrowNullPointerException(env, NULL);
1206        return;
1207    }
1208
1209    IBinder* target = (IBinder*)
1210        env->GetLongField(obj, gBinderProxyOffsets.mObject);
1211    if (target == NULL) {
1212        ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
1213        assert(false);
1214    }
1215
1216    LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
1217
1218    if (!target->localBinder()) {
1219        DeathRecipientList* list = (DeathRecipientList*)
1220                env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
1221        sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);
1222        status_t err = target->linkToDeath(jdr, NULL, flags);
1223        if (err != NO_ERROR) {
1224            // Failure adding the death recipient, so clear its reference
1225            // now.
1226            jdr->clearReference();
1227            signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
1228        }
1229    }
1230}
1231
1232static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
1233                                                 jobject recipient, jint flags)
1234{
1235    jboolean res = JNI_FALSE;
1236    if (recipient == NULL) {
1237        jniThrowNullPointerException(env, NULL);
1238        return res;
1239    }
1240
1241    IBinder* target = (IBinder*)
1242        env->GetLongField(obj, gBinderProxyOffsets.mObject);
1243    if (target == NULL) {
1244        ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
1245        return JNI_FALSE;
1246    }
1247
1248    LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
1249
1250    if (!target->localBinder()) {
1251        status_t err = NAME_NOT_FOUND;
1252
1253        // If we find the matching recipient, proceed to unlink using that
1254        DeathRecipientList* list = (DeathRecipientList*)
1255                env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
1256        sp<JavaDeathRecipient> origJDR = list->find(recipient);
1257        LOGDEATH("   unlink found list %p and JDR %p", list, origJDR.get());
1258        if (origJDR != NULL) {
1259            wp<IBinder::DeathRecipient> dr;
1260            err = target->unlinkToDeath(origJDR, NULL, flags, &dr);
1261            if (err == NO_ERROR && dr != NULL) {
1262                sp<IBinder::DeathRecipient> sdr = dr.promote();
1263                JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get());
1264                if (jdr != NULL) {
1265                    jdr->clearReference();
1266                }
1267            }
1268        }
1269
1270        if (err == NO_ERROR || err == DEAD_OBJECT) {
1271            res = JNI_TRUE;
1272        } else {
1273            jniThrowException(env, "java/util/NoSuchElementException",
1274                              "Death link does not exist");
1275        }
1276    }
1277
1278    return res;
1279}
1280
1281static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj)
1282{
1283    // Don't race with construction/initialization
1284    AutoMutex _l(mProxyLock);
1285
1286    IBinder* b = (IBinder*)
1287            env->GetLongField(obj, gBinderProxyOffsets.mObject);
1288    DeathRecipientList* drl = (DeathRecipientList*)
1289            env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
1290
1291    LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl);
1292    if (b != nullptr) {
1293        env->SetLongField(obj, gBinderProxyOffsets.mObject, 0);
1294        env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0);
1295        drl->decStrong((void*)javaObjectForIBinder);
1296        b->decStrong((void*)javaObjectForIBinder);
1297    }
1298
1299    IPCThreadState::self()->flushCommands();
1300}
1301
1302// ----------------------------------------------------------------------------
1303
1304static const JNINativeMethod gBinderProxyMethods[] = {
1305     /* name, signature, funcPtr */
1306    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
1307    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
1308    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
1309    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
1310    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
1311    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
1312    {"destroy",             "()V", (void*)android_os_BinderProxy_destroy},
1313};
1314
1315const char* const kBinderProxyPathName = "android/os/BinderProxy";
1316
1317static int int_register_android_os_BinderProxy(JNIEnv* env)
1318{
1319    jclass clazz = FindClassOrDie(env, "java/lang/Error");
1320    gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
1321
1322    clazz = FindClassOrDie(env, kBinderProxyPathName);
1323    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
1324    gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
1325    gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
1326            "(Landroid/os/IBinder$DeathRecipient;)V");
1327
1328    gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
1329    gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf",
1330                                                "Ljava/lang/ref/WeakReference;");
1331    gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");
1332
1333    clazz = FindClassOrDie(env, "java/lang/Class");
1334    gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
1335
1336    return RegisterMethodsOrDie(
1337        env, kBinderProxyPathName,
1338        gBinderProxyMethods, NELEM(gBinderProxyMethods));
1339}
1340
1341// ****************************************************************************
1342// ****************************************************************************
1343// ****************************************************************************
1344
1345int register_android_os_Binder(JNIEnv* env)
1346{
1347    if (int_register_android_os_Binder(env) < 0)
1348        return -1;
1349    if (int_register_android_os_BinderInternal(env) < 0)
1350        return -1;
1351    if (int_register_android_os_BinderProxy(env) < 0)
1352        return -1;
1353
1354    jclass clazz = FindClassOrDie(env, "android/util/Log");
1355    gLogOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
1356    gLogOffsets.mLogE = GetStaticMethodIDOrDie(env, clazz, "e",
1357            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
1358
1359    clazz = FindClassOrDie(env, "android/os/ParcelFileDescriptor");
1360    gParcelFileDescriptorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
1361    gParcelFileDescriptorOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>",
1362                                                                 "(Ljava/io/FileDescriptor;)V");
1363
1364    clazz = FindClassOrDie(env, "android/os/StrictMode");
1365    gStrictModeCallbackOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
1366    gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz,
1367            "onBinderStrictModePolicyChange", "(I)V");
1368
1369    clazz = FindClassOrDie(env, "java/lang/Thread");
1370    gThreadDispatchOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
1371    gThreadDispatchOffsets.mDispatchUncaughtException = GetMethodIDOrDie(env, clazz,
1372            "dispatchUncaughtException", "(Ljava/lang/Throwable;)V");
1373    gThreadDispatchOffsets.mCurrentThread = GetStaticMethodIDOrDie(env, clazz, "currentThread",
1374            "()Ljava/lang/Thread;");
1375
1376    return 0;
1377}
1378