static jboolean PackageRedirectionMap_writeToParcel(JNIEnv* env, jobject clazz,
														PackageRedirectionMap* resMap, jobject parcel)
	{
		if (parcel == NULL) {
			return JNI_FALSE;
		}
		
		Parcel* p = parcelForJavaObject(env, parcel);
		
		int package = resMap->getPackage();
		size_t nTypes = resMap->getNumberOfTypes();
		size_t entryCount = 0;
		for (size_t type=0; type<nTypes; type++) {
			entryCount += resMap->getNumberOfUsedEntries(type);
		}
		p->writeInt32(entryCount);
		for (size_t type=0; type<nTypes; type++) {
			size_t nEntries = resMap->getNumberOfEntries(type);
			for (size_t entry=0; entry<nEntries; entry++) {
				uint32_t toIdent = resMap->getEntry(type, entry);
				if (toIdent != 0) {
					uint32_t fromIdent = Res_MAKEID(package-1, type, entry);
					p->writeInt32(fromIdent);
					p->writeInt32(toIdent);
				}
			}
		}
		
		return JNI_TRUE;
	}
static void android_view_InputChannel_nativeReadFromParcel(JNIEnv* env, jobject obj,
        jobject parcelObj) {
    if (android_view_InputChannel_getNativeInputChannel(env, obj) != NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
                "This object already has a native input channel.");
        return;
    }

    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (parcel) {
        bool isInitialized = parcel->readInt32();
        if (isInitialized) {
            String8 name = parcel->readString8();
            int rawFd = parcel->readFileDescriptor();
            int dupFd = dup(rawFd);
            if (dupFd < 0) {
                ALOGE("Error %d dup channel fd %d.", errno, rawFd);
                jniThrowRuntimeException(env,
                        "Could not read input channel file descriptors from parcel.");
                return;
            }

            InputChannel* inputChannel = new InputChannel(name.string(), dupFd);
            NativeInputChannel* nativeInputChannel = new NativeInputChannel(inputChannel);

            android_view_InputChannel_setNativeInputChannel(env, obj, nativeInputChannel);
        }
    }
}
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (parcel == NULL) {
        doThrowNPE(env);
        return 0;
    }

    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    sp<IBinder> binder(parcel->readStrongBinder());

    // update the Surface only if the underlying IGraphicBufferProducer
    // has changed.
    if (self != NULL
            && (self->getIGraphicBufferProducer()->asBinder() == binder)) {
        // same IGraphicBufferProducer, return ourselves
        return jlong(self.get());
    }

    sp<Surface> sur;
    sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder));
    if (gbp != NULL) {
        // we have a new IGraphicBufferProducer, create a new Surface for it
        sur = new Surface(gbp, true);
        // and keep a reference before passing to java
        sur->incStrong(&sRefBaseOwner);
    }

    if (self != NULL) {
        // and loose the java reference to ourselves
        self->decStrong(&sRefBaseOwner);
    }

    return jlong(sur.get());
}
static void nativeWriteToParcel(JNIEnv* env, jobject clazz, jlong ptr, jobject parcelObj) {
    NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (parcel) {
        parcel->writeInt32(map->getDeviceId());
        map->getMap()->writeToParcel(parcel);
    }
}
static void android_view_GraphiceBuffer_write(JNIEnv* env, jobject clazz,
        jlong wrapperHandle, jobject dest) {
    GraphicBufferWrapper* wrapper =
                reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
    Parcel* parcel = parcelForJavaObject(env, dest);
    if (parcel) {
        parcel->write(*wrapper->buffer);
    }
}
static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz,
        jint nativePtr, jobject parcelObj) {
    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
    Parcel* parcel = parcelForJavaObject(env, parcelObj);

    status_t status = event->writeToParcel(parcel);
    if (status) {
        jniThrowRuntimeException(env, "Failed to write MotionEvent parcel.");
    }
}
static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (parcel == NULL) {
        doThrowNPE(env);
        return;
    }
    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    parcel->writeStrongBinder( self != 0 ? self->getIGraphicBufferProducer()->asBinder() : NULL);
}
static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jlong windowPtr,
        jobject parcelObj) {
    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
    Parcel* parcel = parcelForJavaObject(env, parcelObj);

    status_t status = window->writeToParcel(parcel);
    if (status) {
        String8 msg;
        msg.appendFormat("Could not write CursorWindow to Parcel due to error %d.", status);
        jniThrowRuntimeException(env, msg.string());
    }
}
static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jint windowPtr,
        jobject parcelObj) {
    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
    Parcel* parcel = parcelForJavaObject(env, parcelObj);

    status_t status = window->writeToParcel(parcel);
    if (status) {
    	char buf[100];
		snprintf(buf, sizeof(buf), "Could not write CursorWindow to Parcel due to error %d.", status);
		jniThrowException(env, "java/lang/IllegalStateException", buf);
    }
}
static jlong android_view_GraphiceBuffer_read(JNIEnv* env, jobject clazz,
        jobject in) {

    Parcel* parcel = parcelForJavaObject(env, in);
    if (parcel) {
        sp<GraphicBuffer> buffer = new GraphicBuffer();
        parcel->read(*buffer);
        return reinterpret_cast<jlong>(new GraphicBufferWrapper(buffer));
    }

    return NULL;
}
static jint nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);

    CursorWindow* window;
    status_t status = CursorWindow::createFromParcel(parcel, &window);
    if (status || !window) {
        LOGE("Could not create CursorWindow from Parcel due to error %d.", status);
        return 0;
    }

    LOG_WINDOW("nativeInitializeFromBinder: numRows = %d, numColumns = %d, window = %p",
            window->getNumRows(), window->getNumColumns(), window);
    return reinterpret_cast<jint>(window);
}
static void android_view_InputChannel_nativeWriteToParcel(JNIEnv* env, jobject obj,
        jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (parcel) {
        NativeInputChannel* nativeInputChannel =
                android_view_InputChannel_getNativeInputChannel(env, obj);
        if (nativeInputChannel) {
            sp<InputChannel> inputChannel = nativeInputChannel->getInputChannel();

            parcel->writeInt32(1);
            parcel->writeString8(String8(inputChannel->getName().c_str()));
            parcel->writeDupFileDescriptor(inputChannel->getFd());
        } else {
            parcel->writeInt32(0);
        }
    }
}
static void android_view_InputChannel_nativeReadFromParcel(JNIEnv* env, jobject obj,
        jobject parcelObj) {
    if (android_view_InputChannel_getNativeInputChannel(env, obj) != NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
                "This object already has a native input channel.");
        return;
    }

    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (parcel) {
        bool isInitialized = parcel->readInt32();
        if (isInitialized) {
            String8 name = parcel->readString8();
            int32_t parcelAshmemFd = parcel->readFileDescriptor();
            int32_t ashmemFd = dup(parcelAshmemFd);
            if (ashmemFd < 0) {
                ALOGE("Error %d dup ashmem fd %d.", errno, parcelAshmemFd);
            }
            int32_t parcelReceivePipeFd = parcel->readFileDescriptor();
            int32_t receivePipeFd = dup(parcelReceivePipeFd);
            if (receivePipeFd < 0) {
                ALOGE("Error %d dup receive pipe fd %d.", errno, parcelReceivePipeFd);
            }
            int32_t parcelSendPipeFd = parcel->readFileDescriptor();
            int32_t sendPipeFd = dup(parcelSendPipeFd);
            if (sendPipeFd < 0) {
                ALOGE("Error %d dup send pipe fd %d.", errno, parcelSendPipeFd);
            }
            if (ashmemFd < 0 || receivePipeFd < 0 || sendPipeFd < 0) {
                if (ashmemFd >= 0) ::close(ashmemFd);
                if (receivePipeFd >= 0) ::close(receivePipeFd);
                if (sendPipeFd >= 0) ::close(sendPipeFd);
                jniThrowRuntimeException(env,
                        "Could not read input channel file descriptors from parcel.");
                return;
            }

            InputChannel* inputChannel = new InputChannel(name, ashmemFd,
                    receivePipeFd, sendPipeFd);
            NativeInputChannel* nativeInputChannel = new NativeInputChannel(inputChannel);

            android_view_InputChannel_setNativeInputChannel(env, obj, nativeInputChannel);
        }
    }
}
static jlong nativeReadFromParcel(JNIEnv *env, jobject clazz, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (!parcel) {
        return 0;
    }

    int32_t deviceId = parcel->readInt32();
    if (parcel->errorCheck()) {
        return 0;
    }

    sp<KeyCharacterMap> kcm = KeyCharacterMap::readFromParcel(parcel);
    if (!kcm.get()) {
        return 0;
    }

    NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId, kcm);
    return reinterpret_cast<jlong>(map);
}
	static PackageRedirectionMap* PackageRedirectionMap_createFromParcel(JNIEnv* env, jobject clazz,
																		 jobject parcel)
	{
		if (parcel == NULL) {
			return NULL;
		}
		
		Parcel* p = parcelForJavaObject(env, parcel);
		PackageRedirectionMap* resMap = new PackageRedirectionMap;
		
		int32_t entryCount = p->readInt32();
		while (entryCount-- > 0) {
			uint32_t fromIdent = (uint32_t)p->readInt32();
			uint32_t toIdent = (uint32_t)p->readInt32();
			resMap->addRedirection(fromIdent, toIdent);
		}
		
		return resMap;
	}
static jint android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz,
        jint nativePtr, jobject parcelObj) {
    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
    if (!event) {
        event = new MotionEvent();
    }

    Parcel* parcel = parcelForJavaObject(env, parcelObj);

    status_t status = event->readFromParcel(parcel);
    if (status) {
        if (!nativePtr) {
            delete event;
        }
        jniThrowRuntimeException(env, "Failed to read MotionEvent parcel.");
        return 0;
    }
    return reinterpret_cast<jint>(event);
}
void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
                            const Parcel *obj)
{
    jint jeventType;

    // translate DrmPlugin event types into their java equivalents
    switch(eventType) {
        case DrmPlugin::kDrmPluginEventProvisionRequired:
            jeventType = gEventTypes.kEventProvisionRequired;
            break;
        case DrmPlugin::kDrmPluginEventKeyNeeded:
            jeventType = gEventTypes.kEventKeyRequired;
            break;
        case DrmPlugin::kDrmPluginEventKeyExpired:
            jeventType = gEventTypes.kEventKeyExpired;
            break;
        case DrmPlugin::kDrmPluginEventVendorDefined:
            jeventType = gEventTypes.kEventVendorDefined;
            break;
        default:
            ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
            return;
    }

    JNIEnv *env = AndroidRuntime::getJNIEnv();
    if (obj && obj->dataSize() > 0) {
        jobject jParcel = createJavaParcelObject(env);
        if (jParcel != NULL) {
            Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
            nativeParcel->setData(obj->data(), obj->dataSize());
            env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
                    jeventType, extra, jParcel);
            env->DeleteLocalRef(jParcel);
        }
    }

    if (env->ExceptionCheck()) {
        ALOGW("An exception occurred while notifying an event.");
        LOGW_EX(env);
        env->ExceptionClear();
    }
}