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