blob: e00970a2dbdef31fb7f4ceaeef8597b4ea32e65a [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
Steve Block5baa3a62011-12-20 16:23:08 +000053#define LOGDEATH ALOGD
Christopher Tate79dd31f2011-03-04 17:45:00 -080054#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 */
Steve Block3762c312012-01-06 19:20:56 +0000197 ALOGE("Unable to call Log.e()\n");
198 ALOGE("%s", msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 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 */
Steve Block8564c8d2012-01-05 23:22:43 +0000206 ALOGW("Failed trying to log exception, msg='%s'\n", msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 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);
Steve Block3762c312012-01-06 19:20:56 +0000224 ALOGE("Forcefully exiting");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 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) {
Steve Block8564c8d2012-01-05 23:22:43 +0000466 ALOGW("BinderProxy is being destroyed but the application did not call "
Christopher Tate0d4a7922011-08-30 12:09:43 -0700467 "unlinkToDeath to unlink all of its death recipients beforehand. "
468 "Releasing leaked death recipient: %s", nameUtf.c_str());
469 } else {
Steve Block8564c8d2012-01-05 23:22:43 +0000470 ALOGW("BinderProxy being destroyed; unable to get DR object name");
Christopher Tate0d4a7922011-08-30 12:09:43 -0700471 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 {
Steve Block6215d3f2012-01-04 20:05:49 +0000479 //ALOGI("Removing death ref: recipient=%p\n", mObject);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 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
Steve Block8564c8d2012-01-05 23:22:43 +0000633 ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 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:
Steve Block3762c312012-01-06 19:20:56 +0000702 ALOGE("!!! 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:
Steve Block3762c312012-01-06 19:20:56 +0000718 ALOGE("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
Amith Yamasani742a6712011-05-04 14:49:28 -0700742static jint android_os_Binder_getOrigCallingUid(JNIEnv* env, jobject clazz)
743{
744 return IPCThreadState::self()->getOrigCallingUid();
745}
746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz)
748{
749 return IPCThreadState::self()->clearCallingIdentity();
750}
751
752static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
753{
Dianne Hackborncf3004a2011-03-14 14:24:04 -0700754 // XXX temporary sanity check to debug crashes.
755 int uid = (int)(token>>32);
756 if (uid > 0 && uid < 999) {
757 // In Android currently there are no uids in this range.
758 char buf[128];
759 sprintf(buf, "Restoring bad calling ident: 0x%Lx", token);
760 jniThrowException(env, "java/lang/IllegalStateException", buf);
761 return;
762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 IPCThreadState::self()->restoreCallingIdentity(token);
764}
765
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700766static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask)
767{
768 IPCThreadState::self()->setStrictModePolicy(policyMask);
769}
770
771static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz)
772{
773 return IPCThreadState::self()->getStrictModePolicy();
774}
775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz)
777{
778 IPCThreadState::self()->flushCommands();
779}
780
Christopher Tate0b414482011-02-17 13:00:38 -0800781static void android_os_Binder_init(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782{
Christopher Tate0b414482011-02-17 13:00:38 -0800783 JavaBBinderHolder* jbh = new JavaBBinderHolder();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 if (jbh == NULL) {
785 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
786 return;
787 }
Steve Block71f2cf12011-10-20 11:56:00 +0100788 ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
Christopher Tate0b414482011-02-17 13:00:38 -0800789 jbh->incStrong((void*)android_os_Binder_init);
790 env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791}
792
Christopher Tate0b414482011-02-17 13:00:38 -0800793static void android_os_Binder_destroy(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794{
795 JavaBBinderHolder* jbh = (JavaBBinderHolder*)
Christopher Tate0b414482011-02-17 13:00:38 -0800796 env->GetIntField(obj, gBinderOffsets.mObject);
Jeff Brown582763a2010-03-24 18:56:57 -0700797 if (jbh != NULL) {
Christopher Tate0b414482011-02-17 13:00:38 -0800798 env->SetIntField(obj, gBinderOffsets.mObject, 0);
Steve Block71f2cf12011-10-20 11:56:00 +0100799 ALOGV("Java Binder %p: removing ref on holder %p", obj, jbh);
Christopher Tate0b414482011-02-17 13:00:38 -0800800 jbh->decStrong((void*)android_os_Binder_init);
Jeff Brown582763a2010-03-24 18:56:57 -0700801 } else {
802 // Encountering an uninitialized binder is harmless. All it means is that
803 // the Binder was only partially initialized when its finalizer ran and called
804 // destroy(). The Binder could be partially initialized for several reasons.
805 // For example, a Binder subclass constructor might have thrown an exception before
806 // it could delegate to its superclass's constructor. Consequently init() would
807 // not have been called and the holder pointer would remain NULL.
Steve Block71f2cf12011-10-20 11:56:00 +0100808 ALOGV("Java Binder %p: ignoring uninitialized binder", obj);
Jeff Brown582763a2010-03-24 18:56:57 -0700809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810}
811
812// ----------------------------------------------------------------------------
813
814static const JNINativeMethod gBinderMethods[] = {
815 /* name, signature, funcPtr */
816 { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
817 { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
Amith Yamasani742a6712011-05-04 14:49:28 -0700818 { "getOrigCallingUidNative", "()I", (void*)android_os_Binder_getOrigCallingUid },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
820 { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700821 { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
822 { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823 { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
824 { "init", "()V", (void*)android_os_Binder_init },
825 { "destroy", "()V", (void*)android_os_Binder_destroy }
826};
827
828const char* const kBinderPathName = "android/os/Binder";
829
830static int int_register_android_os_Binder(JNIEnv* env)
831{
832 jclass clazz;
833
834 clazz = env->FindClass(kBinderPathName);
835 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");
836
837 gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
838 gBinderOffsets.mExecTransact
839 = env->GetMethodID(clazz, "execTransact", "(IIII)Z");
840 assert(gBinderOffsets.mExecTransact);
841
842 gBinderOffsets.mObject
843 = env->GetFieldID(clazz, "mObject", "I");
844 assert(gBinderOffsets.mObject);
845
846 return AndroidRuntime::registerNativeMethods(
847 env, kBinderPathName,
848 gBinderMethods, NELEM(gBinderMethods));
849}
850
851// ****************************************************************************
852// ****************************************************************************
853// ****************************************************************************
854
855namespace android {
856
857jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz)
858{
859 return gNumLocalRefs;
860}
861
862jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
863{
864 return gNumProxyRefs;
865}
866
867jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
868{
869 return gNumDeathRefs;
870}
871
872}
873
874// ****************************************************************************
875// ****************************************************************************
876// ****************************************************************************
877
878static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
879{
880 sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
881 return javaObjectForIBinder(env, b);
882}
883
884static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz)
885{
886 sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
887 android::IPCThreadState::self()->joinThreadPool();
888}
889
Dianne Hackborn887f3552009-12-07 17:59:37 -0800890static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env,
891 jobject clazz, jboolean disable)
892{
893 IPCThreadState::disableBackgroundScheduling(disable ? true : false);
894}
895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz)
897{
Steve Block71f2cf12011-10-20 11:56:00 +0100898 ALOGV("Gc has executed, clearing binder ops");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 android_atomic_and(0, &gNumRefsCreated);
900}
901
902// ----------------------------------------------------------------------------
903
904static const JNINativeMethod gBinderInternalMethods[] = {
905 /* name, signature, funcPtr */
906 { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
907 { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
Dianne Hackborn887f3552009-12-07 17:59:37 -0800908 { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
910};
911
912const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
913
914static int int_register_android_os_BinderInternal(JNIEnv* env)
915{
916 jclass clazz;
917
918 clazz = env->FindClass(kBinderInternalPathName);
919 LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal");
920
921 gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
922 gBinderInternalOffsets.mForceGc
923 = env->GetStaticMethodID(clazz, "forceBinderGc", "()V");
924 assert(gBinderInternalOffsets.mForceGc);
925
926 return AndroidRuntime::registerNativeMethods(
927 env, kBinderInternalPathName,
928 gBinderInternalMethods, NELEM(gBinderInternalMethods));
929}
930
931// ****************************************************************************
932// ****************************************************************************
933// ****************************************************************************
934
935static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj)
936{
937 IBinder* target = (IBinder*)
938 env->GetIntField(obj, gBinderProxyOffsets.mObject);
939 if (target == NULL) {
940 return JNI_FALSE;
941 }
942 status_t err = target->pingBinder();
943 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
944}
945
946static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj)
947{
948 IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject);
949 if (target != NULL) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -0700950 const String16& desc = target->getInterfaceDescriptor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 return env->NewString(desc.string(), desc.size());
952 }
953 jniThrowException(env, "java/lang/RuntimeException",
954 "No binder found for object");
955 return NULL;
956}
957
958static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj)
959{
960 IBinder* target = (IBinder*)
961 env->GetIntField(obj, gBinderProxyOffsets.mObject);
962 if (target == NULL) {
963 return JNI_FALSE;
964 }
965 bool alive = target->isBinderAlive();
966 return alive ? JNI_TRUE : JNI_FALSE;
967}
968
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -0700969static int getprocname(pid_t pid, char *buf, size_t len) {
970 char filename[20];
971 FILE *f;
972
973 sprintf(filename, "/proc/%d/cmdline", pid);
974 f = fopen(filename, "r");
975 if (!f) { *buf = '\0'; return 1; }
976 if (!fgets(buf, len, f)) { *buf = '\0'; return 2; }
977 fclose(f);
978 return 0;
979}
980
981static bool push_eventlog_string(char** pos, const char* end, const char* str) {
982 jint len = strlen(str);
983 int space_needed = 1 + sizeof(len) + len;
984 if (end - *pos < space_needed) {
Steve Block8564c8d2012-01-05 23:22:43 +0000985 ALOGW("not enough space for string. remain=%d; needed=%d",
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -0700986 (end - *pos), space_needed);
987 return false;
988 }
989 **pos = EVENT_TYPE_STRING;
990 (*pos)++;
991 memcpy(*pos, &len, sizeof(len));
992 *pos += sizeof(len);
993 memcpy(*pos, str, len);
994 *pos += len;
995 return true;
996}
997
998static bool push_eventlog_int(char** pos, const char* end, jint val) {
999 int space_needed = 1 + sizeof(val);
1000 if (end - *pos < space_needed) {
Steve Block8564c8d2012-01-05 23:22:43 +00001001 ALOGW("not enough space for int. remain=%d; needed=%d",
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001002 (end - *pos), space_needed);
1003 return false;
1004 }
1005 **pos = EVENT_TYPE_INT;
1006 (*pos)++;
1007 memcpy(*pos, &val, sizeof(val));
1008 *pos += sizeof(val);
1009 return true;
1010}
1011
1012// From frameworks/base/core/java/android/content/EventLogTags.logtags:
1013#define LOGTAG_BINDER_OPERATION 52004
1014
1015static void conditionally_log_binder_call(int64_t start_millis,
1016 IBinder* target, jint code) {
1017 int duration_ms = static_cast<int>(uptimeMillis() - start_millis);
1018
1019 int sample_percent;
1020 if (duration_ms >= 500) {
1021 sample_percent = 100;
1022 } else {
1023 sample_percent = 100 * duration_ms / 500;
1024 if (sample_percent == 0) {
1025 return;
1026 }
1027 if (sample_percent < (random() % 100 + 1)) {
1028 return;
1029 }
1030 }
1031
1032 char process_name[40];
1033 getprocname(getpid(), process_name, sizeof(process_name));
1034 String8 desc(target->getInterfaceDescriptor());
1035
1036 char buf[LOGGER_ENTRY_MAX_PAYLOAD];
1037 buf[0] = EVENT_TYPE_LIST;
1038 buf[1] = 5;
1039 char* pos = &buf[2];
1040 char* end = &buf[LOGGER_ENTRY_MAX_PAYLOAD - 1]; // leave room for final \n
1041 if (!push_eventlog_string(&pos, end, desc.string())) return;
1042 if (!push_eventlog_int(&pos, end, code)) return;
1043 if (!push_eventlog_int(&pos, end, duration_ms)) return;
1044 if (!push_eventlog_string(&pos, end, process_name)) return;
1045 if (!push_eventlog_int(&pos, end, sample_percent)) return;
1046 *(pos++) = '\n'; // conventional with EVENT_TYPE_LIST apparently.
1047 android_bWriteLog(LOGTAG_BINDER_OPERATION, buf, pos - buf);
1048}
1049
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001050// We only measure binder call durations to potentially log them if
1051// we're on the main thread. Unfortunately sim-eng doesn't seem to
1052// have gettid, so we just ignore this and don't log if we can't
1053// get the thread id.
1054static bool should_time_binder_calls() {
Brad Fitzpatrick5348c012010-03-25 12:43:56 -07001055#ifdef HAVE_GETTID
1056 return (getpid() == androidGetTid());
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001057#else
1058#warning no gettid(), so not logging Binder calls...
1059 return false;
1060#endif
1061}
1062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
Jeff Brown0bde66a2011-11-07 12:50:08 -08001064 jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065{
1066 if (dataObj == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001067 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 return JNI_FALSE;
1069 }
1070
1071 Parcel* data = parcelForJavaObject(env, dataObj);
1072 if (data == NULL) {
1073 return JNI_FALSE;
1074 }
1075 Parcel* reply = parcelForJavaObject(env, replyObj);
1076 if (reply == NULL && replyObj != NULL) {
1077 return JNI_FALSE;
1078 }
1079
1080 IBinder* target = (IBinder*)
1081 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1082 if (target == NULL) {
1083 jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
1084 return JNI_FALSE;
1085 }
1086
Steve Block71f2cf12011-10-20 11:56:00 +01001087 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 -08001088 target, obj, code);
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001089
1090 // Only log the binder call duration for things on the Java-level main thread.
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001091 // But if we don't
1092 const bool time_binder_calls = should_time_binder_calls();
1093
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001094 int64_t start_millis;
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001095 if (time_binder_calls) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001096 start_millis = uptimeMillis();
1097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 //printf("Transact from Java code to %p sending: ", target); data->print();
1099 status_t err = target->transact(code, *data, reply, flags);
1100 //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
Brad Fitzpatrickad8fd282010-03-25 02:01:32 -07001101 if (time_binder_calls) {
Brad Fitzpatrick2c5da312010-03-24 16:14:09 -07001102 conditionally_log_binder_call(start_millis, target, code);
1103 }
1104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 if (err == NO_ERROR) {
1106 return JNI_TRUE;
1107 } else if (err == UNKNOWN_TRANSACTION) {
1108 return JNI_FALSE;
1109 }
1110
Jeff Brown0bde66a2011-11-07 12:50:08 -08001111 signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 return JNI_FALSE;
1113}
1114
1115static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
Jeff Brown0bde66a2011-11-07 12:50:08 -08001116 jobject recipient, jint flags) // throws RemoteException
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117{
1118 if (recipient == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001119 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 return;
1121 }
1122
1123 IBinder* target = (IBinder*)
1124 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1125 if (target == NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +00001126 ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 assert(false);
1128 }
1129
Christopher Tate79dd31f2011-03-04 17:45:00 -08001130 LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131
1132 if (!target->localBinder()) {
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001133 DeathRecipientList* list = (DeathRecipientList*)
1134 env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
1135 sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);
Christopher Tate0b414482011-02-17 13:00:38 -08001136 status_t err = target->linkToDeath(jdr, NULL, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 if (err != NO_ERROR) {
1138 // Failure adding the death recipient, so clear its reference
1139 // now.
1140 jdr->clearReference();
Jeff Brown0bde66a2011-11-07 12:50:08 -08001141 signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 }
1143 }
1144}
1145
1146static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
1147 jobject recipient, jint flags)
1148{
1149 jboolean res = JNI_FALSE;
1150 if (recipient == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001151 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 return res;
1153 }
1154
1155 IBinder* target = (IBinder*)
1156 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1157 if (target == NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +00001158 ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 return JNI_FALSE;
1160 }
1161
Christopher Tate79dd31f2011-03-04 17:45:00 -08001162 LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163
1164 if (!target->localBinder()) {
Christopher Tate0b414482011-02-17 13:00:38 -08001165 status_t err = NAME_NOT_FOUND;
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001166
1167 // If we find the matching recipient, proceed to unlink using that
1168 DeathRecipientList* list = (DeathRecipientList*)
1169 env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
1170 sp<JavaDeathRecipient> origJDR = list->find(recipient);
Christopher Tate79dd31f2011-03-04 17:45:00 -08001171 LOGDEATH(" unlink found list %p and JDR %p", list, origJDR.get());
Christopher Tate0b414482011-02-17 13:00:38 -08001172 if (origJDR != NULL) {
1173 wp<IBinder::DeathRecipient> dr;
1174 err = target->unlinkToDeath(origJDR, NULL, flags, &dr);
1175 if (err == NO_ERROR && dr != NULL) {
1176 sp<IBinder::DeathRecipient> sdr = dr.promote();
1177 JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get());
1178 if (jdr != NULL) {
1179 jdr->clearReference();
1180 }
1181 }
1182 }
1183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 if (err == NO_ERROR || err == DEAD_OBJECT) {
1185 res = JNI_TRUE;
1186 } else {
1187 jniThrowException(env, "java/util/NoSuchElementException",
1188 "Death link does not exist");
1189 }
1190 }
1191
1192 return res;
1193}
1194
1195static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj)
1196{
1197 IBinder* b = (IBinder*)
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001198 env->GetIntField(obj, gBinderProxyOffsets.mObject);
1199 DeathRecipientList* drl = (DeathRecipientList*)
1200 env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
Christopher Tate0b414482011-02-17 13:00:38 -08001201
Christopher Tate79dd31f2011-03-04 17:45:00 -08001202 LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl);
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001203 env->SetIntField(obj, gBinderProxyOffsets.mObject, 0);
1204 env->SetIntField(obj, gBinderProxyOffsets.mOrgue, 0);
1205 drl->decStrong((void*)javaObjectForIBinder);
1206 b->decStrong(obj);
1207
1208 IPCThreadState::self()->flushCommands();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209}
1210
1211// ----------------------------------------------------------------------------
1212
1213static const JNINativeMethod gBinderProxyMethods[] = {
1214 /* name, signature, funcPtr */
1215 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
1216 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
1217 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
1218 {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
1219 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
1220 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
1221 {"destroy", "()V", (void*)android_os_BinderProxy_destroy},
1222};
1223
1224const char* const kBinderProxyPathName = "android/os/BinderProxy";
1225
1226static int int_register_android_os_BinderProxy(JNIEnv* env)
1227{
1228 jclass clazz;
1229
1230 clazz = env->FindClass("java/lang/ref/WeakReference");
1231 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.ref.WeakReference");
1232 gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1233 gWeakReferenceOffsets.mGet
1234 = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;");
1235 assert(gWeakReferenceOffsets.mGet);
1236
1237 clazz = env->FindClass("java/lang/Error");
1238 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error");
1239 gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 clazz = env->FindClass(kBinderProxyPathName);
1242 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy");
1243
1244 gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1245 gBinderProxyOffsets.mConstructor
1246 = env->GetMethodID(clazz, "<init>", "()V");
1247 assert(gBinderProxyOffsets.mConstructor);
1248 gBinderProxyOffsets.mSendDeathNotice
1249 = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V");
1250 assert(gBinderProxyOffsets.mSendDeathNotice);
1251
1252 gBinderProxyOffsets.mObject
1253 = env->GetFieldID(clazz, "mObject", "I");
1254 assert(gBinderProxyOffsets.mObject);
1255 gBinderProxyOffsets.mSelf
1256 = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
1257 assert(gBinderProxyOffsets.mSelf);
Christopher Tatebd8b6f22011-03-01 11:55:27 -08001258 gBinderProxyOffsets.mOrgue
1259 = env->GetFieldID(clazz, "mOrgue", "I");
1260 assert(gBinderProxyOffsets.mOrgue);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261
Christopher Tate0d4a7922011-08-30 12:09:43 -07001262 clazz = env->FindClass("java/lang/Class");
1263 LOG_FATAL_IF(clazz == NULL, "Unable to find java.lang.Class");
1264 gClassOffsets.mGetName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");
1265 assert(gClassOffsets.mGetName);
1266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 return AndroidRuntime::registerNativeMethods(
1268 env, kBinderProxyPathName,
1269 gBinderProxyMethods, NELEM(gBinderProxyMethods));
1270}
1271
1272// ****************************************************************************
1273// ****************************************************************************
1274// ****************************************************************************
1275
1276static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz)
1277{
1278 Parcel* parcel = parcelForJavaObject(env, clazz);
1279 return parcel ? parcel->dataSize() : 0;
1280}
1281
1282static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz)
1283{
1284 Parcel* parcel = parcelForJavaObject(env, clazz);
1285 return parcel ? parcel->dataAvail() : 0;
1286}
1287
1288static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz)
1289{
1290 Parcel* parcel = parcelForJavaObject(env, clazz);
1291 return parcel ? parcel->dataPosition() : 0;
1292}
1293
1294static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz)
1295{
1296 Parcel* parcel = parcelForJavaObject(env, clazz);
1297 return parcel ? parcel->dataCapacity() : 0;
1298}
1299
1300static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size)
1301{
1302 Parcel* parcel = parcelForJavaObject(env, clazz);
1303 if (parcel != NULL) {
1304 const status_t err = parcel->setDataSize(size);
1305 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001306 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307 }
1308 }
1309}
1310
1311static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos)
1312{
1313 Parcel* parcel = parcelForJavaObject(env, clazz);
1314 if (parcel != NULL) {
1315 parcel->setDataPosition(pos);
1316 }
1317}
1318
1319static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size)
1320{
1321 Parcel* parcel = parcelForJavaObject(env, clazz);
1322 if (parcel != NULL) {
1323 const status_t err = parcel->setDataCapacity(size);
1324 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001325 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326 }
1327 }
1328}
1329
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001330static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001331{
1332 Parcel* parcel = parcelForJavaObject(env, clazz);
1333 jboolean ret = JNI_TRUE;
1334 if (parcel != NULL) {
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001335 ret = (jboolean)parcel->pushAllowFds(allowFds);
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001336 }
1337 return ret;
1338}
1339
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001340static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jobject clazz, jboolean lastValue)
1341{
1342 Parcel* parcel = parcelForJavaObject(env, clazz);
1343 if (parcel != NULL) {
1344 parcel->restoreAllowFds((bool)lastValue);
1345 }
1346}
1347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
1349 jobject data, jint offset,
1350 jint length)
1351{
1352 Parcel* parcel = parcelForJavaObject(env, clazz);
1353 if (parcel == NULL) {
1354 return;
1355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356
1357 const status_t err = parcel->writeInt32(length);
1358 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001359 signalExceptionForError(env, clazz, err);
1360 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 }
1362
Elliott Hughesa28b83e2011-02-28 14:26:13 -08001363 void* dest = parcel->writeInplace(length);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 if (dest == NULL) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001365 signalExceptionForError(env, clazz, NO_MEMORY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 return;
1367 }
1368
1369 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
1370 if (ar) {
Elliott Hughesa28b83e2011-02-28 14:26:13 -08001371 memcpy(dest, ar + offset, length);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
1373 }
1374}
1375
1376
1377static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
1378{
1379 Parcel* parcel = parcelForJavaObject(env, clazz);
1380 if (parcel != NULL) {
1381 const status_t err = parcel->writeInt32(val);
1382 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001383 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 }
1385 }
1386}
1387
1388static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
1389{
1390 Parcel* parcel = parcelForJavaObject(env, clazz);
1391 if (parcel != NULL) {
1392 const status_t err = parcel->writeInt64(val);
1393 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001394 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 }
1396 }
1397}
1398
1399static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
1400{
1401 Parcel* parcel = parcelForJavaObject(env, clazz);
1402 if (parcel != NULL) {
1403 const status_t err = parcel->writeFloat(val);
1404 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001405 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
1407 }
1408}
1409
1410static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val)
1411{
1412 Parcel* parcel = parcelForJavaObject(env, clazz);
1413 if (parcel != NULL) {
1414 const status_t err = parcel->writeDouble(val);
1415 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001416 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 }
1418 }
1419}
1420
1421static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val)
1422{
1423 Parcel* parcel = parcelForJavaObject(env, clazz);
1424 if (parcel != NULL) {
1425 status_t err = NO_MEMORY;
1426 if (val) {
1427 const jchar* str = env->GetStringCritical(val, 0);
1428 if (str) {
1429 err = parcel->writeString16(str, env->GetStringLength(val));
1430 env->ReleaseStringCritical(val, str);
1431 }
1432 } else {
1433 err = parcel->writeString16(NULL, 0);
1434 }
1435 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001436 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 }
1438 }
1439}
1440
1441static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
1442{
1443 Parcel* parcel = parcelForJavaObject(env, clazz);
1444 if (parcel != NULL) {
1445 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
1446 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001447 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 }
1449 }
1450}
1451
1452static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1453{
1454 Parcel* parcel = parcelForJavaObject(env, clazz);
1455 if (parcel != NULL) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001456 const status_t err =
1457 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 if (err != NO_ERROR) {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001459 signalExceptionForError(env, clazz, err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 }
1461 }
1462}
1463
1464static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz)
1465{
1466 jbyteArray ret = NULL;
1467
1468 Parcel* parcel = parcelForJavaObject(env, clazz);
1469 if (parcel != NULL) {
1470 int32_t len = parcel->readInt32();
1471
1472 // sanity check the stored length against the true data size
1473 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
1474 ret = env->NewByteArray(len);
1475
1476 if (ret != NULL) {
1477 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
1478 if (a2) {
1479 const void* data = parcel->readInplace(len);
1480 memcpy(a2, data, len);
1481 env->ReleasePrimitiveArrayCritical(ret, a2, 0);
1482 }
1483 }
1484 }
1485 }
1486
1487 return ret;
1488}
1489
1490static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz)
1491{
1492 Parcel* parcel = parcelForJavaObject(env, clazz);
1493 if (parcel != NULL) {
1494 return parcel->readInt32();
1495 }
1496 return 0;
1497}
1498
1499static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz)
1500{
1501 Parcel* parcel = parcelForJavaObject(env, clazz);
1502 if (parcel != NULL) {
1503 return parcel->readInt64();
1504 }
1505 return 0;
1506}
1507
1508static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz)
1509{
1510 Parcel* parcel = parcelForJavaObject(env, clazz);
1511 if (parcel != NULL) {
1512 return parcel->readFloat();
1513 }
1514 return 0;
1515}
1516
1517static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz)
1518{
1519 Parcel* parcel = parcelForJavaObject(env, clazz);
1520 if (parcel != NULL) {
1521 return parcel->readDouble();
1522 }
1523 return 0;
1524}
1525
1526static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz)
1527{
1528 Parcel* parcel = parcelForJavaObject(env, clazz);
1529 if (parcel != NULL) {
1530 size_t len;
1531 const char16_t* str = parcel->readString16Inplace(&len);
1532 if (str) {
1533 return env->NewString(str, len);
1534 }
1535 return NULL;
1536 }
1537 return NULL;
1538}
1539
1540static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
1541{
1542 Parcel* parcel = parcelForJavaObject(env, clazz);
1543 if (parcel != NULL) {
1544 return javaObjectForIBinder(env, parcel->readStrongBinder());
1545 }
1546 return NULL;
1547}
1548
1549static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz)
1550{
1551 Parcel* parcel = parcelForJavaObject(env, clazz);
1552 if (parcel != NULL) {
1553 int fd = parcel->readFileDescriptor();
1554 if (fd < 0) return NULL;
1555 fd = dup(fd);
1556 if (fd < 0) return NULL;
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001557 return jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 }
1559 return NULL;
1560}
1561
1562static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz,
1563 jstring name, jint mode)
1564{
1565 if (name == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001566 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 return NULL;
1568 }
1569 const jchar* str = env->GetStringCritical(name, 0);
1570 if (str == NULL) {
1571 // Whatever, whatever.
1572 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1573 return NULL;
1574 }
1575 String8 name8(str, env->GetStringLength(name));
1576 env->ReleaseStringCritical(name, str);
1577 int flags=0;
1578 switch (mode&0x30000000) {
1579 case 0:
1580 case 0x10000000:
1581 flags = O_RDONLY;
1582 break;
1583 case 0x20000000:
1584 flags = O_WRONLY;
1585 break;
1586 case 0x30000000:
1587 flags = O_RDWR;
1588 break;
1589 }
1590
1591 if (mode&0x08000000) flags |= O_CREAT;
1592 if (mode&0x04000000) flags |= O_TRUNC;
1593 if (mode&0x02000000) flags |= O_APPEND;
1594
1595 int realMode = S_IRWXU|S_IRWXG;
1596 if (mode&0x00000001) realMode |= S_IROTH;
1597 if (mode&0x00000002) realMode |= S_IWOTH;
1598
1599 int fd = open(name8.string(), flags, realMode);
1600 if (fd < 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001601 jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
1602 return NULL;
1603 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001604 jobject object = jniCreateFileDescriptor(env, fd);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001605 if (object == NULL) {
1606 close(fd);
1607 }
1608 return object;
1609}
1610
1611static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jobject clazz, jobject orig)
1612{
1613 if (orig == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001614 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001615 return NULL;
1616 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001617 int origfd = jniGetFDFromFileDescriptor(env, orig);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001618 if (origfd < 0) {
1619 jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
1620 return NULL;
1621 }
1622
1623 int fd = dup(origfd);
1624 if (fd < 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001625 jniThrowIOException(env, errno);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 return NULL;
1627 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001628 jobject object = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 if (object == NULL) {
1630 close(fd);
1631 }
1632 return object;
1633}
1634
1635static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1636{
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001637 if (object == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001638 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001639 return;
1640 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001641 int fd = jniGetFDFromFileDescriptor(env, object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 if (fd >= 0) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001643 jniSetFileDescriptorOfFD(env, object, -1);
Steve Block6215d3f2012-01-04 20:05:49 +00001644 //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 close(fd);
1646 }
1647}
1648
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001649static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1650{
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001651 if (object == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001652 jniThrowNullPointerException(env, NULL);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001653 return;
1654 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001655 int fd = jniGetFDFromFileDescriptor(env, object);
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001656 if (fd >= 0) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -07001657 jniSetFileDescriptorOfFD(env, object, -1);
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001658 }
1659}
1660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz)
1662{
1663 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
1664 if (own) {
1665 Parcel* parcel = parcelForJavaObject(env, clazz);
1666 if (parcel != NULL) {
Steve Block6215d3f2012-01-04 20:05:49 +00001667 //ALOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 parcel->freeData();
1669 }
1670 }
1671}
1672
1673static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt)
1674{
1675 Parcel* parcel = (Parcel*)parcelInt;
1676 int own = 0;
1677 if (!parcel) {
Steve Block6215d3f2012-01-04 20:05:49 +00001678 //ALOGI("Initializing obj %p: creating new Parcel\n", clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 own = 1;
1680 parcel = new Parcel;
1681 } else {
Steve Block6215d3f2012-01-04 20:05:49 +00001682 //ALOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 }
1684 if (parcel == NULL) {
1685 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1686 return;
1687 }
Steve Block6215d3f2012-01-04 20:05:49 +00001688 //ALOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own);
1690 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel);
1691}
1692
1693static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz)
1694{
1695 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
1696 if (own) {
1697 Parcel* parcel = parcelForJavaObject(env, clazz);
1698 env->SetIntField(clazz, gParcelOffsets.mObject, 0);
Steve Block6215d3f2012-01-04 20:05:49 +00001699 //ALOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 delete parcel;
1701 } else {
1702 env->SetIntField(clazz, gParcelOffsets.mObject, 0);
Steve Block6215d3f2012-01-04 20:05:49 +00001703 //ALOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 }
1705}
1706
1707static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz)
1708{
1709 Parcel* parcel = parcelForJavaObject(env, clazz);
1710 if (parcel == NULL) {
1711 return NULL;
1712 }
1713
1714 // do not marshall if there are binder objects in the parcel
1715 if (parcel->objectsCount())
1716 {
1717 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
1718 return NULL;
1719 }
1720
1721 jbyteArray ret = env->NewByteArray(parcel->dataSize());
1722
1723 if (ret != NULL)
1724 {
1725 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
1726 if (array != NULL)
1727 {
1728 memcpy(array, parcel->data(), parcel->dataSize());
1729 env->ReleasePrimitiveArrayCritical(ret, array, 0);
1730 }
1731 }
1732
1733 return ret;
1734}
1735
1736static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length)
1737{
1738 Parcel* parcel = parcelForJavaObject(env, clazz);
1739 if (parcel == NULL || length < 0) {
1740 return;
1741 }
1742
1743 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
1744 if (array)
1745 {
1746 parcel->setDataSize(length);
1747 parcel->setDataPosition(0);
1748
1749 void* raw = parcel->writeInplace(length);
1750 memcpy(raw, (array + offset), length);
1751
1752 env->ReleasePrimitiveArrayCritical(data, array, 0);
1753 }
1754}
1755
1756static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length)
1757{
1758 Parcel* thisParcel = parcelForJavaObject(env, clazz);
1759 if (thisParcel == NULL) {
1760 return;
1761 }
1762 Parcel* otherParcel = parcelForJavaObject(env, parcel);
1763 if (otherParcel == NULL) {
1764 return;
1765 }
1766
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001767 status_t err = thisParcel->appendFrom(otherParcel, offset, length);
1768 if (err != NO_ERROR) {
1769 signalExceptionForError(env, clazz, err);
1770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771}
1772
1773static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
1774{
1775 jboolean ret = JNI_FALSE;
1776 Parcel* parcel = parcelForJavaObject(env, clazz);
1777 if (parcel != NULL) {
1778 if (parcel->hasFileDescriptors()) {
1779 ret = JNI_TRUE;
1780 }
1781 }
1782 return ret;
1783}
1784
1785static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name)
1786{
1787 Parcel* parcel = parcelForJavaObject(env, clazz);
1788 if (parcel != NULL) {
1789 // In the current implementation, the token is just the serialized interface name that
1790 // the caller expects to be invoking
1791 const jchar* str = env->GetStringCritical(name, 0);
1792 if (str != NULL) {
1793 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
1794 env->ReleaseStringCritical(name, str);
1795 }
1796 }
1797}
1798
1799static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name)
1800{
1801 jboolean ret = JNI_FALSE;
1802
1803 Parcel* parcel = parcelForJavaObject(env, clazz);
1804 if (parcel != NULL) {
1805 const jchar* str = env->GetStringCritical(name, 0);
1806 if (str) {
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001807 IPCThreadState* threadState = IPCThreadState::self();
1808 const int32_t oldPolicy = threadState->getStrictModePolicy();
1809 const bool isValid = parcel->enforceInterface(
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001810 String16(str, env->GetStringLength(name)),
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001811 threadState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 env->ReleaseStringCritical(name, str);
1813 if (isValid) {
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001814 const int32_t newPolicy = threadState->getStrictModePolicy();
1815 if (oldPolicy != newPolicy) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001816 // Need to keep the Java-level thread-local strict
1817 // mode policy in sync for the libcore
1818 // enforcements, which involves an upcall back
1819 // into Java. (We can't modify the
1820 // Parcel.enforceInterface signature, as it's
1821 // pseudo-public, and used via AIDL
1822 // auto-generation...)
Brad Fitzpatrick7bcad8a32010-07-27 09:49:11 -07001823 set_dalvik_blockguard_policy(env, newPolicy);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 return; // everything was correct -> return silently
1826 }
1827 }
1828 }
1829
1830 // all error conditions wind up here
1831 jniThrowException(env, "java/lang/SecurityException",
1832 "Binder invocation to an incorrect interface");
1833}
1834
1835// ----------------------------------------------------------------------------
1836
1837static const JNINativeMethod gParcelMethods[] = {
1838 {"dataSize", "()I", (void*)android_os_Parcel_dataSize},
1839 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail},
1840 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition},
1841 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity},
1842 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize},
1843 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition},
1844 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity},
Dianne Hackbornc04db7e2011-10-03 21:09:35 -07001845 {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
1846 {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative},
1848 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt},
1849 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong},
1850 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat},
1851 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble},
1852 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString},
1853 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
1854 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
1855 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray},
1856 {"readInt", "()I", (void*)android_os_Parcel_readInt},
1857 {"readLong", "()J", (void*)android_os_Parcel_readLong},
1858 {"readFloat", "()F", (void*)android_os_Parcel_readFloat},
1859 {"readDouble", "()D", (void*)android_os_Parcel_readDouble},
1860 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString},
1861 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
1862 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
1863 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001864 {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
Dianne Hackbornc9119f52011-02-28 18:03:26 -08001866 {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer},
1868 {"init", "(I)V", (void*)android_os_Parcel_init},
1869 {"destroy", "()V", (void*)android_os_Parcel_destroy},
1870 {"marshall", "()[B", (void*)android_os_Parcel_marshall},
1871 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall},
1872 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom},
1873 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors},
1874 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
1875 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
1876};
1877
1878const char* const kParcelPathName = "android/os/Parcel";
1879
1880static int int_register_android_os_Parcel(JNIEnv* env)
1881{
1882 jclass clazz;
1883
1884 clazz = env->FindClass("android/util/Log");
1885 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log");
1886 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1887 gLogOffsets.mLogE = env->GetStaticMethodID(
1888 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
1889 assert(gLogOffsets.mLogE);
1890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 clazz = env->FindClass("android/os/ParcelFileDescriptor");
1892 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
1893 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1894 gParcelFileDescriptorOffsets.mConstructor
1895 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
1896
1897 clazz = env->FindClass(kParcelPathName);
1898 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
1899
1900 gParcelOffsets.mObject
1901 = env->GetFieldID(clazz, "mObject", "I");
1902 gParcelOffsets.mOwnObject
1903 = env->GetFieldID(clazz, "mOwnObject", "I");
1904
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001905 clazz = env->FindClass("android/os/StrictMode");
1906 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
1907 gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
1908 gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID(
1909 clazz, "onBinderStrictModePolicyChange", "(I)V");
1910 LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
1911 "Unable to find strict mode callback.");
1912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 return AndroidRuntime::registerNativeMethods(
1914 env, kParcelPathName,
1915 gParcelMethods, NELEM(gParcelMethods));
1916}
1917
1918int register_android_os_Binder(JNIEnv* env)
1919{
1920 if (int_register_android_os_Binder(env) < 0)
1921 return -1;
1922 if (int_register_android_os_BinderInternal(env) < 0)
1923 return -1;
1924 if (int_register_android_os_BinderProxy(env) < 0)
1925 return -1;
1926 if (int_register_android_os_Parcel(env) < 0)
1927 return -1;
1928 return 0;
1929}