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