android_util_Binder.cpp revision 8564c8da817a845353d213acd8636b76f567b234
115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root/*
215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Copyright (C) 2006 The Android Open Source Project
315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root *
415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * you may not use this file except in compliance with the License.
615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * You may obtain a copy of the License at
715a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root *
815a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
915a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root *
1015a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Unless required by applicable law or agreed to in writing, software
1115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
1215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * See the License for the specific language governing permissions and
1415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * limitations under the License.
1515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root */
1615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "JavaBinder"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define LOG_NDEBUG 0
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_util_Binder.h"
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h"
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/IInterface.h>
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/IPCThreadState.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
338a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#include <utils/SystemClock.h>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/List.h>
358a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#include <utils/KeyedVector.h>
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/logger.h>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/Parcel.h>
388a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#include <binder/ProcessState.h>
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/IServiceManager.h>
408a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#include <utils/threads.h>
418a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#include <utils/String8.h>
428a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ScopedUtfChars.h>
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ScopedLocalRef.h>
458a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey
468a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#include <android_runtime/AndroidRuntime.h>
478a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey
488a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey//#undef ALOGV
498a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
508a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey
518a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#define DEBUG_DEATH 0
528a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#if DEBUG_DEATH
538a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#define LOGDEATH ALOGD
548a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#else
558a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#define LOGDEATH ALOGV
568a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey#endif
578a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey
588a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkeyusing namespace android;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6015447798a38d2b5acb1998731340255f4203f294Jeff Sharkey// ----------------------------------------------------------------------------
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct bindernative_offsets_t
6385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root{
6415447798a38d2b5acb1998731340255f4203f294Jeff Sharkey    // Class state.
658a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey    jclass mClass;
6615447798a38d2b5acb1998731340255f4203f294Jeff Sharkey    jmethodID mExecTransact;
678a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey
6815447798a38d2b5acb1998731340255f4203f294Jeff Sharkey    // Object state.
69e713efcac103f3d8083ec9d5b00c528af7266b21Todd Kennedy    jfieldID mObject;
7085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root
7185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root} gBinderOffsets;
72e713efcac103f3d8083ec9d5b00c528af7266b21Todd Kennedy
73e713efcac103f3d8083ec9d5b00c528af7266b21Todd Kennedy// ----------------------------------------------------------------------------
74e713efcac103f3d8083ec9d5b00c528af7266b21Todd Kennedy
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct binderinternal_offsets_t
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Class state.
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass mClass;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jmethodID mForceGc;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gBinderInternalOffsets;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct debug_offsets_t
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Class state.
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass mClass;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gDebugOffsets;
9115447798a38d2b5acb1998731340255f4203f294Jeff Sharkey
9215447798a38d2b5acb1998731340255f4203f294Jeff Sharkey// ----------------------------------------------------------------------------
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
948a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkeystatic struct weakreference_offsets_t
958a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey{
9685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root    // Class state.
97e713efcac103f3d8083ec9d5b00c528af7266b21Todd Kennedy    jclass mClass;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jmethodID mGet;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gWeakReferenceOffsets;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct error_offsets_t
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass mClass;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gErrorOffsets;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct binderproxy_offsets_t
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Class state.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass mClass;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jmethodID mConstructor;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jmethodID mSendDeathNotice;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Object state.
11715447798a38d2b5acb1998731340255f4203f294Jeff Sharkey    jfieldID mObject;
11815447798a38d2b5acb1998731340255f4203f294Jeff Sharkey    jfieldID mSelf;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID mOrgue;
1208a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey
1218a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey} gBinderProxyOffsets;
12285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root
123e713efcac103f3d8083ec9d5b00c528af7266b21Todd Kennedystatic struct class_offsets_t
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jmethodID mGetName;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gClassOffsets;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct parcel_offsets_t
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID mObject;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID mOwnObject;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gParcelOffsets;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct log_offsets_t
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Class state.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass mClass;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jmethodID mLogE;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gLogOffsets;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14315447798a38d2b5acb1998731340255f4203f294Jeff Sharkeystatic struct parcel_file_descriptor_offsets_t
14415447798a38d2b5acb1998731340255f4203f294Jeff Sharkey{
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass mClass;
1468a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey    jmethodID mConstructor;
1478a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey} gParcelFileDescriptorOffsets;
14885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root
149e713efcac103f3d8083ec9d5b00c528af7266b21Todd Kennedystatic struct strict_mode_callback_offsets_t
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass mClass;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jmethodID mCallback;
15315447798a38d2b5acb1998731340255f4203f294Jeff Sharkey} gStrictModeCallbackOffsets;
15415447798a38d2b5acb1998731340255f4203f294Jeff Sharkey
15515447798a38d2b5acb1998731340255f4203f294Jeff Sharkey// ****************************************************************************
15615447798a38d2b5acb1998731340255f4203f294Jeff Sharkey// ****************************************************************************
15715447798a38d2b5acb1998731340255f4203f294Jeff Sharkey// ****************************************************************************
15815447798a38d2b5acb1998731340255f4203f294Jeff Sharkey
15915447798a38d2b5acb1998731340255f4203f294Jeff Sharkeystatic volatile int32_t gNumRefsCreated = 0;
16015447798a38d2b5acb1998731340255f4203f294Jeff Sharkeystatic volatile int32_t gNumProxyRefs = 0;
16115447798a38d2b5acb1998731340255f4203f294Jeff Sharkeystatic volatile int32_t gNumLocalRefs = 0;
1628a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkeystatic volatile int32_t gNumDeathRefs = 0;
1638a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey
16415447798a38d2b5acb1998731340255f4203f294Jeff Sharkeystatic void incRefsCreated(JNIEnv* env)
165e713efcac103f3d8083ec9d5b00c528af7266b21Todd Kennedy{
16615447798a38d2b5acb1998731340255f4203f294Jeff Sharkey    int old = android_atomic_inc(&gNumRefsCreated);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (old == 200) {
168        android_atomic_and(0, &gNumRefsCreated);
169        env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
170                gBinderInternalOffsets.mForceGc);
171    } else {
172        ALOGV("Now have %d binder ops", old);
173    }
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        ALOGW("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
235static 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
244class 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    {
252        ALOGV("Creating JavaBBinder %p\n", this);
253        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    {
270        ALOGV("Destroying JavaBBinder %p\n", this);
271        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
281        ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
282
283        IPCThreadState* thread_state = IPCThreadState::self();
284        const int strict_policy_before = thread_state->getStrictModePolicy();
285        thread_state->setLastTransactionBinderFlags(flags);
286
287        //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();
293
294        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
304        // 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
316        jthrowable excep2 = env->ExceptionOccurred();
317        if (excep2) {
318            report_exception(env, excep2,
319                "*** Uncaught exception in onBinderStrictModePolicyChange");
320            /* clean up JNI local ref -- we don't return to Java code */
321            env->DeleteLocalRef(excep2);
322        }
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:
345    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
346    {
347        AutoMutex _l(mLock);
348        sp<JavaBBinder> b = mBinder.promote();
349        if (b == NULL) {
350            b = new JavaBBinder(env, obj);
351            mBinder = b;
352            ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n",
353                 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
354        }
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;
367    wp<JavaBBinder> mBinder;
368};
369
370// ----------------------------------------------------------------------------
371
372// 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:
383    DeathRecipientList();
384    ~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
393class JavaDeathRecipient : public IBinder::DeathRecipient
394{
395public:
396    JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
397        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
398          mObjectWeak(NULL), mList(list)
399    {
400        // These objects manage their own lifetimes so are responsible for final bookkeeping.
401        // The list holds a strong reference to this object.
402        LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
403        list->add(this);
404
405        android_atomic_inc(&gNumDeathRefs);
406        incRefsCreated(env);
407    }
408
409    void binderDied(const wp<IBinder>& who)
410    {
411        LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
412        if (mObject != NULL) {
413            JNIEnv* env = javavm_to_jnienv(mVM);
414
415            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;
428        }
429    }
430
431    void clearReference()
432    {
433        sp<DeathRecipientList> list = mList.promote();
434        if (list != NULL) {
435            LOGDEATH("Removing JDR %p from DRL %p", this, list.get());
436            list->remove(this);
437        } else {
438            LOGDEATH("clearReference() on JDR %p but DRL wp purged", this);
439        }
440    }
441
442    bool matches(jobject obj) {
443        bool result;
444        JNIEnv* env = javavm_to_jnienv(mVM);
445
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;
454    }
455
456    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);
461            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                ALOGW("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                ALOGW("BinderProxy being destroyed; unable to get DR object name");
471                env->ExceptionClear();
472            }
473        }
474    }
475
476protected:
477    virtual ~JavaDeathRecipient()
478    {
479        //ALOGI("Removing death ref: recipient=%p\n", mObject);
480        android_atomic_dec(&gNumDeathRefs);
481        JNIEnv* env = javavm_to_jnienv(mVM);
482        if (mObject != NULL) {
483            env->DeleteGlobalRef(mObject);
484        } else {
485            env->DeleteWeakGlobalRef(mObjectWeak);
486        }
487    }
488
489private:
490    JavaVM* const mVM;
491    jobject mObject;
492    jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied()
493    wp<DeathRecipientList> mList;
494};
495
496// ----------------------------------------------------------------------------
497
498DeathRecipientList::DeathRecipientList() {
499    LOGDEATH("New DRL @ %p", this);
500}
501
502DeathRecipientList::~DeathRecipientList() {
503    LOGDEATH("Destroy DRL @ %p", this);
504    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) {
510        List< sp<JavaDeathRecipient> >::iterator iter;
511        for (iter = mList.begin(); iter != mList.end(); iter++) {
512            (*iter)->warnIfStillLive();
513        }
514    }
515}
516
517void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) {
518    AutoMutex _l(mLock);
519
520    LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get());
521    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) {
530            LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get());
531            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
549// ----------------------------------------------------------------------------
550
551namespace 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();
569        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
570        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) {
582            ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
583            return res;
584        }
585        LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
586        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) {
593        LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
594        // 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
605        // 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
610        // 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);
625        return jbh != NULL ? jbh->get(env, obj) : NULL;
626    }
627
628    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
629        return (IBinder*)
630            env->GetIntField(obj, gBinderProxyOffsets.mObject);
631    }
632
633    ALOGW("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
649jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
650{
651    return env->NewObject(
652            gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc);
653}
654
655static void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
656        bool canThrowRemoteException = false)
657{
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:
693            // DeadObjectException is a checked exception, only throw from certain methods.
694            jniThrowException(env, canThrowRemoteException
695                    ? "android/os/DeadObjectException"
696                            : "java/lang/RuntimeException", NULL);
697            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 !!!");
703            // 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);
712            break;
713        case FDS_NOT_ALLOWED:
714            jniThrowException(env, "java/lang/RuntimeException",
715                    "Not allowed to write file descriptors here");
716            break;
717        default:
718            LOGE("Unknown binder error code. 0x%x", err);
719            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;
725    }
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{
749    // 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    }
758    IPCThreadState::self()->restoreCallingIdentity(token);
759}
760
761static 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
771static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz)
772{
773    IPCThreadState::self()->flushCommands();
774}
775
776static void android_os_Binder_init(JNIEnv* env, jobject obj)
777{
778    JavaBBinderHolder* jbh = new JavaBBinderHolder();
779    if (jbh == NULL) {
780        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
781        return;
782    }
783    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
784    jbh->incStrong((void*)android_os_Binder_init);
785    env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
786}
787
788static void android_os_Binder_destroy(JNIEnv* env, jobject obj)
789{
790    JavaBBinderHolder* jbh = (JavaBBinderHolder*)
791        env->GetIntField(obj, gBinderOffsets.mObject);
792    if (jbh != NULL) {
793        env->SetIntField(obj, gBinderOffsets.mObject, 0);
794        ALOGV("Java Binder %p: removing ref on holder %p", obj, jbh);
795        jbh->decStrong((void*)android_os_Binder_init);
796    } 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.
803        ALOGV("Java Binder %p: ignoring uninitialized binder", obj);
804    }
805}
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 },
815    { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
816    { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
817    { "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
884static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env,
885        jobject clazz, jboolean disable)
886{
887    IPCThreadState::disableBackgroundScheduling(disable ? true : false);
888}
889
890static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz)
891{
892    ALOGV("Gc has executed, clearing binder ops");
893    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 },
902    { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
903    { "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) {
944        const String16& desc = target->getInterfaceDescriptor();
945        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
963static 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        ALOGW("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        ALOGW("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
1044// 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() {
1049#ifdef HAVE_GETTID
1050  return (getpid() == androidGetTid());
1051#else
1052#warning no gettid(), so not logging Binder calls...
1053  return false;
1054#endif
1055}
1056
1057static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
1058        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
1059{
1060    if (dataObj == NULL) {
1061        jniThrowNullPointerException(env, NULL);
1062        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
1081    ALOGV("Java code calling transact on %p in Java object %p with code %d\n",
1082            target, obj, code);
1083
1084    // Only log the binder call duration for things on the Java-level main thread.
1085    // But if we don't
1086    const bool time_binder_calls = should_time_binder_calls();
1087
1088    int64_t start_millis;
1089    if (time_binder_calls) {
1090        start_millis = uptimeMillis();
1091    }
1092    //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();
1095    if (time_binder_calls) {
1096        conditionally_log_binder_call(start_millis, target, code);
1097    }
1098
1099    if (err == NO_ERROR) {
1100        return JNI_TRUE;
1101    } else if (err == UNKNOWN_TRANSACTION) {
1102        return JNI_FALSE;
1103    }
1104
1105    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
1106    return JNI_FALSE;
1107}
1108
1109static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
1110        jobject recipient, jint flags) // throws RemoteException
1111{
1112    if (recipient == NULL) {
1113        jniThrowNullPointerException(env, NULL);
1114        return;
1115    }
1116
1117    IBinder* target = (IBinder*)
1118        env->GetIntField(obj, gBinderProxyOffsets.mObject);
1119    if (target == NULL) {
1120        ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
1121        assert(false);
1122    }
1123
1124    LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
1125
1126    if (!target->localBinder()) {
1127        DeathRecipientList* list = (DeathRecipientList*)
1128                env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
1129        sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);
1130        status_t err = target->linkToDeath(jdr, NULL, flags);
1131        if (err != NO_ERROR) {
1132            // Failure adding the death recipient, so clear its reference
1133            // now.
1134            jdr->clearReference();
1135            signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
1136        }
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) {
1145        jniThrowNullPointerException(env, NULL);
1146        return res;
1147    }
1148
1149    IBinder* target = (IBinder*)
1150        env->GetIntField(obj, gBinderProxyOffsets.mObject);
1151    if (target == NULL) {
1152        ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient);
1153        return JNI_FALSE;
1154    }
1155
1156    LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
1157
1158    if (!target->localBinder()) {
1159        status_t err = NAME_NOT_FOUND;
1160
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);
1165        LOGDEATH("   unlink found list %p and JDR %p", list, origJDR.get());
1166        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
1178        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*)
1192            env->GetIntField(obj, gBinderProxyOffsets.mObject);
1193    DeathRecipientList* drl = (DeathRecipientList*)
1194            env->GetIntField(obj, gBinderProxyOffsets.mOrgue);
1195
1196    LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl);
1197    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();
1203}
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);
1234
1235    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);
1252    gBinderProxyOffsets.mOrgue
1253        = env->GetFieldID(clazz, "mOrgue", "I");
1254    assert(gBinderProxyOffsets.mOrgue);
1255
1256    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
1261    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) {
1300            signalExceptionForError(env, clazz, err);
1301        }
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) {
1319            signalExceptionForError(env, clazz, err);
1320        }
1321    }
1322}
1323
1324static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
1325{
1326    Parcel* parcel = parcelForJavaObject(env, clazz);
1327    jboolean ret = JNI_TRUE;
1328    if (parcel != NULL) {
1329        ret = (jboolean)parcel->pushAllowFds(allowFds);
1330    }
1331    return ret;
1332}
1333
1334static 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
1342static 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    }
1350
1351    const status_t err = parcel->writeInt32(length);
1352    if (err != NO_ERROR) {
1353        signalExceptionForError(env, clazz, err);
1354        return;
1355    }
1356
1357    void* dest = parcel->writeInplace(length);
1358    if (dest == NULL) {
1359        signalExceptionForError(env, clazz, NO_MEMORY);
1360        return;
1361    }
1362
1363    jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
1364    if (ar) {
1365        memcpy(dest, ar + offset, length);
1366        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) {
1377            signalExceptionForError(env, clazz, err);
1378        }
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) {
1388            signalExceptionForError(env, clazz, err);
1389        }
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) {
1399            signalExceptionForError(env, clazz, err);
1400        }
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) {
1410            signalExceptionForError(env, clazz, err);
1411        }
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) {
1430            signalExceptionForError(env, clazz, err);
1431        }
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) {
1441            signalExceptionForError(env, clazz, err);
1442        }
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) {
1450        const status_t err =
1451                parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
1452        if (err != NO_ERROR) {
1453            signalExceptionForError(env, clazz, err);
1454        }
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;
1551        return jniCreateFileDescriptor(env, fd);
1552    }
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) {
1560        jniThrowNullPointerException(env, NULL);
1561        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) {
1595        jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
1596        return NULL;
1597    }
1598    jobject object = jniCreateFileDescriptor(env, fd);
1599    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) {
1608        jniThrowNullPointerException(env, NULL);
1609        return NULL;
1610    }
1611    int origfd = jniGetFDFromFileDescriptor(env, orig);
1612    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) {
1619        jniThrowIOException(env, errno);
1620        return NULL;
1621    }
1622    jobject object = jniCreateFileDescriptor(env, fd);
1623    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{
1631    if (object == NULL) {
1632        jniThrowNullPointerException(env, NULL);
1633        return;
1634    }
1635    int fd = jniGetFDFromFileDescriptor(env, object);
1636    if (fd >= 0) {
1637        jniSetFileDescriptorOfFD(env, object, -1);
1638        //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
1639        close(fd);
1640    }
1641}
1642
1643static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
1644{
1645    if (object == NULL) {
1646        jniThrowNullPointerException(env, NULL);
1647        return;
1648    }
1649    int fd = jniGetFDFromFileDescriptor(env, object);
1650    if (fd >= 0) {
1651        jniSetFileDescriptorOfFD(env, object, -1);
1652    }
1653}
1654
1655static 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            //ALOGI("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        //ALOGI("Initializing obj %p: creating new Parcel\n", clazz);
1673        own = 1;
1674        parcel = new Parcel;
1675    } else {
1676        //ALOGI("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    //ALOGI("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        //ALOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel);
1694        delete parcel;
1695    } else {
1696        env->SetIntField(clazz, gParcelOffsets.mObject, 0);
1697        //ALOGI("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
1761    status_t err = thisParcel->appendFrom(otherParcel, offset, length);
1762    if (err != NO_ERROR) {
1763        signalExceptionForError(env, clazz, err);
1764    }
1765}
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) {
1801            IPCThreadState* threadState = IPCThreadState::self();
1802            const int32_t oldPolicy = threadState->getStrictModePolicy();
1803            const bool isValid = parcel->enforceInterface(
1804                String16(str, env->GetStringLength(name)),
1805                threadState);
1806            env->ReleaseStringCritical(name, str);
1807            if (isValid) {
1808                const int32_t newPolicy = threadState->getStrictModePolicy();
1809                if (oldPolicy != newPolicy) {
1810                    // 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...)
1817                    set_dalvik_blockguard_policy(env, newPolicy);
1818                }
1819                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},
1839    {"pushAllowFds",        "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
1840    {"restoreAllowFds",     "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
1841    {"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},
1858    {"dupFileDescriptor",   "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
1859    {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
1860    {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
1861    {"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
1885    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
1899    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
1907    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}
1924