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