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