blob: 1718e741d8d07efc4cc3aa7a6ef222bb86141a27 [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
Christopher Tateac5e3502011-08-25 15:48:09 -070042#include <ScopedUtfChars.h>
43#include <ScopedLocalRef.h>
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045#include <android_runtime/AndroidRuntime.h>
46
47//#undef LOGV
48//#define LOGV(...) fprintf(stderr, __VA_ARGS__)
49
Christopher Tate79dd31f2011-03-04 17:45:00 -080050#define DEBUG_DEATH 0
51#if DEBUG_DEATH
52#define LOGDEATH LOGD
53#else
54#define LOGDEATH LOGV
55#endif
56
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057using namespace android;
58
59// ----------------------------------------------------------------------------
60
61static 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
74static struct binderinternal_offsets_t
75{
76 // Class state.
77 jclass mClass;
78 jmethodID mForceGc;
79
80} gBinderInternalOffsets;
81
82// ----------------------------------------------------------------------------
83
84static struct debug_offsets_t
85{
86 // Class state.
87 jclass mClass;
88
89} gDebugOffsets;
90
91// ----------------------------------------------------------------------------
92
93static struct weakreference_offsets_t
94{
95 // Class state.
96 jclass mClass;
97 jmethodID mGet;
98
99} gWeakReferenceOffsets;
100
101static struct error_offsets_t
102{
103 jclass mClass;
104} gErrorOffsets;
105
106// ----------------------------------------------------------------------------
107
108static 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;
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800118 jfieldID mOrgue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119
120} gBinderProxyOffsets;
121
Christopher Tate0d4a7922011-08-30 12:09:43 -0700122static struct class_offsets_t
123{
124 jmethodID mGetName;
125} gClassOffsets;
126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127// ----------------------------------------------------------------------------
128
129static struct parcel_offsets_t
130{
131 jfieldID mObject;
132 jfieldID mOwnObject;
133} gParcelOffsets;
134
135static struct log_offsets_t
136{
137 // Class state.
138 jclass mClass;
139 jmethodID mLogE;
140} gLogOffsets;
141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142static struct parcel_file_descriptor_offsets_t
143{
144 jclass mClass;
145 jmethodID mConstructor;
146} gParcelFileDescriptorOffsets;
147
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700148static struct strict_mode_callback_offsets_t
149{
150 jclass mClass;
151 jmethodID mCallback;
152} gStrictModeCallbackOffsets;
153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154// ****************************************************************************
155// ****************************************************************************
156// ****************************************************************************
157
158static volatile int32_t gNumRefsCreated = 0;
159static volatile int32_t gNumProxyRefs = 0;
160static volatile int32_t gNumLocalRefs = 0;
161static volatile int32_t gNumDeathRefs = 0;
162
163static 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
175static JavaVM* jnienv_to_javavm(JNIEnv* env)
176{
177 JavaVM* vm;
178 return env->GetJavaVM(&vm) >= 0 ? vm : NULL;
179}
180
181static 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
187static 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
228bail:
229 /* discard local refs created for us by VM */
230 env->DeleteLocalRef(tagstr);
231 env->DeleteLocalRef(msgstr);
232}
233
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700234static 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243class JavaBBinderHolder;
244
245class JavaBBinder : public BBinder
246{
247public:
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
256 bool checkSubclass(const void* subclassID) const
257 {
258 return subclassID == &gBinderOffsets;
259 }
260
261 jobject object() const
262 {
263 return mObject;
264 }
265
266protected:
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
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
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700282 IPCThreadState* thread_state = IPCThreadState::self();
283 const int strict_policy_before = thread_state->getStrictModePolicy();
Brad Fitzpatrick02343762010-08-30 16:01:16 -0700284 thread_state->setLastTransactionBinderFlags(flags);
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 //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();
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700292
Bjorn Bringert9013ccd2011-04-26 19:10:58 +0100293 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
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700303 // 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
Bjorn Bringert9013ccd2011-04-26 19:10:58 +0100315 jthrowable excep2 = env->ExceptionOccurred();
316 if (excep2) {
317 report_exception(env, excep2,
318 "*** Uncaught exception in onBinderStrictModePolicyChange");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 /* clean up JNI local ref -- we don't return to Java code */
Bjorn Bringert9013ccd2011-04-26 19:10:58 +0100320 env->DeleteLocalRef(excep2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 }
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
329 virtual status_t dump(int fd, const Vector<String16>& args)
330 {
331 return 0;
332 }
333
334private:
335 JavaVM* const mVM;
336 jobject const mObject;
337};
338
339// ----------------------------------------------------------------------------
340
341class JavaBBinderHolder : public RefBase
342{
343public:
Christopher Tate0b414482011-02-17 13:00:38 -0800344 sp<JavaBBinder> get(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 {
346 AutoMutex _l(mLock);
347 sp<JavaBBinder> b = mBinder.promote();
348 if (b == NULL) {
Christopher Tate0b414482011-02-17 13:00:38 -0800349 b = new JavaBBinder(env, obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 mBinder = b;
351 LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n",
Christopher Tate0b414482011-02-17 13:00:38 -0800352 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 }
354
355 return b;
356 }
357
358 sp<JavaBBinder> getExisting()
359 {
360 AutoMutex _l(mLock);
361 return mBinder.promote();
362 }
363
364private:
365 Mutex mLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 wp<JavaBBinder> mBinder;
367};
368
369// ----------------------------------------------------------------------------
370
Christopher Tate0b414482011-02-17 13:00:38 -0800371// 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
375class JavaDeathRecipient;
376
377class DeathRecipientList : public RefBase {
378 List< sp<JavaDeathRecipient> > mList;
379 Mutex mLock;
380
381public:
Christopher Tate79dd31f2011-03-04 17:45:00 -0800382 DeathRecipientList();
Christopher Tate0b414482011-02-17 13:00:38 -0800383 ~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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392class JavaDeathRecipient : public IBinder::DeathRecipient
393{
394public:
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800395 JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
Christopher Tate86284c62011-08-17 15:19:29 -0700396 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
397 mObjectWeak(NULL), mList(list)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 {
Christopher Tate0b414482011-02-17 13:00:38 -0800399 // These objects manage their own lifetimes so are responsible for final bookkeeping.
400 // The list holds a strong reference to this object.
Christopher Tate79dd31f2011-03-04 17:45:00 -0800401 LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800402 list->add(this);
Christopher Tate0b414482011-02-17 13:00:38 -0800403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 android_atomic_inc(&gNumDeathRefs);
405 incRefsCreated(env);
406 }
407
408 void binderDied(const wp<IBinder>& who)
409 {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800410 LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
Christopher Tate86284c62011-08-17 15:19:29 -0700411 if (mObject != NULL) {
412 JNIEnv* env = javavm_to_jnienv(mVM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413
Christopher Tate86284c62011-08-17 15:19:29 -0700414 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 }
429
430 void clearReference()
431 {
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800432 sp<DeathRecipientList> list = mList.promote();
433 if (list != NULL) {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800434 LOGDEATH("Removing JDR %p from DRL %p", this, list.get());
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800435 list->remove(this);
Christopher Tate79dd31f2011-03-04 17:45:00 -0800436 } else {
437 LOGDEATH("clearReference() on JDR %p but DRL wp purged", this);
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800438 }
Christopher Tate0b414482011-02-17 13:00:38 -0800439 }
440
441 bool matches(jobject obj) {
Christopher Tate86284c62011-08-17 15:19:29 -0700442 bool result;
Christopher Tate0b414482011-02-17 13:00:38 -0800443 JNIEnv* env = javavm_to_jnienv(mVM);
Christopher Tate86284c62011-08-17 15:19:29 -0700444
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 }
454
Christopher Tateac5e3502011-08-25 15:48:09 -0700455 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);
Christopher Tate0d4a7922011-08-30 12:09:43 -0700460 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 }
Christopher Tateac5e3502011-08-25 15:48:09 -0700472 }
473 }
474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475protected:
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);
Christopher Tate86284c62011-08-17 15:19:29 -0700481 if (mObject != NULL) {
482 env->DeleteGlobalRef(mObject);
483 } else {
484 env->DeleteWeakGlobalRef(mObjectWeak);
485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 }
487
488private:
Christopher Tate86284c62011-08-17 15:19:29 -0700489 JavaVM* const mVM;
490 jobject mObject;
491 jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied()
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800492 wp<DeathRecipientList> mList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493};
494
495// ----------------------------------------------------------------------------
496
Christopher Tate79dd31f2011-03-04 17:45:00 -0800497DeathRecipientList::DeathRecipientList() {
498 LOGDEATH("New DRL @ %p", this);
499}
500
Christopher Tate0b414482011-02-17 13:00:38 -0800501DeathRecipientList::~DeathRecipientList() {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800502 LOGDEATH("Destroy DRL @ %p", this);
Christopher Tate0b414482011-02-17 13:00:38 -0800503 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) {
Christopher Tateac5e3502011-08-25 15:48:09 -0700509 List< sp<JavaDeathRecipient> >::iterator iter;
510 for (iter = mList.begin(); iter != mList.end(); iter++) {
511 (*iter)->warnIfStillLive();
512 }
Christopher Tate0b414482011-02-17 13:00:38 -0800513 }
514}
515
516void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) {
517 AutoMutex _l(mLock);
518
Christopher Tate79dd31f2011-03-04 17:45:00 -0800519 LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get());
Christopher Tate0b414482011-02-17 13:00:38 -0800520 mList.push_back(recipient);
521}
522
523void 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) {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800529 LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get());
Christopher Tate0b414482011-02-17 13:00:38 -0800530 mList.erase(iter);
531 return;
532 }
533 }
534}
535
536sp<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
Christopher Tate0b414482011-02-17 13:00:38 -0800548// ----------------------------------------------------------------------------
549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550namespace android {
551
552static 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
559static Mutex mProxyLock;
560
561jobject 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();
Christopher Tate86284c62011-08-17 15:19:29 -0700568 LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 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 }
Christopher Tate86284c62011-08-17 15:19:29 -0700584 LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 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) {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800592 LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 // 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
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800604 // 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 // Note that a new object reference has been created.
610 android_atomic_inc(&gNumProxyRefs);
611 incRefsCreated(env);
612 }
613
614 return object;
615}
616
617sp<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);
Christopher Tate0b414482011-02-17 13:00:38 -0800624 return jbh != NULL ? jbh->get(env, obj) : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 }
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
636Parcel* 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
649{
650 return env->NewObject(
651 gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc);
652}
653
654void 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;
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400700 case FDS_NOT_ALLOWED:
701 jniThrowException(env, "java/lang/RuntimeException",
702 "Not allowed to write file descriptors here");
703 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 default:
705 LOGE("Unknown binder error code. 0x%x", err);
706 }
707}
708
709}
710
711// ----------------------------------------------------------------------------
712
713static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz)
714{
715 return IPCThreadState::self()->getCallingPid();
716}
717
718static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz)
719{
720 return IPCThreadState::self()->getCallingUid();
721}
722
723static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz)
724{
725 return IPCThreadState::self()->clearCallingIdentity();
726}
727
728static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
729{
Dianne Hackborncf3004a2011-03-14 14:24:04 -0700730 // 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 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 IPCThreadState::self()->restoreCallingIdentity(token);
740}
741
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700742static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask)
743{
744 IPCThreadState::self()->setStrictModePolicy(policyMask);
745}
746
747static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz)
748{
749 return IPCThreadState::self()->getStrictModePolicy();
750}
751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz)
753{
754 IPCThreadState::self()->flushCommands();
755}
756
Christopher Tate0b414482011-02-17 13:00:38 -0800757static void android_os_Binder_init(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758{
Christopher Tate0b414482011-02-17 13:00:38 -0800759 JavaBBinderHolder* jbh = new JavaBBinderHolder();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 if (jbh == NULL) {
761 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
762 return;
763 }
Christopher Tate0b414482011-02-17 13:00:38 -0800764 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);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767}
768
Christopher Tate0b414482011-02-17 13:00:38 -0800769static void android_os_Binder_destroy(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770{
771 JavaBBinderHolder* jbh = (JavaBBinderHolder*)
Christopher Tate0b414482011-02-17 13:00:38 -0800772 env->GetIntField(obj, gBinderOffsets.mObject);
Jeff Brown582763a2010-03-24 18:56:57 -0700773 if (jbh != NULL) {
Christopher Tate0b414482011-02-17 13:00:38 -0800774 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);
Jeff Brown582763a2010-03-24 18:56:57 -0700777 } 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.
Christopher Tate0b414482011-02-17 13:00:38 -0800784 LOGV("Java Binder %p: ignoring uninitialized binder", obj);
Jeff Brown582763a2010-03-24 18:56:57 -0700785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786}
787
788// ----------------------------------------------------------------------------
789
790static 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 },
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700796 { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
797 { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 { "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
803const char* const kBinderPathName = "android/os/Binder";
804
805static 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
830namespace android {
831
832jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz)
833{
834 return gNumLocalRefs;
835}
836
837jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
838{
839 return gNumProxyRefs;
840}
841
842jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
843{
844 return gNumDeathRefs;
845}
846
847}
848
849// ****************************************************************************
850// ****************************************************************************
851// ****************************************************************************
852
853static 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
859static 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
Dianne Hackborn887f3552009-12-07 17:59:37 -0800865static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env,
866 jobject clazz, jboolean disable)
867{
868 IPCThreadState::disableBackgroundScheduling(disable ? true : false);
869}
870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871static 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
879static 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 },
Dianne Hackborn887f3552009-12-07 17:59:37 -0800883 { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
885};
886
887const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
888
889static 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
910static 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
921static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj)
922{
923 IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject);
924 if (target != NULL) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -0700925 const String16& desc = target->getInterfaceDescriptor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 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
933static 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
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -0700944static 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
956static 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
973static 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
990static 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
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001025// 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.
1029static bool should_time_binder_calls() {
Brad Fitzpatrick5348c012010-03-25 12:43:56 -07001030#ifdef HAVE_GETTID
1031 return (getpid() == androidGetTid());
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001032#else
1033#warning no gettid(), so not logging Binder calls...
1034 return false;
1035#endif
1036}
1037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
1039 jint code, jobject dataObj,
1040 jobject replyObj, jint flags)
1041{
1042 if (dataObj == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001043 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 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);
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001065
1066 // Only log the binder call duration for things on the Java-level main thread.
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001067 // But if we don't
1068 const bool time_binder_calls = should_time_binder_calls();
1069
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001070 int64_t start_millis;
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001071 if (time_binder_calls) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001072 start_millis = uptimeMillis();
1073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 //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();
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001077 if (time_binder_calls) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001078 conditionally_log_binder_call(start_millis, target, code);
1079 }
1080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 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
1091static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
1092 jobject recipient, jint flags)
1093{
1094 if (recipient == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001095 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 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
Christopher Tate79dd31f2011-03-04 17:45:00 -08001106 LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107
1108 if (!target->localBinder()) {
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001109 DeathRecipientList* list = (DeathRecipientList*)
1110 env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
1111 sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);
Christopher Tate0b414482011-02-17 13:00:38 -08001112 status_t err = target->linkToDeath(jdr, NULL, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 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
1122static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
1123 jobject recipient, jint flags)
1124{
1125 jboolean res = JNI_FALSE;
1126 if (recipient == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001127 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 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
Christopher Tate79dd31f2011-03-04 17:45:00 -08001138 LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139
1140 if (!target->localBinder()) {
Christopher Tate0b414482011-02-17 13:00:38 -08001141 status_t err = NAME_NOT_FOUND;
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001142
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);
Christopher Tate79dd31f2011-03-04 17:45:00 -08001147 LOGDEATH(" unlink found list %p and JDR %p", list, origJDR.get());
Christopher Tate0b414482011-02-17 13:00:38 -08001148 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 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
1171static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj)
1172{
1173 IBinder* b = (IBinder*)
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001174 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1175 DeathRecipientList* drl = (DeathRecipientList*)
1176 env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
Christopher Tate0b414482011-02-17 13:00:38 -08001177
Christopher Tate79dd31f2011-03-04 17:45:00 -08001178 LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl);
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001179 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();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185}
1186
1187// ----------------------------------------------------------------------------
1188
1189static 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
1200const char* const kBinderProxyPathName = "android/os/BinderProxy";
1201
1202static 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);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 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);
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001234 gBinderProxyOffsets.mOrgue
1235 = env->GetFieldID(clazz, "mOrgue", "I");
1236 assert(gBinderProxyOffsets.mOrgue);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237
Christopher Tate0d4a7922011-08-30 12:09:43 -07001238 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 return AndroidRuntime::registerNativeMethods(
1244 env, kBinderProxyPathName,
1245 gBinderProxyMethods, NELEM(gBinderProxyMethods));
1246}
1247
1248// ****************************************************************************
1249// ****************************************************************************
1250// ****************************************************************************
1251
1252static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz)
1253{
1254 Parcel* parcel = parcelForJavaObject(env, clazz);
1255 return parcel ? parcel->dataSize() : 0;
1256}
1257
1258static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz)
1259{
1260 Parcel* parcel = parcelForJavaObject(env, clazz);
1261 return parcel ? parcel->dataAvail() : 0;
1262}
1263
1264static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz)
1265{
1266 Parcel* parcel = parcelForJavaObject(env, clazz);
1267 return parcel ? parcel->dataPosition() : 0;
1268}
1269
1270static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz)
1271{
1272 Parcel* parcel = parcelForJavaObject(env, clazz);
1273 return parcel ? parcel->dataCapacity() : 0;
1274}
1275
1276static 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) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001282 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 }
1284 }
1285}
1286
1287static 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
1295static 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) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001301 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 }
1303 }
1304}
1305
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001306static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001307{
1308 Parcel* parcel = parcelForJavaObject(env, clazz);
1309 jboolean ret = JNI_TRUE;
1310 if (parcel != NULL) {
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001311 ret = (jboolean)parcel->pushAllowFds(allowFds);
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001312 }
1313 return ret;
1314}
1315
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001316static 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324static 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 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332
1333 const status_t err = parcel->writeInt32(length);
1334 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001335 signalExceptionForError(env, clazz, err);
1336 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 }
1338
Elliott Hughesa28b83e2011-02-28 14:26:13 -08001339 void* dest = parcel->writeInplace(length);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 if (dest == NULL) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001341 signalExceptionForError(env, clazz, NO_MEMORY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 return;
1343 }
1344
1345 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
1346 if (ar) {
Elliott Hughesa28b83e2011-02-28 14:26:13 -08001347 memcpy(dest, ar + offset, length);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
1349 }
1350}
1351
1352
1353static 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) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001359 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 }
1361 }
1362}
1363
1364static 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) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001370 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 }
1372 }
1373}
1374
1375static 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) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001381 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 }
1383 }
1384}
1385
1386static 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) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001392 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394 }
1395}
1396
1397static 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) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001412 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 }
1414 }
1415}
1416
1417static 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) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001423 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 }
1425 }
1426}
1427
1428static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1429{
1430 Parcel* parcel = parcelForJavaObject(env, clazz);
1431 if (parcel != NULL) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001432 const status_t err =
1433 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001435 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 }
1437 }
1438}
1439
1440static 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
1466static 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
1475static 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
1484static 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
1493static 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
1502static 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
1516static 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
1525static 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;
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001533 return jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 }
1535 return NULL;
1536}
1537
1538static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz,
1539 jstring name, jint mode)
1540{
1541 if (name == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001542 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 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) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001577 jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
1578 return NULL;
1579 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001580 jobject object = jniCreateFileDescriptor(env, fd);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001581 if (object == NULL) {
1582 close(fd);
1583 }
1584 return object;
1585}
1586
1587static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jobject clazz, jobject orig)
1588{
1589 if (orig == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001590 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001591 return NULL;
1592 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001593 int origfd = jniGetFDFromFileDescriptor(env, orig);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001594 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) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001601 jniThrowIOException(env, errno);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 return NULL;
1603 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001604 jobject object = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 if (object == NULL) {
1606 close(fd);
1607 }
1608 return object;
1609}
1610
1611static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1612{
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001613 if (object == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001614 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001615 return;
1616 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001617 int fd = jniGetFDFromFileDescriptor(env, object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if (fd >= 0) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001619 jniSetFileDescriptorOfFD(env, object, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 //LOGI("Closing ParcelFileDescriptor %d\n", fd);
1621 close(fd);
1622 }
1623}
1624
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001625static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1626{
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001627 if (object == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001628 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001629 return;
1630 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001631 int fd = jniGetFDFromFileDescriptor(env, object);
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001632 if (fd >= 0) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001633 jniSetFileDescriptorOfFD(env, object, -1);
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001634 }
1635}
1636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637static 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
1649static 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
1669static 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
1683static 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
1712static 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
1732static 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
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001743 status_t err = thisParcel->appendFrom(otherParcel, offset, length);
1744 if (err != NO_ERROR) {
1745 signalExceptionForError(env, clazz, err);
1746 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747}
1748
1749static 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
1761static 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
1775static 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) {
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001783 IPCThreadState* threadState = IPCThreadState::self();
1784 const int32_t oldPolicy = threadState->getStrictModePolicy();
1785 const bool isValid = parcel->enforceInterface(
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001786 String16(str, env->GetStringLength(name)),
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001787 threadState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 env->ReleaseStringCritical(name, str);
1789 if (isValid) {
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001790 const int32_t newPolicy = threadState->getStrictModePolicy();
1791 if (oldPolicy != newPolicy) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001792 // 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...)
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001799 set_dalvik_blockguard_policy(env, newPolicy);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 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
1813static 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},
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001821 {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
1822 {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 {"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},
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001840 {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001842 {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 {"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
1854const char* const kParcelPathName = "android/os/Parcel";
1855
1856static 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 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
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001881 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 return AndroidRuntime::registerNativeMethods(
1890 env, kParcelPathName,
1891 gParcelMethods, NELEM(gParcelMethods));
1892}
1893
1894int 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}