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