blob: bd62268dd770d87098ced01802e6ef9154a60e92 [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>
Jeff Brown0bde66a2011-11-07 12:50:08 -080041#include <utils/String8.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042
Christopher Tateac5e3502011-08-25 15:48:09 -070043#include <ScopedUtfChars.h>
44#include <ScopedLocalRef.h>
45
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046#include <android_runtime/AndroidRuntime.h>
47
Steve Block71f2cf12011-10-20 11:56:00 +010048//#undef ALOGV
49//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
Christopher Tate79dd31f2011-03-04 17:45:00 -080051#define DEBUG_DEATH 0
52#if DEBUG_DEATH
53#define LOGDEATH LOGD
54#else
Steve Block71f2cf12011-10-20 11:56:00 +010055#define LOGDEATH ALOGV
Christopher Tate79dd31f2011-03-04 17:45:00 -080056#endif
57
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058using namespace android;
59
60// ----------------------------------------------------------------------------
61
62static struct bindernative_offsets_t
63{
64 // Class state.
65 jclass mClass;
66 jmethodID mExecTransact;
67
68 // Object state.
69 jfieldID mObject;
70
71} gBinderOffsets;
72
73// ----------------------------------------------------------------------------
74
75static struct binderinternal_offsets_t
76{
77 // Class state.
78 jclass mClass;
79 jmethodID mForceGc;
80
81} gBinderInternalOffsets;
82
83// ----------------------------------------------------------------------------
84
85static struct debug_offsets_t
86{
87 // Class state.
88 jclass mClass;
89
90} gDebugOffsets;
91
92// ----------------------------------------------------------------------------
93
94static struct weakreference_offsets_t
95{
96 // Class state.
97 jclass mClass;
98 jmethodID mGet;
99
100} gWeakReferenceOffsets;
101
102static struct error_offsets_t
103{
104 jclass mClass;
105} gErrorOffsets;
106
107// ----------------------------------------------------------------------------
108
109static struct binderproxy_offsets_t
110{
111 // Class state.
112 jclass mClass;
113 jmethodID mConstructor;
114 jmethodID mSendDeathNotice;
115
116 // Object state.
117 jfieldID mObject;
118 jfieldID mSelf;
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800119 jfieldID mOrgue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120
121} gBinderProxyOffsets;
122
Christopher Tate0d4a7922011-08-30 12:09:43 -0700123static struct class_offsets_t
124{
125 jmethodID mGetName;
126} gClassOffsets;
127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128// ----------------------------------------------------------------------------
129
130static struct parcel_offsets_t
131{
132 jfieldID mObject;
133 jfieldID mOwnObject;
134} gParcelOffsets;
135
136static struct log_offsets_t
137{
138 // Class state.
139 jclass mClass;
140 jmethodID mLogE;
141} gLogOffsets;
142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143static struct parcel_file_descriptor_offsets_t
144{
145 jclass mClass;
146 jmethodID mConstructor;
147} gParcelFileDescriptorOffsets;
148
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700149static struct strict_mode_callback_offsets_t
150{
151 jclass mClass;
152 jmethodID mCallback;
153} gStrictModeCallbackOffsets;
154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155// ****************************************************************************
156// ****************************************************************************
157// ****************************************************************************
158
159static volatile int32_t gNumRefsCreated = 0;
160static volatile int32_t gNumProxyRefs = 0;
161static volatile int32_t gNumLocalRefs = 0;
162static volatile int32_t gNumDeathRefs = 0;
163
164static void incRefsCreated(JNIEnv* env)
165{
166 int old = android_atomic_inc(&gNumRefsCreated);
167 if (old == 200) {
168 android_atomic_and(0, &gNumRefsCreated);
169 env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
170 gBinderInternalOffsets.mForceGc);
171 } else {
Steve Block71f2cf12011-10-20 11:56:00 +0100172 ALOGV("Now have %d binder ops", old);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 }
174}
175
176static JavaVM* jnienv_to_javavm(JNIEnv* env)
177{
178 JavaVM* vm;
179 return env->GetJavaVM(&vm) >= 0 ? vm : NULL;
180}
181
182static JNIEnv* javavm_to_jnienv(JavaVM* vm)
183{
184 JNIEnv* env;
185 return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL;
186}
187
188static void report_exception(JNIEnv* env, jthrowable excep, const char* msg)
189{
190 env->ExceptionClear();
191
192 jstring tagstr = env->NewStringUTF(LOG_TAG);
193 jstring msgstr = env->NewStringUTF(msg);
194
195 if ((tagstr == NULL) || (msgstr == NULL)) {
196 env->ExceptionClear(); /* assume exception (OOM?) was thrown */
197 LOGE("Unable to call Log.e()\n");
198 LOGE("%s", msg);
199 goto bail;
200 }
201
202 env->CallStaticIntMethod(
203 gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep);
204 if (env->ExceptionCheck()) {
205 /* attempting to log the failure has failed */
206 LOGW("Failed trying to log exception, msg='%s'\n", msg);
207 env->ExceptionClear();
208 }
209
210 if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) {
211 /*
212 * It's an Error: Reraise the exception, detach this thread, and
213 * wait for the fireworks. Die even more blatantly after a minute
214 * if the gentler attempt doesn't do the trick.
215 *
216 * The GetJavaVM function isn't on the "approved" list of JNI calls
217 * that can be made while an exception is pending, so we want to
218 * get the VM ptr, throw the exception, and then detach the thread.
219 */
220 JavaVM* vm = jnienv_to_javavm(env);
221 env->Throw(excep);
222 vm->DetachCurrentThread();
223 sleep(60);
224 LOGE("Forcefully exiting");
225 exit(1);
226 *((int *) 1) = 1;
227 }
228
229bail:
230 /* discard local refs created for us by VM */
231 env->DeleteLocalRef(tagstr);
232 env->DeleteLocalRef(msgstr);
233}
234
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700235static void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy)
236{
237 // Call back into android.os.StrictMode#onBinderStrictModePolicyChange
238 // to sync our state back to it. See the comments in StrictMode.java.
239 env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass,
240 gStrictModeCallbackOffsets.mCallback,
241 strict_policy);
242}
243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244class JavaBBinderHolder;
245
246class JavaBBinder : public BBinder
247{
248public:
249 JavaBBinder(JNIEnv* env, jobject object)
250 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
251 {
Steve Block71f2cf12011-10-20 11:56:00 +0100252 ALOGV("Creating JavaBBinder %p\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 android_atomic_inc(&gNumLocalRefs);
254 incRefsCreated(env);
255 }
256
257 bool checkSubclass(const void* subclassID) const
258 {
259 return subclassID == &gBinderOffsets;
260 }
261
262 jobject object() const
263 {
264 return mObject;
265 }
266
267protected:
268 virtual ~JavaBBinder()
269 {
Steve Block71f2cf12011-10-20 11:56:00 +0100270 ALOGV("Destroying JavaBBinder %p\n", this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 android_atomic_dec(&gNumLocalRefs);
272 JNIEnv* env = javavm_to_jnienv(mVM);
273 env->DeleteGlobalRef(mObject);
274 }
275
276 virtual status_t onTransact(
277 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
278 {
279 JNIEnv* env = javavm_to_jnienv(mVM);
280
Steve Block71f2cf12011-10-20 11:56:00 +0100281 ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700283 IPCThreadState* thread_state = IPCThreadState::self();
284 const int strict_policy_before = thread_state->getStrictModePolicy();
Brad Fitzpatrick02343762010-08-30 16:01:16 -0700285 thread_state->setLastTransactionBinderFlags(flags);
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 //printf("Transact from %p to Java code sending: ", this);
288 //data.print();
289 //printf("\n");
290 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
291 code, (int32_t)&data, (int32_t)reply, flags);
292 jthrowable excep = env->ExceptionOccurred();
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700293
Bjorn Bringert9013ccd2011-04-26 19:10:58 +0100294 if (excep) {
295 report_exception(env, excep,
296 "*** Uncaught remote exception! "
297 "(Exceptions are not yet supported across processes.)");
298 res = JNI_FALSE;
299
300 /* clean up JNI local ref -- we don't return to Java code */
301 env->DeleteLocalRef(excep);
302 }
303
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700304 // Restore the Java binder thread's state if it changed while
305 // processing a call (as it would if the Parcel's header had a
306 // new policy mask and Parcel.enforceInterface() changed
307 // it...)
308 const int strict_policy_after = thread_state->getStrictModePolicy();
309 if (strict_policy_after != strict_policy_before) {
310 // Our thread-local...
311 thread_state->setStrictModePolicy(strict_policy_before);
312 // And the Java-level thread-local...
313 set_dalvik_blockguard_policy(env, strict_policy_before);
314 }
315
Bjorn Bringert9013ccd2011-04-26 19:10:58 +0100316 jthrowable excep2 = env->ExceptionOccurred();
317 if (excep2) {
318 report_exception(env, excep2,
319 "*** Uncaught exception in onBinderStrictModePolicyChange");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 /* clean up JNI local ref -- we don't return to Java code */
Bjorn Bringert9013ccd2011-04-26 19:10:58 +0100321 env->DeleteLocalRef(excep2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 }
323
324 //aout << "onTransact to Java code; result=" << res << endl
325 // << "Transact from " << this << " to Java code returning "
326 // << reply << ": " << *reply << endl;
327 return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
328 }
329
330 virtual status_t dump(int fd, const Vector<String16>& args)
331 {
332 return 0;
333 }
334
335private:
336 JavaVM* const mVM;
337 jobject const mObject;
338};
339
340// ----------------------------------------------------------------------------
341
342class JavaBBinderHolder : public RefBase
343{
344public:
Christopher Tate0b414482011-02-17 13:00:38 -0800345 sp<JavaBBinder> get(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 {
347 AutoMutex _l(mLock);
348 sp<JavaBBinder> b = mBinder.promote();
349 if (b == NULL) {
Christopher Tate0b414482011-02-17 13:00:38 -0800350 b = new JavaBBinder(env, obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 mBinder = b;
Steve Block71f2cf12011-10-20 11:56:00 +0100352 ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n",
Christopher Tate0b414482011-02-17 13:00:38 -0800353 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 }
355
356 return b;
357 }
358
359 sp<JavaBBinder> getExisting()
360 {
361 AutoMutex _l(mLock);
362 return mBinder.promote();
363 }
364
365private:
366 Mutex mLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 wp<JavaBBinder> mBinder;
368};
369
370// ----------------------------------------------------------------------------
371
Christopher Tate0b414482011-02-17 13:00:38 -0800372// Per-IBinder death recipient bookkeeping. This is how we reconcile local jobject
373// death recipient references passed in through JNI with the permanent corresponding
374// JavaDeathRecipient objects.
375
376class JavaDeathRecipient;
377
378class DeathRecipientList : public RefBase {
379 List< sp<JavaDeathRecipient> > mList;
380 Mutex mLock;
381
382public:
Christopher Tate79dd31f2011-03-04 17:45:00 -0800383 DeathRecipientList();
Christopher Tate0b414482011-02-17 13:00:38 -0800384 ~DeathRecipientList();
385
386 void add(const sp<JavaDeathRecipient>& recipient);
387 void remove(const sp<JavaDeathRecipient>& recipient);
388 sp<JavaDeathRecipient> find(jobject recipient);
389};
390
391// ----------------------------------------------------------------------------
392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393class JavaDeathRecipient : public IBinder::DeathRecipient
394{
395public:
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800396 JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
Christopher Tate86284c62011-08-17 15:19:29 -0700397 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
398 mObjectWeak(NULL), mList(list)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 {
Christopher Tate0b414482011-02-17 13:00:38 -0800400 // These objects manage their own lifetimes so are responsible for final bookkeeping.
401 // The list holds a strong reference to this object.
Christopher Tate79dd31f2011-03-04 17:45:00 -0800402 LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800403 list->add(this);
Christopher Tate0b414482011-02-17 13:00:38 -0800404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 android_atomic_inc(&gNumDeathRefs);
406 incRefsCreated(env);
407 }
408
409 void binderDied(const wp<IBinder>& who)
410 {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800411 LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
Christopher Tate86284c62011-08-17 15:19:29 -0700412 if (mObject != NULL) {
413 JNIEnv* env = javavm_to_jnienv(mVM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414
Christopher Tate86284c62011-08-17 15:19:29 -0700415 env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
416 gBinderProxyOffsets.mSendDeathNotice, mObject);
417 jthrowable excep = env->ExceptionOccurred();
418 if (excep) {
419 report_exception(env, excep,
420 "*** Uncaught exception returned from death notification!");
421 }
422
423 // Demote from strong ref to weak after binderDied() has been delivered,
424 // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
425 mObjectWeak = env->NewWeakGlobalRef(mObject);
426 env->DeleteGlobalRef(mObject);
427 mObject = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 }
430
431 void clearReference()
432 {
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800433 sp<DeathRecipientList> list = mList.promote();
434 if (list != NULL) {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800435 LOGDEATH("Removing JDR %p from DRL %p", this, list.get());
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800436 list->remove(this);
Christopher Tate79dd31f2011-03-04 17:45:00 -0800437 } else {
438 LOGDEATH("clearReference() on JDR %p but DRL wp purged", this);
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800439 }
Christopher Tate0b414482011-02-17 13:00:38 -0800440 }
441
442 bool matches(jobject obj) {
Christopher Tate86284c62011-08-17 15:19:29 -0700443 bool result;
Christopher Tate0b414482011-02-17 13:00:38 -0800444 JNIEnv* env = javavm_to_jnienv(mVM);
Christopher Tate86284c62011-08-17 15:19:29 -0700445
446 if (mObject != NULL) {
447 result = env->IsSameObject(obj, mObject);
448 } else {
449 jobject me = env->NewLocalRef(mObjectWeak);
450 result = env->IsSameObject(obj, me);
451 env->DeleteLocalRef(me);
452 }
453 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 }
455
Christopher Tateac5e3502011-08-25 15:48:09 -0700456 void warnIfStillLive() {
457 if (mObject != NULL) {
458 // Okay, something is wrong -- we have a hard reference to a live death
459 // recipient on the VM side, but the list is being torn down.
460 JNIEnv* env = javavm_to_jnienv(mVM);
Christopher Tate0d4a7922011-08-30 12:09:43 -0700461 ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
462 ScopedLocalRef<jstring> nameRef(env,
463 (jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName));
464 ScopedUtfChars nameUtf(env, nameRef.get());
465 if (nameUtf.c_str() != NULL) {
466 LOGW("BinderProxy is being destroyed but the application did not call "
467 "unlinkToDeath to unlink all of its death recipients beforehand. "
468 "Releasing leaked death recipient: %s", nameUtf.c_str());
469 } else {
470 LOGW("BinderProxy being destroyed; unable to get DR object name");
471 env->ExceptionClear();
472 }
Christopher Tateac5e3502011-08-25 15:48:09 -0700473 }
474 }
475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476protected:
477 virtual ~JavaDeathRecipient()
478 {
479 //LOGI("Removing death ref: recipient=%p\n", mObject);
480 android_atomic_dec(&gNumDeathRefs);
481 JNIEnv* env = javavm_to_jnienv(mVM);
Christopher Tate86284c62011-08-17 15:19:29 -0700482 if (mObject != NULL) {
483 env->DeleteGlobalRef(mObject);
484 } else {
485 env->DeleteWeakGlobalRef(mObjectWeak);
486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 }
488
489private:
Christopher Tate86284c62011-08-17 15:19:29 -0700490 JavaVM* const mVM;
491 jobject mObject;
492 jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied()
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800493 wp<DeathRecipientList> mList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494};
495
496// ----------------------------------------------------------------------------
497
Christopher Tate79dd31f2011-03-04 17:45:00 -0800498DeathRecipientList::DeathRecipientList() {
499 LOGDEATH("New DRL @ %p", this);
500}
501
Christopher Tate0b414482011-02-17 13:00:38 -0800502DeathRecipientList::~DeathRecipientList() {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800503 LOGDEATH("Destroy DRL @ %p", this);
Christopher Tate0b414482011-02-17 13:00:38 -0800504 AutoMutex _l(mLock);
505
506 // Should never happen -- the JavaDeathRecipient objects that have added themselves
507 // to the list are holding references on the list object. Only when they are torn
508 // down can the list header be destroyed.
509 if (mList.size() > 0) {
Christopher Tateac5e3502011-08-25 15:48:09 -0700510 List< sp<JavaDeathRecipient> >::iterator iter;
511 for (iter = mList.begin(); iter != mList.end(); iter++) {
512 (*iter)->warnIfStillLive();
513 }
Christopher Tate0b414482011-02-17 13:00:38 -0800514 }
515}
516
517void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) {
518 AutoMutex _l(mLock);
519
Christopher Tate79dd31f2011-03-04 17:45:00 -0800520 LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get());
Christopher Tate0b414482011-02-17 13:00:38 -0800521 mList.push_back(recipient);
522}
523
524void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) {
525 AutoMutex _l(mLock);
526
527 List< sp<JavaDeathRecipient> >::iterator iter;
528 for (iter = mList.begin(); iter != mList.end(); iter++) {
529 if (*iter == recipient) {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800530 LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get());
Christopher Tate0b414482011-02-17 13:00:38 -0800531 mList.erase(iter);
532 return;
533 }
534 }
535}
536
537sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) {
538 AutoMutex _l(mLock);
539
540 List< sp<JavaDeathRecipient> >::iterator iter;
541 for (iter = mList.begin(); iter != mList.end(); iter++) {
542 if ((*iter)->matches(recipient)) {
543 return *iter;
544 }
545 }
546 return NULL;
547}
548
Christopher Tate0b414482011-02-17 13:00:38 -0800549// ----------------------------------------------------------------------------
550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551namespace android {
552
553static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie)
554{
555 android_atomic_dec(&gNumProxyRefs);
556 JNIEnv* env = javavm_to_jnienv((JavaVM*)cleanupCookie);
557 env->DeleteGlobalRef((jobject)obj);
558}
559
560static Mutex mProxyLock;
561
562jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
563{
564 if (val == NULL) return NULL;
565
566 if (val->checkSubclass(&gBinderOffsets)) {
567 // One of our own!
568 jobject object = static_cast<JavaBBinder*>(val.get())->object();
Christopher Tate86284c62011-08-17 15:19:29 -0700569 LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 return object;
571 }
572
573 // For the rest of the function we will hold this lock, to serialize
574 // looking/creation of Java proxies for native Binder proxies.
575 AutoMutex _l(mProxyLock);
576
577 // Someone else's... do we know about it?
578 jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
579 if (object != NULL) {
580 jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet);
581 if (res != NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +0100582 ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 return res;
584 }
Christopher Tate86284c62011-08-17 15:19:29 -0700585 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 -0800586 android_atomic_dec(&gNumProxyRefs);
587 val->detachObject(&gBinderProxyOffsets);
588 env->DeleteGlobalRef(object);
589 }
590
591 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
592 if (object != NULL) {
Christopher Tate79dd31f2011-03-04 17:45:00 -0800593 LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 // The proxy holds a reference to the native object.
595 env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());
596 val->incStrong(object);
597
598 // The native object needs to hold a weak reference back to the
599 // proxy, so we can retrieve the same proxy if it is still active.
600 jobject refObject = env->NewGlobalRef(
601 env->GetObjectField(object, gBinderProxyOffsets.mSelf));
602 val->attachObject(&gBinderProxyOffsets, refObject,
603 jnienv_to_javavm(env), proxy_cleanup);
604
Christopher Tatebd8b6f22011-03-01 11:55:27 -0800605 // Also remember the death recipients registered on this proxy
606 sp<DeathRecipientList> drl = new DeathRecipientList;
607 drl->incStrong((void*)javaObjectForIBinder);
608 env->SetIntField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jint>(drl.get()));
609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 // Note that a new object reference has been created.
611 android_atomic_inc(&gNumProxyRefs);
612 incRefsCreated(env);
613 }
614
615 return object;
616}
617
618sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
619{
620 if (obj == NULL) return NULL;
621
622 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
623 JavaBBinderHolder* jbh = (JavaBBinderHolder*)
624 env->GetIntField(obj, gBinderOffsets.mObject);
Christopher Tate0b414482011-02-17 13:00:38 -0800625 return jbh != NULL ? jbh->get(env, obj) : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 }
627
628 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
629 return (IBinder*)
630 env->GetIntField(obj, gBinderProxyOffsets.mObject);
631 }
632
633 LOGW("ibinderForJavaObject: %p is not a Binder object", obj);
634 return NULL;
635}
636
637Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
638{
639 if (obj) {
640 Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mObject);
641 if (p != NULL) {
642 return p;
643 }
644 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
645 }
646 return NULL;
647}
648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
650{
651 return env->NewObject(
652 gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc);
653}
654
Jeff Brown0bde66a2011-11-07 12:50:08 -0800655static void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
656 bool canThrowRemoteException = false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657{
658 switch (err) {
659 case UNKNOWN_ERROR:
660 jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
661 break;
662 case NO_MEMORY:
663 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
664 break;
665 case INVALID_OPERATION:
666 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
667 break;
668 case BAD_VALUE:
669 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
670 break;
671 case BAD_INDEX:
672 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
673 break;
674 case BAD_TYPE:
675 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
676 break;
677 case NAME_NOT_FOUND:
678 jniThrowException(env, "java/util/NoSuchElementException", NULL);
679 break;
680 case PERMISSION_DENIED:
681 jniThrowException(env, "java/lang/SecurityException", NULL);
682 break;
683 case NOT_ENOUGH_DATA:
684 jniThrowException(env, "android/os/ParcelFormatException", "Not enough data");
685 break;
686 case NO_INIT:
687 jniThrowException(env, "java/lang/RuntimeException", "Not initialized");
688 break;
689 case ALREADY_EXISTS:
690 jniThrowException(env, "java/lang/RuntimeException", "Item already exists");
691 break;
692 case DEAD_OBJECT:
Jeff Brown0bde66a2011-11-07 12:50:08 -0800693 // DeadObjectException is a checked exception, only throw from certain methods.
694 jniThrowException(env, canThrowRemoteException
695 ? "android/os/DeadObjectException"
696 : "java/lang/RuntimeException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 break;
698 case UNKNOWN_TRANSACTION:
699 jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code");
700 break;
701 case FAILED_TRANSACTION:
702 LOGE("!!! FAILED BINDER TRANSACTION !!!");
Jeff Brown0bde66a2011-11-07 12:50:08 -0800703 // TransactionTooLargeException is a checked exception, only throw from certain methods.
704 // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
705 // but it is not the only one. The Binder driver can return BR_FAILED_REPLY
706 // for other reasons also, such as if the transaction is malformed or
707 // refers to an FD that has been closed. We should change the driver
708 // to enable us to distinguish these cases in the future.
709 jniThrowException(env, canThrowRemoteException
710 ? "android/os/TransactionTooLargeException"
711 : "java/lang/RuntimeException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 break;
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400713 case FDS_NOT_ALLOWED:
714 jniThrowException(env, "java/lang/RuntimeException",
715 "Not allowed to write file descriptors here");
716 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 default:
718 LOGE("Unknown binder error code. 0x%x", err);
Jeff Brown0bde66a2011-11-07 12:50:08 -0800719 String8 msg;
720 msg.appendFormat("Unknown binder error code. 0x%x", err);
721 // RemoteException is a checked exception, only throw from certain methods.
722 jniThrowException(env, canThrowRemoteException
723 ? "android/os/RemoteException" : "java/lang/RuntimeException", msg.string());
724 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725 }
726}
727
728}
729
730// ----------------------------------------------------------------------------
731
732static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz)
733{
734 return IPCThreadState::self()->getCallingPid();
735}
736
737static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz)
738{
739 return IPCThreadState::self()->getCallingUid();
740}
741
742static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz)
743{
744 return IPCThreadState::self()->clearCallingIdentity();
745}
746
747static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
748{
Dianne Hackborncf3004a2011-03-14 14:24:04 -0700749 // XXX temporary sanity check to debug crashes.
750 int uid = (int)(token>>32);
751 if (uid > 0 && uid < 999) {
752 // In Android currently there are no uids in this range.
753 char buf[128];
754 sprintf(buf, "Restoring bad calling ident: 0x%Lx", token);
755 jniThrowException(env, "java/lang/IllegalStateException", buf);
756 return;
757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 IPCThreadState::self()->restoreCallingIdentity(token);
759}
760
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700761static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask)
762{
763 IPCThreadState::self()->setStrictModePolicy(policyMask);
764}
765
766static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz)
767{
768 return IPCThreadState::self()->getStrictModePolicy();
769}
770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz)
772{
773 IPCThreadState::self()->flushCommands();
774}
775
Christopher Tate0b414482011-02-17 13:00:38 -0800776static void android_os_Binder_init(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777{
Christopher Tate0b414482011-02-17 13:00:38 -0800778 JavaBBinderHolder* jbh = new JavaBBinderHolder();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 if (jbh == NULL) {
780 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
781 return;
782 }
Steve Block71f2cf12011-10-20 11:56:00 +0100783 ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
Christopher Tate0b414482011-02-17 13:00:38 -0800784 jbh->incStrong((void*)android_os_Binder_init);
785 env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786}
787
Christopher Tate0b414482011-02-17 13:00:38 -0800788static void android_os_Binder_destroy(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789{
790 JavaBBinderHolder* jbh = (JavaBBinderHolder*)
Christopher Tate0b414482011-02-17 13:00:38 -0800791 env->GetIntField(obj, gBinderOffsets.mObject);
Jeff Brown582763a2010-03-24 18:56:57 -0700792 if (jbh != NULL) {
Christopher Tate0b414482011-02-17 13:00:38 -0800793 env->SetIntField(obj, gBinderOffsets.mObject, 0);
Steve Block71f2cf12011-10-20 11:56:00 +0100794 ALOGV("Java Binder %p: removing ref on holder %p", obj, jbh);
Christopher Tate0b414482011-02-17 13:00:38 -0800795 jbh->decStrong((void*)android_os_Binder_init);
Jeff Brown582763a2010-03-24 18:56:57 -0700796 } else {
797 // Encountering an uninitialized binder is harmless. All it means is that
798 // the Binder was only partially initialized when its finalizer ran and called
799 // destroy(). The Binder could be partially initialized for several reasons.
800 // For example, a Binder subclass constructor might have thrown an exception before
801 // it could delegate to its superclass's constructor. Consequently init() would
802 // not have been called and the holder pointer would remain NULL.
Steve Block71f2cf12011-10-20 11:56:00 +0100803 ALOGV("Java Binder %p: ignoring uninitialized binder", obj);
Jeff Brown582763a2010-03-24 18:56:57 -0700804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805}
806
807// ----------------------------------------------------------------------------
808
809static const JNINativeMethod gBinderMethods[] = {
810 /* name, signature, funcPtr */
811 { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
812 { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
813 { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
814 { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700815 { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
816 { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
818 { "init", "()V", (void*)android_os_Binder_init },
819 { "destroy", "()V", (void*)android_os_Binder_destroy }
820};
821
822const char* const kBinderPathName = "android/os/Binder";
823
824static int int_register_android_os_Binder(JNIEnv* env)
825{
826 jclass clazz;
827
828 clazz = env->FindClass(kBinderPathName);
829 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");
830
831 gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
832 gBinderOffsets.mExecTransact
833 = env->GetMethodID(clazz, "execTransact", "(IIII)Z");
834 assert(gBinderOffsets.mExecTransact);
835
836 gBinderOffsets.mObject
837 = env->GetFieldID(clazz, "mObject", "I");
838 assert(gBinderOffsets.mObject);
839
840 return AndroidRuntime::registerNativeMethods(
841 env, kBinderPathName,
842 gBinderMethods, NELEM(gBinderMethods));
843}
844
845// ****************************************************************************
846// ****************************************************************************
847// ****************************************************************************
848
849namespace android {
850
851jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz)
852{
853 return gNumLocalRefs;
854}
855
856jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
857{
858 return gNumProxyRefs;
859}
860
861jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
862{
863 return gNumDeathRefs;
864}
865
866}
867
868// ****************************************************************************
869// ****************************************************************************
870// ****************************************************************************
871
872static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
873{
874 sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
875 return javaObjectForIBinder(env, b);
876}
877
878static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz)
879{
880 sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
881 android::IPCThreadState::self()->joinThreadPool();
882}
883
Dianne Hackborn887f3552009-12-07 17:59:37 -0800884static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env,
885 jobject clazz, jboolean disable)
886{
887 IPCThreadState::disableBackgroundScheduling(disable ? true : false);
888}
889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz)
891{
Steve Block71f2cf12011-10-20 11:56:00 +0100892 ALOGV("Gc has executed, clearing binder ops");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 android_atomic_and(0, &gNumRefsCreated);
894}
895
896// ----------------------------------------------------------------------------
897
898static const JNINativeMethod gBinderInternalMethods[] = {
899 /* name, signature, funcPtr */
900 { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
901 { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
Dianne Hackborn887f3552009-12-07 17:59:37 -0800902 { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
904};
905
906const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
907
908static int int_register_android_os_BinderInternal(JNIEnv* env)
909{
910 jclass clazz;
911
912 clazz = env->FindClass(kBinderInternalPathName);
913 LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal");
914
915 gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
916 gBinderInternalOffsets.mForceGc
917 = env->GetStaticMethodID(clazz, "forceBinderGc", "()V");
918 assert(gBinderInternalOffsets.mForceGc);
919
920 return AndroidRuntime::registerNativeMethods(
921 env, kBinderInternalPathName,
922 gBinderInternalMethods, NELEM(gBinderInternalMethods));
923}
924
925// ****************************************************************************
926// ****************************************************************************
927// ****************************************************************************
928
929static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj)
930{
931 IBinder* target = (IBinder*)
932 env->GetIntField(obj, gBinderProxyOffsets.mObject);
933 if (target == NULL) {
934 return JNI_FALSE;
935 }
936 status_t err = target->pingBinder();
937 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
938}
939
940static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj)
941{
942 IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject);
943 if (target != NULL) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -0700944 const String16& desc = target->getInterfaceDescriptor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 return env->NewString(desc.string(), desc.size());
946 }
947 jniThrowException(env, "java/lang/RuntimeException",
948 "No binder found for object");
949 return NULL;
950}
951
952static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj)
953{
954 IBinder* target = (IBinder*)
955 env->GetIntField(obj, gBinderProxyOffsets.mObject);
956 if (target == NULL) {
957 return JNI_FALSE;
958 }
959 bool alive = target->isBinderAlive();
960 return alive ? JNI_TRUE : JNI_FALSE;
961}
962
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -0700963static int getprocname(pid_t pid, char *buf, size_t len) {
964 char filename[20];
965 FILE *f;
966
967 sprintf(filename, "/proc/%d/cmdline", pid);
968 f = fopen(filename, "r");
969 if (!f) { *buf = '\0'; return 1; }
970 if (!fgets(buf, len, f)) { *buf = '\0'; return 2; }
971 fclose(f);
972 return 0;
973}
974
975static bool push_eventlog_string(char** pos, const char* end, const char* str) {
976 jint len = strlen(str);
977 int space_needed = 1 + sizeof(len) + len;
978 if (end - *pos < space_needed) {
979 LOGW("not enough space for string. remain=%d; needed=%d",
980 (end - *pos), space_needed);
981 return false;
982 }
983 **pos = EVENT_TYPE_STRING;
984 (*pos)++;
985 memcpy(*pos, &len, sizeof(len));
986 *pos += sizeof(len);
987 memcpy(*pos, str, len);
988 *pos += len;
989 return true;
990}
991
992static bool push_eventlog_int(char** pos, const char* end, jint val) {
993 int space_needed = 1 + sizeof(val);
994 if (end - *pos < space_needed) {
995 LOGW("not enough space for int. remain=%d; needed=%d",
996 (end - *pos), space_needed);
997 return false;
998 }
999 **pos = EVENT_TYPE_INT;
1000 (*pos)++;
1001 memcpy(*pos, &val, sizeof(val));
1002 *pos += sizeof(val);
1003 return true;
1004}
1005
1006// From frameworks/base/core/java/android/content/EventLogTags.logtags:
1007#define LOGTAG_BINDER_OPERATION 52004
1008
1009static void conditionally_log_binder_call(int64_t start_millis,
1010 IBinder* target, jint code) {
1011 int duration_ms = static_cast<int>(uptimeMillis() - start_millis);
1012
1013 int sample_percent;
1014 if (duration_ms >= 500) {
1015 sample_percent = 100;
1016 } else {
1017 sample_percent = 100 * duration_ms / 500;
1018 if (sample_percent == 0) {
1019 return;
1020 }
1021 if (sample_percent < (random() % 100 + 1)) {
1022 return;
1023 }
1024 }
1025
1026 char process_name[40];
1027 getprocname(getpid(), process_name, sizeof(process_name));
1028 String8 desc(target->getInterfaceDescriptor());
1029
1030 char buf[LOGGER_ENTRY_MAX_PAYLOAD];
1031 buf[0] = EVENT_TYPE_LIST;
1032 buf[1] = 5;
1033 char* pos = &buf[2];
1034 char* end = &buf[LOGGER_ENTRY_MAX_PAYLOAD - 1]; // leave room for final \n
1035 if (!push_eventlog_string(&pos, end, desc.string())) return;
1036 if (!push_eventlog_int(&pos, end, code)) return;
1037 if (!push_eventlog_int(&pos, end, duration_ms)) return;
1038 if (!push_eventlog_string(&pos, end, process_name)) return;
1039 if (!push_eventlog_int(&pos, end, sample_percent)) return;
1040 *(pos++) = '\n'; // conventional with EVENT_TYPE_LIST apparently.
1041 android_bWriteLog(LOGTAG_BINDER_OPERATION, buf, pos - buf);
1042}
1043
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001044// We only measure binder call durations to potentially log them if
1045// we're on the main thread. Unfortunately sim-eng doesn't seem to
1046// have gettid, so we just ignore this and don't log if we can't
1047// get the thread id.
1048static bool should_time_binder_calls() {
Brad Fitzpatrick5348c012010-03-25 12:43:56 -07001049#ifdef HAVE_GETTID
1050 return (getpid() == androidGetTid());
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001051#else
1052#warning no gettid(), so not logging Binder calls...
1053 return false;
1054#endif
1055}
1056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
Jeff Brown0bde66a2011-11-07 12:50:08 -08001058 jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059{
1060 if (dataObj == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001061 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 return JNI_FALSE;
1063 }
1064
1065 Parcel* data = parcelForJavaObject(env, dataObj);
1066 if (data == NULL) {
1067 return JNI_FALSE;
1068 }
1069 Parcel* reply = parcelForJavaObject(env, replyObj);
1070 if (reply == NULL && replyObj != NULL) {
1071 return JNI_FALSE;
1072 }
1073
1074 IBinder* target = (IBinder*)
1075 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1076 if (target == NULL) {
1077 jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
1078 return JNI_FALSE;
1079 }
1080
Steve Block71f2cf12011-10-20 11:56:00 +01001081 ALOGV("Java code calling transact on %p in Java object %p with code %d\n",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 target, obj, code);
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001083
1084 // Only log the binder call duration for things on the Java-level main thread.
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001085 // But if we don't
1086 const bool time_binder_calls = should_time_binder_calls();
1087
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001088 int64_t start_millis;
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001089 if (time_binder_calls) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001090 start_millis = uptimeMillis();
1091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 //printf("Transact from Java code to %p sending: ", target); data->print();
1093 status_t err = target->transact(code, *data, reply, flags);
1094 //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001095 if (time_binder_calls) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001096 conditionally_log_binder_call(start_millis, target, code);
1097 }
1098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 if (err == NO_ERROR) {
1100 return JNI_TRUE;
1101 } else if (err == UNKNOWN_TRANSACTION) {
1102 return JNI_FALSE;
1103 }
1104
Jeff Brown0bde66a2011-11-07 12:50:08 -08001105 signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 return JNI_FALSE;
1107}
1108
1109static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
Jeff Brown0bde66a2011-11-07 12:50:08 -08001110 jobject recipient, jint flags) // throws RemoteException
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111{
1112 if (recipient == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001113 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 return;
1115 }
1116
1117 IBinder* target = (IBinder*)
1118 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1119 if (target == NULL) {
1120 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
1121 assert(false);
1122 }
1123
Christopher Tate79dd31f2011-03-04 17:45:00 -08001124 LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125
1126 if (!target->localBinder()) {
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001127 DeathRecipientList* list = (DeathRecipientList*)
1128 env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
1129 sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);
Christopher Tate0b414482011-02-17 13:00:38 -08001130 status_t err = target->linkToDeath(jdr, NULL, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 if (err != NO_ERROR) {
1132 // Failure adding the death recipient, so clear its reference
1133 // now.
1134 jdr->clearReference();
Jeff Brown0bde66a2011-11-07 12:50:08 -08001135 signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 }
1137 }
1138}
1139
1140static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
1141 jobject recipient, jint flags)
1142{
1143 jboolean res = JNI_FALSE;
1144 if (recipient == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001145 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 return res;
1147 }
1148
1149 IBinder* target = (IBinder*)
1150 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1151 if (target == NULL) {
1152 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
1153 return JNI_FALSE;
1154 }
1155
Christopher Tate79dd31f2011-03-04 17:45:00 -08001156 LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157
1158 if (!target->localBinder()) {
Christopher Tate0b414482011-02-17 13:00:38 -08001159 status_t err = NAME_NOT_FOUND;
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001160
1161 // If we find the matching recipient, proceed to unlink using that
1162 DeathRecipientList* list = (DeathRecipientList*)
1163 env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
1164 sp<JavaDeathRecipient> origJDR = list->find(recipient);
Christopher Tate79dd31f2011-03-04 17:45:00 -08001165 LOGDEATH(" unlink found list %p and JDR %p", list, origJDR.get());
Christopher Tate0b414482011-02-17 13:00:38 -08001166 if (origJDR != NULL) {
1167 wp<IBinder::DeathRecipient> dr;
1168 err = target->unlinkToDeath(origJDR, NULL, flags, &dr);
1169 if (err == NO_ERROR && dr != NULL) {
1170 sp<IBinder::DeathRecipient> sdr = dr.promote();
1171 JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get());
1172 if (jdr != NULL) {
1173 jdr->clearReference();
1174 }
1175 }
1176 }
1177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 if (err == NO_ERROR || err == DEAD_OBJECT) {
1179 res = JNI_TRUE;
1180 } else {
1181 jniThrowException(env, "java/util/NoSuchElementException",
1182 "Death link does not exist");
1183 }
1184 }
1185
1186 return res;
1187}
1188
1189static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj)
1190{
1191 IBinder* b = (IBinder*)
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001192 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1193 DeathRecipientList* drl = (DeathRecipientList*)
1194 env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
Christopher Tate0b414482011-02-17 13:00:38 -08001195
Christopher Tate79dd31f2011-03-04 17:45:00 -08001196 LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl);
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001197 env->SetIntField(obj, gBinderProxyOffsets.mObject, 0);
1198 env->SetIntField(obj, gBinderProxyOffsets.mOrgue, 0);
1199 drl->decStrong((void*)javaObjectForIBinder);
1200 b->decStrong(obj);
1201
1202 IPCThreadState::self()->flushCommands();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203}
1204
1205// ----------------------------------------------------------------------------
1206
1207static const JNINativeMethod gBinderProxyMethods[] = {
1208 /* name, signature, funcPtr */
1209 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
1210 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
1211 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
1212 {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
1213 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
1214 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
1215 {"destroy", "()V", (void*)android_os_BinderProxy_destroy},
1216};
1217
1218const char* const kBinderProxyPathName = "android/os/BinderProxy";
1219
1220static int int_register_android_os_BinderProxy(JNIEnv* env)
1221{
1222 jclass clazz;
1223
1224 clazz = env->FindClass("java/lang/ref/WeakReference");
1225 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.ref.WeakReference");
1226 gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1227 gWeakReferenceOffsets.mGet
1228 = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;");
1229 assert(gWeakReferenceOffsets.mGet);
1230
1231 clazz = env->FindClass("java/lang/Error");
1232 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error");
1233 gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001235 clazz = env->FindClass(kBinderProxyPathName);
1236 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy");
1237
1238 gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1239 gBinderProxyOffsets.mConstructor
1240 = env->GetMethodID(clazz, "<init>", "()V");
1241 assert(gBinderProxyOffsets.mConstructor);
1242 gBinderProxyOffsets.mSendDeathNotice
1243 = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V");
1244 assert(gBinderProxyOffsets.mSendDeathNotice);
1245
1246 gBinderProxyOffsets.mObject
1247 = env->GetFieldID(clazz, "mObject", "I");
1248 assert(gBinderProxyOffsets.mObject);
1249 gBinderProxyOffsets.mSelf
1250 = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
1251 assert(gBinderProxyOffsets.mSelf);
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001252 gBinderProxyOffsets.mOrgue
1253 = env->GetFieldID(clazz, "mOrgue", "I");
1254 assert(gBinderProxyOffsets.mOrgue);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255
Christopher Tate0d4a7922011-08-30 12:09:43 -07001256 clazz = env->FindClass("java/lang/Class");
1257 LOG_FATAL_IF(clazz == NULL, "Unable to find java.lang.Class");
1258 gClassOffsets.mGetName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");
1259 assert(gClassOffsets.mGetName);
1260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 return AndroidRuntime::registerNativeMethods(
1262 env, kBinderProxyPathName,
1263 gBinderProxyMethods, NELEM(gBinderProxyMethods));
1264}
1265
1266// ****************************************************************************
1267// ****************************************************************************
1268// ****************************************************************************
1269
1270static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz)
1271{
1272 Parcel* parcel = parcelForJavaObject(env, clazz);
1273 return parcel ? parcel->dataSize() : 0;
1274}
1275
1276static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz)
1277{
1278 Parcel* parcel = parcelForJavaObject(env, clazz);
1279 return parcel ? parcel->dataAvail() : 0;
1280}
1281
1282static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz)
1283{
1284 Parcel* parcel = parcelForJavaObject(env, clazz);
1285 return parcel ? parcel->dataPosition() : 0;
1286}
1287
1288static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz)
1289{
1290 Parcel* parcel = parcelForJavaObject(env, clazz);
1291 return parcel ? parcel->dataCapacity() : 0;
1292}
1293
1294static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size)
1295{
1296 Parcel* parcel = parcelForJavaObject(env, clazz);
1297 if (parcel != NULL) {
1298 const status_t err = parcel->setDataSize(size);
1299 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001300 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 }
1302 }
1303}
1304
1305static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos)
1306{
1307 Parcel* parcel = parcelForJavaObject(env, clazz);
1308 if (parcel != NULL) {
1309 parcel->setDataPosition(pos);
1310 }
1311}
1312
1313static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size)
1314{
1315 Parcel* parcel = parcelForJavaObject(env, clazz);
1316 if (parcel != NULL) {
1317 const status_t err = parcel->setDataCapacity(size);
1318 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001319 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 }
1321 }
1322}
1323
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001324static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001325{
1326 Parcel* parcel = parcelForJavaObject(env, clazz);
1327 jboolean ret = JNI_TRUE;
1328 if (parcel != NULL) {
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001329 ret = (jboolean)parcel->pushAllowFds(allowFds);
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001330 }
1331 return ret;
1332}
1333
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001334static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jobject clazz, jboolean lastValue)
1335{
1336 Parcel* parcel = parcelForJavaObject(env, clazz);
1337 if (parcel != NULL) {
1338 parcel->restoreAllowFds((bool)lastValue);
1339 }
1340}
1341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
1343 jobject data, jint offset,
1344 jint length)
1345{
1346 Parcel* parcel = parcelForJavaObject(env, clazz);
1347 if (parcel == NULL) {
1348 return;
1349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350
1351 const status_t err = parcel->writeInt32(length);
1352 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001353 signalExceptionForError(env, clazz, err);
1354 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 }
1356
Elliott Hughesa28b83e2011-02-28 14:26:13 -08001357 void* dest = parcel->writeInplace(length);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 if (dest == NULL) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001359 signalExceptionForError(env, clazz, NO_MEMORY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 return;
1361 }
1362
1363 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
1364 if (ar) {
Elliott Hughesa28b83e2011-02-28 14:26:13 -08001365 memcpy(dest, ar + offset, length);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
1367 }
1368}
1369
1370
1371static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
1372{
1373 Parcel* parcel = parcelForJavaObject(env, clazz);
1374 if (parcel != NULL) {
1375 const status_t err = parcel->writeInt32(val);
1376 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001377 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 }
1379 }
1380}
1381
1382static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
1383{
1384 Parcel* parcel = parcelForJavaObject(env, clazz);
1385 if (parcel != NULL) {
1386 const status_t err = parcel->writeInt64(val);
1387 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001388 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 }
1390 }
1391}
1392
1393static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
1394{
1395 Parcel* parcel = parcelForJavaObject(env, clazz);
1396 if (parcel != NULL) {
1397 const status_t err = parcel->writeFloat(val);
1398 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001399 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 }
1401 }
1402}
1403
1404static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val)
1405{
1406 Parcel* parcel = parcelForJavaObject(env, clazz);
1407 if (parcel != NULL) {
1408 const status_t err = parcel->writeDouble(val);
1409 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001410 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 }
1412 }
1413}
1414
1415static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val)
1416{
1417 Parcel* parcel = parcelForJavaObject(env, clazz);
1418 if (parcel != NULL) {
1419 status_t err = NO_MEMORY;
1420 if (val) {
1421 const jchar* str = env->GetStringCritical(val, 0);
1422 if (str) {
1423 err = parcel->writeString16(str, env->GetStringLength(val));
1424 env->ReleaseStringCritical(val, str);
1425 }
1426 } else {
1427 err = parcel->writeString16(NULL, 0);
1428 }
1429 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001430 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 }
1432 }
1433}
1434
1435static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
1436{
1437 Parcel* parcel = parcelForJavaObject(env, clazz);
1438 if (parcel != NULL) {
1439 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
1440 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001441 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 }
1443 }
1444}
1445
1446static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1447{
1448 Parcel* parcel = parcelForJavaObject(env, clazz);
1449 if (parcel != NULL) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001450 const status_t err =
1451 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001453 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 }
1455 }
1456}
1457
1458static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz)
1459{
1460 jbyteArray ret = NULL;
1461
1462 Parcel* parcel = parcelForJavaObject(env, clazz);
1463 if (parcel != NULL) {
1464 int32_t len = parcel->readInt32();
1465
1466 // sanity check the stored length against the true data size
1467 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
1468 ret = env->NewByteArray(len);
1469
1470 if (ret != NULL) {
1471 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
1472 if (a2) {
1473 const void* data = parcel->readInplace(len);
1474 memcpy(a2, data, len);
1475 env->ReleasePrimitiveArrayCritical(ret, a2, 0);
1476 }
1477 }
1478 }
1479 }
1480
1481 return ret;
1482}
1483
1484static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz)
1485{
1486 Parcel* parcel = parcelForJavaObject(env, clazz);
1487 if (parcel != NULL) {
1488 return parcel->readInt32();
1489 }
1490 return 0;
1491}
1492
1493static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz)
1494{
1495 Parcel* parcel = parcelForJavaObject(env, clazz);
1496 if (parcel != NULL) {
1497 return parcel->readInt64();
1498 }
1499 return 0;
1500}
1501
1502static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz)
1503{
1504 Parcel* parcel = parcelForJavaObject(env, clazz);
1505 if (parcel != NULL) {
1506 return parcel->readFloat();
1507 }
1508 return 0;
1509}
1510
1511static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz)
1512{
1513 Parcel* parcel = parcelForJavaObject(env, clazz);
1514 if (parcel != NULL) {
1515 return parcel->readDouble();
1516 }
1517 return 0;
1518}
1519
1520static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz)
1521{
1522 Parcel* parcel = parcelForJavaObject(env, clazz);
1523 if (parcel != NULL) {
1524 size_t len;
1525 const char16_t* str = parcel->readString16Inplace(&len);
1526 if (str) {
1527 return env->NewString(str, len);
1528 }
1529 return NULL;
1530 }
1531 return NULL;
1532}
1533
1534static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
1535{
1536 Parcel* parcel = parcelForJavaObject(env, clazz);
1537 if (parcel != NULL) {
1538 return javaObjectForIBinder(env, parcel->readStrongBinder());
1539 }
1540 return NULL;
1541}
1542
1543static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz)
1544{
1545 Parcel* parcel = parcelForJavaObject(env, clazz);
1546 if (parcel != NULL) {
1547 int fd = parcel->readFileDescriptor();
1548 if (fd < 0) return NULL;
1549 fd = dup(fd);
1550 if (fd < 0) return NULL;
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001551 return jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 }
1553 return NULL;
1554}
1555
1556static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz,
1557 jstring name, jint mode)
1558{
1559 if (name == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001560 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 return NULL;
1562 }
1563 const jchar* str = env->GetStringCritical(name, 0);
1564 if (str == NULL) {
1565 // Whatever, whatever.
1566 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1567 return NULL;
1568 }
1569 String8 name8(str, env->GetStringLength(name));
1570 env->ReleaseStringCritical(name, str);
1571 int flags=0;
1572 switch (mode&0x30000000) {
1573 case 0:
1574 case 0x10000000:
1575 flags = O_RDONLY;
1576 break;
1577 case 0x20000000:
1578 flags = O_WRONLY;
1579 break;
1580 case 0x30000000:
1581 flags = O_RDWR;
1582 break;
1583 }
1584
1585 if (mode&0x08000000) flags |= O_CREAT;
1586 if (mode&0x04000000) flags |= O_TRUNC;
1587 if (mode&0x02000000) flags |= O_APPEND;
1588
1589 int realMode = S_IRWXU|S_IRWXG;
1590 if (mode&0x00000001) realMode |= S_IROTH;
1591 if (mode&0x00000002) realMode |= S_IWOTH;
1592
1593 int fd = open(name8.string(), flags, realMode);
1594 if (fd < 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001595 jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
1596 return NULL;
1597 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001598 jobject object = jniCreateFileDescriptor(env, fd);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001599 if (object == NULL) {
1600 close(fd);
1601 }
1602 return object;
1603}
1604
1605static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jobject clazz, jobject orig)
1606{
1607 if (orig == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001608 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001609 return NULL;
1610 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001611 int origfd = jniGetFDFromFileDescriptor(env, orig);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001612 if (origfd < 0) {
1613 jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
1614 return NULL;
1615 }
1616
1617 int fd = dup(origfd);
1618 if (fd < 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001619 jniThrowIOException(env, errno);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 return NULL;
1621 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001622 jobject object = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 if (object == NULL) {
1624 close(fd);
1625 }
1626 return object;
1627}
1628
1629static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1630{
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001631 if (object == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001632 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001633 return;
1634 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001635 int fd = jniGetFDFromFileDescriptor(env, object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 if (fd >= 0) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001637 jniSetFileDescriptorOfFD(env, object, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 //LOGI("Closing ParcelFileDescriptor %d\n", fd);
1639 close(fd);
1640 }
1641}
1642
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001643static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1644{
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001645 if (object == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001646 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001647 return;
1648 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001649 int fd = jniGetFDFromFileDescriptor(env, object);
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001650 if (fd >= 0) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001651 jniSetFileDescriptorOfFD(env, object, -1);
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001652 }
1653}
1654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz)
1656{
1657 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
1658 if (own) {
1659 Parcel* parcel = parcelForJavaObject(env, clazz);
1660 if (parcel != NULL) {
1661 //LOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel);
1662 parcel->freeData();
1663 }
1664 }
1665}
1666
1667static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt)
1668{
1669 Parcel* parcel = (Parcel*)parcelInt;
1670 int own = 0;
1671 if (!parcel) {
1672 //LOGI("Initializing obj %p: creating new Parcel\n", clazz);
1673 own = 1;
1674 parcel = new Parcel;
1675 } else {
1676 //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel);
1677 }
1678 if (parcel == NULL) {
1679 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1680 return;
1681 }
1682 //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own);
1683 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own);
1684 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel);
1685}
1686
1687static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz)
1688{
1689 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
1690 if (own) {
1691 Parcel* parcel = parcelForJavaObject(env, clazz);
1692 env->SetIntField(clazz, gParcelOffsets.mObject, 0);
1693 //LOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel);
1694 delete parcel;
1695 } else {
1696 env->SetIntField(clazz, gParcelOffsets.mObject, 0);
1697 //LOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz);
1698 }
1699}
1700
1701static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz)
1702{
1703 Parcel* parcel = parcelForJavaObject(env, clazz);
1704 if (parcel == NULL) {
1705 return NULL;
1706 }
1707
1708 // do not marshall if there are binder objects in the parcel
1709 if (parcel->objectsCount())
1710 {
1711 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
1712 return NULL;
1713 }
1714
1715 jbyteArray ret = env->NewByteArray(parcel->dataSize());
1716
1717 if (ret != NULL)
1718 {
1719 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
1720 if (array != NULL)
1721 {
1722 memcpy(array, parcel->data(), parcel->dataSize());
1723 env->ReleasePrimitiveArrayCritical(ret, array, 0);
1724 }
1725 }
1726
1727 return ret;
1728}
1729
1730static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length)
1731{
1732 Parcel* parcel = parcelForJavaObject(env, clazz);
1733 if (parcel == NULL || length < 0) {
1734 return;
1735 }
1736
1737 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
1738 if (array)
1739 {
1740 parcel->setDataSize(length);
1741 parcel->setDataPosition(0);
1742
1743 void* raw = parcel->writeInplace(length);
1744 memcpy(raw, (array + offset), length);
1745
1746 env->ReleasePrimitiveArrayCritical(data, array, 0);
1747 }
1748}
1749
1750static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length)
1751{
1752 Parcel* thisParcel = parcelForJavaObject(env, clazz);
1753 if (thisParcel == NULL) {
1754 return;
1755 }
1756 Parcel* otherParcel = parcelForJavaObject(env, parcel);
1757 if (otherParcel == NULL) {
1758 return;
1759 }
1760
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001761 status_t err = thisParcel->appendFrom(otherParcel, offset, length);
1762 if (err != NO_ERROR) {
1763 signalExceptionForError(env, clazz, err);
1764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765}
1766
1767static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
1768{
1769 jboolean ret = JNI_FALSE;
1770 Parcel* parcel = parcelForJavaObject(env, clazz);
1771 if (parcel != NULL) {
1772 if (parcel->hasFileDescriptors()) {
1773 ret = JNI_TRUE;
1774 }
1775 }
1776 return ret;
1777}
1778
1779static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name)
1780{
1781 Parcel* parcel = parcelForJavaObject(env, clazz);
1782 if (parcel != NULL) {
1783 // In the current implementation, the token is just the serialized interface name that
1784 // the caller expects to be invoking
1785 const jchar* str = env->GetStringCritical(name, 0);
1786 if (str != NULL) {
1787 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
1788 env->ReleaseStringCritical(name, str);
1789 }
1790 }
1791}
1792
1793static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name)
1794{
1795 jboolean ret = JNI_FALSE;
1796
1797 Parcel* parcel = parcelForJavaObject(env, clazz);
1798 if (parcel != NULL) {
1799 const jchar* str = env->GetStringCritical(name, 0);
1800 if (str) {
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001801 IPCThreadState* threadState = IPCThreadState::self();
1802 const int32_t oldPolicy = threadState->getStrictModePolicy();
1803 const bool isValid = parcel->enforceInterface(
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001804 String16(str, env->GetStringLength(name)),
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001805 threadState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 env->ReleaseStringCritical(name, str);
1807 if (isValid) {
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001808 const int32_t newPolicy = threadState->getStrictModePolicy();
1809 if (oldPolicy != newPolicy) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001810 // Need to keep the Java-level thread-local strict
1811 // mode policy in sync for the libcore
1812 // enforcements, which involves an upcall back
1813 // into Java. (We can't modify the
1814 // Parcel.enforceInterface signature, as it's
1815 // pseudo-public, and used via AIDL
1816 // auto-generation...)
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001817 set_dalvik_blockguard_policy(env, newPolicy);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 return; // everything was correct -> return silently
1820 }
1821 }
1822 }
1823
1824 // all error conditions wind up here
1825 jniThrowException(env, "java/lang/SecurityException",
1826 "Binder invocation to an incorrect interface");
1827}
1828
1829// ----------------------------------------------------------------------------
1830
1831static const JNINativeMethod gParcelMethods[] = {
1832 {"dataSize", "()I", (void*)android_os_Parcel_dataSize},
1833 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail},
1834 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition},
1835 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity},
1836 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize},
1837 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition},
1838 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity},
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001839 {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
1840 {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative},
1842 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt},
1843 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong},
1844 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat},
1845 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble},
1846 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString},
1847 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
1848 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
1849 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray},
1850 {"readInt", "()I", (void*)android_os_Parcel_readInt},
1851 {"readLong", "()J", (void*)android_os_Parcel_readLong},
1852 {"readFloat", "()F", (void*)android_os_Parcel_readFloat},
1853 {"readDouble", "()D", (void*)android_os_Parcel_readDouble},
1854 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString},
1855 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
1856 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
1857 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001858 {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001860 {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer},
1862 {"init", "(I)V", (void*)android_os_Parcel_init},
1863 {"destroy", "()V", (void*)android_os_Parcel_destroy},
1864 {"marshall", "()[B", (void*)android_os_Parcel_marshall},
1865 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall},
1866 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom},
1867 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors},
1868 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
1869 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
1870};
1871
1872const char* const kParcelPathName = "android/os/Parcel";
1873
1874static int int_register_android_os_Parcel(JNIEnv* env)
1875{
1876 jclass clazz;
1877
1878 clazz = env->FindClass("android/util/Log");
1879 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log");
1880 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1881 gLogOffsets.mLogE = env->GetStaticMethodID(
1882 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
1883 assert(gLogOffsets.mLogE);
1884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 clazz = env->FindClass("android/os/ParcelFileDescriptor");
1886 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
1887 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1888 gParcelFileDescriptorOffsets.mConstructor
1889 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
1890
1891 clazz = env->FindClass(kParcelPathName);
1892 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
1893
1894 gParcelOffsets.mObject
1895 = env->GetFieldID(clazz, "mObject", "I");
1896 gParcelOffsets.mOwnObject
1897 = env->GetFieldID(clazz, "mOwnObject", "I");
1898
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001899 clazz = env->FindClass("android/os/StrictMode");
1900 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
1901 gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1902 gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID(
1903 clazz, "onBinderStrictModePolicyChange", "(I)V");
1904 LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
1905 "Unable to find strict mode callback.");
1906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907 return AndroidRuntime::registerNativeMethods(
1908 env, kParcelPathName,
1909 gParcelMethods, NELEM(gParcelMethods));
1910}
1911
1912int register_android_os_Binder(JNIEnv* env)
1913{
1914 if (int_register_android_os_Binder(env) < 0)
1915 return -1;
1916 if (int_register_android_os_BinderInternal(env) < 0)
1917 return -1;
1918 if (int_register_android_os_BinderProxy(env) < 0)
1919 return -1;
1920 if (int_register_android_os_Parcel(env) < 0)
1921 return -1;
1922 return 0;
1923}