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