/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "android_drm_DrmManagerClient"
#include <utils/Log.h>

#include <jni.h>
#include <JNIHelp.h>
#include <ScopedLocalRef.h>
#include <android_runtime/AndroidRuntime.h>

#include <drm/DrmInfo.h>
#include <drm/DrmRights.h>
#include <drm/DrmInfoEvent.h>
#include <drm/DrmInfoStatus.h>
#include <drm/DrmInfoRequest.h>
#include <drm/DrmSupportInfo.h>
#include <drm/DrmConstraints.h>
#include <drm/DrmMetadata.h>
#include <drm/DrmConvertedStatus.h>
#include <drm/drm_framework_common.h>

#include <DrmManagerClientImpl.h>

using namespace android;

/**
 * Utility class used to extract the value from the provided java object.
 * May need to add some utility function to create java object.
 */
class Utility {
public:
    static String8 getStringValue(JNIEnv* env, jobject object, const char* fieldName);

    static char* getByteArrayValue(
            JNIEnv* env, jobject object, const char* fieldName, int* dataLength);

    static char* getByteArrayValue(
            JNIEnv* env, jbyteArray byteArray, int* dataLength);

    static String8 getStringValue(JNIEnv* env, jstring string);

    static int getIntValue(JNIEnv* env, jobject object, const char* fieldName);
};

String8 Utility::getStringValue(JNIEnv* env, jobject object, const char* fieldName) {
    /* Look for the instance field with the name fieldName */
    jfieldID fieldID
        = env->GetFieldID(env->GetObjectClass(object), fieldName , "Ljava/lang/String;");

    if (NULL != fieldID) {
        jstring valueString = (jstring) env->GetObjectField(object, fieldID);
        return Utility::getStringValue(env, valueString);
    }

    String8 dataString("");
    return dataString;
}

String8 Utility::getStringValue(JNIEnv* env, jstring string) {
    String8 dataString("");

    if (NULL != string && string != env->NewStringUTF("")) {
        char* bytes = const_cast< char* > (env->GetStringUTFChars(string, NULL));

        const int length = strlen(bytes) + 1;
        char *data = new char[length];
        strncpy(data, bytes, length);
        dataString = String8(data);

        env->ReleaseStringUTFChars(string, bytes);
        delete [] data; data = NULL;
    }
    return dataString;
}

char* Utility::getByteArrayValue(
            JNIEnv* env, jobject object, const char* fieldName, int* dataLength) {

    *dataLength = 0;

    jfieldID fieldID = env->GetFieldID(env->GetObjectClass(object), fieldName , "[B");

    if (NULL != fieldID) {
        jbyteArray byteArray = (jbyteArray) env->GetObjectField(object, fieldID);
        return Utility::getByteArrayValue(env, byteArray, dataLength);
    }
    return NULL;
}

char* Utility::getByteArrayValue(JNIEnv* env, jbyteArray byteArray, int* dataLength) {
    char* data = NULL;
    if (NULL != byteArray) {
        jint length = env->GetArrayLength(byteArray);

        *dataLength = length;
        if (0 < *dataLength) {
            data = new char[length];
            env->GetByteArrayRegion(byteArray, (jint)0, length, (jbyte *) data);
        }
    }
    return data;
}

int Utility::getIntValue(JNIEnv* env, jobject object, const char* fieldName) {
    jfieldID fieldID;
    int intValue = -1;

    /* Get a reference to obj’s class */
    jclass clazz = env->GetObjectClass(object);
    /* Look for the instance field with the name fieldName */
    fieldID = env->GetFieldID(clazz, fieldName , "I");

    if (NULL != fieldID) {
        intValue = (int) env->GetIntField(object, fieldID);
    }

    return intValue;
}

class JNIOnInfoListener : public DrmManagerClient::OnInfoListener {
public:
    JNIOnInfoListener(JNIEnv* env, jobject thiz, jobject weak_thiz);

    virtual ~JNIOnInfoListener();
    void onInfo(const DrmInfoEvent& event);

private:
    JNIOnInfoListener();
    jclass mClass;
    jobject mObject;
};

JNIOnInfoListener::JNIOnInfoListener(JNIEnv* env, jobject thiz, jobject weak_thiz) {
    jclass clazz = env->GetObjectClass(thiz);

    if (clazz == NULL) {
        ALOGE("Can't find android/drm/DrmManagerClient");
        jniThrowException(env, "java/lang/Exception", NULL);
        return;
    }
    mClass = (jclass)env->NewGlobalRef(clazz);
    mObject  = env->NewGlobalRef(weak_thiz);
}

JNIOnInfoListener::~JNIOnInfoListener() {
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    env->DeleteGlobalRef(mObject);
    env->DeleteGlobalRef(mClass);
}

void JNIOnInfoListener::onInfo(const DrmInfoEvent& event) {
    jint uniqueId = event.getUniqueId();
    jint type = event.getType();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jstring message = env->NewStringUTF(event.getMessage().string());
    ALOGV("JNIOnInfoListener::onInfo => %d | %d | %s", uniqueId, type, event.getMessage().string());

    env->CallStaticVoidMethod(
            mClass,
            env->GetStaticMethodID(mClass, "notify", "(Ljava/lang/Object;IILjava/lang/String;)V"),
            mObject, uniqueId, type, message);
}

static Mutex sLock;

static sp<DrmManagerClientImpl> setDrmManagerClientImpl(
            JNIEnv* env, jobject thiz, const sp<DrmManagerClientImpl>& client) {
    Mutex::Autolock l(sLock);
    jclass clazz = env->FindClass("android/drm/DrmManagerClient");
    jfieldID fieldId = env->GetFieldID(clazz, "mNativeContext", "J");

    jlong oldHandle = env->GetLongField(thiz, fieldId);
    sp<DrmManagerClientImpl> old = reinterpret_cast<DrmManagerClientImpl*>(oldHandle);
    if (client.get()) {
        client->incStrong(thiz);
    }
    if (old != 0) {
        old->decStrong(thiz);
    }
    env->SetLongField(thiz, fieldId, reinterpret_cast<jlong>(client.get()));
    return old;
}

static sp<DrmManagerClientImpl> getDrmManagerClientImpl(JNIEnv* env, jobject thiz) {
    Mutex::Autolock l(sLock);
    jclass clazz = env->FindClass("android/drm/DrmManagerClient");
    jfieldID fieldId = env->GetFieldID(clazz, "mNativeContext", "J");

    jlong clientHandle = env->GetLongField(thiz, fieldId);
    DrmManagerClientImpl* const client = reinterpret_cast<DrmManagerClientImpl*>(clientHandle);
    return sp<DrmManagerClientImpl>(client);
}

static jint android_drm_DrmManagerClient_initialize(
        JNIEnv* env, jobject thiz) {
    ALOGV("initialize - Enter");

    int uniqueId = 0;
    sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId, false);
    drmManager->addClient(uniqueId);

    setDrmManagerClientImpl(env, thiz, drmManager);
    ALOGV("initialize - Exit");
    return static_cast<jint>(uniqueId);
}

static void android_drm_DrmManagerClient_setListeners(
        JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) {
    ALOGV("setListeners - Enter");

    // Set the listener to DrmManager
    sp<DrmManagerClient::OnInfoListener> listener = new JNIOnInfoListener(env, thiz, weak_thiz);
    getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, listener);

    ALOGV("setListeners - Exit");
}

static void android_drm_DrmManagerClient_release(
        JNIEnv* env, jobject thiz, jint uniqueId) {
    ALOGV("release - Enter");
    getDrmManagerClientImpl(env, thiz)->remove(uniqueId);
    getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, NULL);

    sp<DrmManagerClientImpl> oldClient = setDrmManagerClientImpl(env, thiz, NULL);
    if (oldClient != NULL) {
        oldClient->setOnInfoListener(uniqueId, NULL);
        oldClient->removeClient(uniqueId);
    }
    ALOGV("release - Exit");
}

static jobject android_drm_DrmManagerClient_getConstraintsFromContent(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring jpath, jint usage) {
    ALOGV("GetConstraints - Enter");

    const String8 pathString = Utility::getStringValue(env, jpath);
    DrmConstraints* pConstraints
        = getDrmManagerClientImpl(env, thiz)->getConstraints(uniqueId, &pathString, usage);

    jclass localRef = env->FindClass("android/content/ContentValues");
    jmethodID ContentValues_putByteArray =
            env->GetMethodID(localRef, "put", "(Ljava/lang/String;[B)V");
    jmethodID ContentValues_putString =
            env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V");
    jmethodID ContentValues_constructor = env->GetMethodID(localRef, "<init>", "()V");
    jobject constraints = NULL;

    if (NULL != localRef && NULL != pConstraints) {
        // create the java DrmConstraints object
        constraints = env->NewObject(localRef, ContentValues_constructor);

        DrmConstraints::KeyIterator keyIt = pConstraints->keyIterator();
        while (keyIt.hasNext()) {
            String8 key = keyIt.next();

            // insert the entry<constraintKey, constraintValue> to newly created java object
            if (DrmConstraints::EXTENDED_METADATA == key) {
                const char* value = pConstraints->getAsByteArray(&key);
                if (NULL != value) {
                    ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(strlen(value)));
                    ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
                    env->SetByteArrayRegion(dataArray.get(), 0, strlen(value), (jbyte*)value);
                    env->CallVoidMethod(constraints, ContentValues_putByteArray,
                                        keyString.get(), dataArray.get());
                }
            } else {
                String8 value = pConstraints->get(key);
                ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
                ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
                env->CallVoidMethod(constraints, ContentValues_putString,
                                    keyString.get(), valueString.get());
            }
        }
    }

    delete pConstraints; pConstraints = NULL;
    ALOGV("GetConstraints - Exit");
    return constraints;
}

static jobject android_drm_DrmManagerClient_getMetadataFromContent(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring jpath) {
    ALOGV("GetMetadata - Enter");
    const String8 pathString = Utility::getStringValue(env, jpath);
    DrmMetadata* pMetadata =
            getDrmManagerClientImpl(env, thiz)->getMetadata(uniqueId, &pathString);

    jobject metadata = NULL;

    jclass localRef = env->FindClass("android/content/ContentValues");
    jmethodID ContentValues_putString =
            env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V");

    if (NULL != localRef && NULL != pMetadata) {
        // Get the constructor id
        jmethodID constructorId = NULL;
        constructorId = env->GetMethodID(localRef, "<init>", "()V");
        if (NULL != constructorId) {
            // create the java DrmMetadata object
            metadata = env->NewObject(localRef, constructorId);
            if (NULL != metadata) {
                DrmMetadata::KeyIterator keyIt = pMetadata->keyIterator();
                while (keyIt.hasNext()) {
                    String8 key = keyIt.next();
                    // insert the entry<constraintKey, constraintValue>
                    // to newly created java object
                    String8 value = pMetadata->get(key);
                    ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
                    ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
                    env->CallVoidMethod(metadata, ContentValues_putString,
                                        keyString.get(), valueString.get());
                }
            }
        }
    }
    delete pMetadata; pMetadata = NULL;
    ALOGV("GetMetadata - Exit");
    return metadata;
}

static jobjectArray android_drm_DrmManagerClient_getAllSupportInfo(
            JNIEnv* env, jobject thiz, jint uniqueId) {
    ALOGV("GetAllSupportInfo - Enter");
    DrmSupportInfo* drmSupportInfoArray = NULL;

    int length = 0;
    getDrmManagerClientImpl(env, thiz)->getAllSupportInfo(uniqueId, &length, &drmSupportInfoArray);

    jclass clazz = env->FindClass("android/drm/DrmSupportInfo");

    jobjectArray array = (jobjectArray)env->NewObjectArray(length, clazz, NULL);

    for (int i = 0; i < length; i++) {
        DrmSupportInfo info = drmSupportInfoArray[i];

        jobject drmSupportInfo = env->NewObject(clazz, env->GetMethodID(clazz, "<init>", "()V"));

        jmethodID addMimeTypeId
            = env->GetMethodID(clazz, "addMimeType", "(Ljava/lang/String;)V");
        jmethodID addFileSuffixId
            = env->GetMethodID(clazz, "addFileSuffix", "(Ljava/lang/String;)V");

        env->CallVoidMethod(
            drmSupportInfo, env->GetMethodID(clazz, "setDescription", "(Ljava/lang/String;)V"),
            env->NewStringUTF(info.getDescription().string()));

        DrmSupportInfo::MimeTypeIterator iterator = info.getMimeTypeIterator();
        while (iterator.hasNext()) {
            String8  value = iterator.next();
            env->CallVoidMethod(drmSupportInfo, addMimeTypeId, env->NewStringUTF(value.string()));
        }

        DrmSupportInfo::FileSuffixIterator it = info.getFileSuffixIterator();
        while (it.hasNext()) {
            String8 value = it.next();
            env->CallVoidMethod(
                drmSupportInfo, addFileSuffixId, env->NewStringUTF(value.string()));
        }

        env->SetObjectArrayElement(array, i, drmSupportInfo);
    }

    delete [] drmSupportInfoArray; drmSupportInfoArray = NULL;
    ALOGV("GetAllSupportInfo - Exit");
    return array;
}

static void android_drm_DrmManagerClient_installDrmEngine(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring engineFilePath) {
    ALOGV("installDrmEngine - Enter");
    //getDrmManagerClient(env, thiz)
    //  ->installDrmEngine(uniqueId, Utility::getStringValue(env, engineFilePath));
    ALOGV("installDrmEngine - Exit");
}

static jint android_drm_DrmManagerClient_saveRights(
            JNIEnv* env, jobject thiz, jint uniqueId,
            jobject drmRights, jstring rightsPath, jstring contentPath) {
    ALOGV("saveRights - Enter");
    int result = DRM_ERROR_UNKNOWN;
    int dataLength = 0;
    char* mData =  Utility::getByteArrayValue(env, drmRights, "mData", &dataLength);

    if (NULL != mData) {
        DrmRights rights(DrmBuffer(mData, dataLength),
                Utility::getStringValue(env, drmRights, "mMimeType"),
                Utility::getStringValue(env, drmRights, "mAccountId"),
                Utility::getStringValue(env, drmRights, "mSubscriptionId"));
        result = getDrmManagerClientImpl(env, thiz)
            ->saveRights(uniqueId, rights, Utility::getStringValue(env, rightsPath),
                                Utility::getStringValue(env, contentPath));
    }

    delete[] mData; mData = NULL;
    ALOGV("saveRights - Exit");
    return static_cast<jint>(result);
}

static jboolean android_drm_DrmManagerClient_canHandle(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring path, jstring mimeType) {
    ALOGV("canHandle - Enter");
    jboolean result
        = getDrmManagerClientImpl(env, thiz)
            ->canHandle(uniqueId, Utility::getStringValue(env, path),
                    Utility::getStringValue(env, mimeType));
    ALOGV("canHandle - Exit");
    return result;
}

static jobject android_drm_DrmManagerClient_processDrmInfo(
            JNIEnv* env, jobject thiz, jint uniqueId, jobject drmInfoObject) {
    ALOGV("processDrmInfo - Enter");
    int dataLength = 0;
    const String8 mMimeType =  Utility::getStringValue(env, drmInfoObject, "mMimeType");
    char* mData =  Utility::getByteArrayValue(env, drmInfoObject, "mData", &dataLength);
    int mInfoType = Utility::getIntValue(env, drmInfoObject, "mInfoType");

    const DrmBuffer buffer(mData, dataLength);
    DrmInfo drmInfo(mInfoType, buffer, mMimeType);

    jclass clazz = env->FindClass("android/drm/DrmInfo");
    jmethodID DrmInfo_get = env->GetMethodID(clazz, "get", "(Ljava/lang/String;)Ljava/lang/Object;");
    jobject keyIterator
        = env->CallObjectMethod(drmInfoObject,
                env->GetMethodID(clazz, "keyIterator", "()Ljava/util/Iterator;"));

    jclass Iterator_class = env->FindClass("java/util/Iterator");
    jmethodID Iterator_hasNext = env->GetMethodID(Iterator_class, "hasNext", "()Z");
    jmethodID Iterator_next = env->GetMethodID(Iterator_class, "next", "()Ljava/lang/Object;");

    jclass Object_class = env->FindClass("java/lang/Object");
    jmethodID Object_toString = env->GetMethodID(Object_class, "toString", "()Ljava/lang/String;");

    while (env->CallBooleanMethod(keyIterator, Iterator_hasNext)) {
        ScopedLocalRef<jstring> key(env,
                (jstring) env->CallObjectMethod(keyIterator, Iterator_next));
        ScopedLocalRef<jobject> valueObject(env,
                env->CallObjectMethod(drmInfoObject, DrmInfo_get, key.get()));
        ScopedLocalRef<jstring> valString(env, NULL);
        if (NULL != valueObject.get()) {
            valString.reset((jstring) env->CallObjectMethod(valueObject.get(), Object_toString));
        }

        String8 keyString = Utility::getStringValue(env, key.get());
        String8 valueString = Utility::getStringValue(env, valString.get());
        ALOGV("Key: %s | Value: %s", keyString.string(), valueString.string());

        drmInfo.put(keyString, valueString);
    }

    DrmInfoStatus* pDrmInfoStatus
        = getDrmManagerClientImpl(env, thiz)->processDrmInfo(uniqueId, &drmInfo);

    jclass localRef = env->FindClass("android/drm/DrmInfoStatus");
    jobject drmInfoStatus = NULL;

    if (NULL != localRef && NULL != pDrmInfoStatus) {
        int statusCode = pDrmInfoStatus->statusCode;
        int infoType = pDrmInfoStatus->infoType;

        jbyteArray dataArray = NULL;
        if (NULL != pDrmInfoStatus->drmBuffer) {
            int length = pDrmInfoStatus->drmBuffer->length;
            dataArray = env->NewByteArray(length);
            env->SetByteArrayRegion(
                dataArray, 0, length, (jbyte*) pDrmInfoStatus->drmBuffer->data);

            delete [] pDrmInfoStatus->drmBuffer->data;
            delete pDrmInfoStatus->drmBuffer; pDrmInfoStatus->drmBuffer = NULL;
        }
        jclass clazz = env->FindClass("android/drm/ProcessedData");
        jmethodID constructorId
            = env->GetMethodID(clazz, "<init>", "([BLjava/lang/String;Ljava/lang/String;)V");
        jobject processedData = env->NewObject(clazz, constructorId, dataArray,
                    env->NewStringUTF((drmInfo.get(DrmInfoRequest::ACCOUNT_ID)).string()),
                    env->NewStringUTF((drmInfo.get(DrmInfoRequest::SUBSCRIPTION_ID)).string()));

        constructorId
            = env->GetMethodID(localRef,
                "<init>", "(IILandroid/drm/ProcessedData;Ljava/lang/String;)V");

        drmInfoStatus = env->NewObject(localRef, constructorId, statusCode, infoType,
                processedData, env->NewStringUTF(pDrmInfoStatus->mimeType.string()));
    }

    delete[] mData; mData = NULL;
    delete pDrmInfoStatus; pDrmInfoStatus = NULL;

    ALOGV("processDrmInfo - Exit");
    return drmInfoStatus;
}

static jobject android_drm_DrmManagerClient_acquireDrmInfo(
            JNIEnv* env, jobject thiz, jint uniqueId, jobject drmInfoRequest) {
    ALOGV("acquireDrmInfo Enter");
    const String8 mMimeType =  Utility::getStringValue(env, drmInfoRequest, "mMimeType");
    int mInfoType = Utility::getIntValue(env, drmInfoRequest, "mInfoType");

    DrmInfoRequest drmInfoReq(mInfoType, mMimeType);

    jclass clazz = env->FindClass("android/drm/DrmInfoRequest");
    jobject keyIterator
        = env->CallObjectMethod(drmInfoRequest,
                env->GetMethodID(clazz, "keyIterator", "()Ljava/util/Iterator;"));
    jmethodID DrmInfoRequest_get = env->GetMethodID(clazz,
            "get", "(Ljava/lang/String;)Ljava/lang/Object;");

    jclass Iterator_class = env->FindClass("java/util/Iterator");
    jmethodID Iterator_hasNext = env->GetMethodID(Iterator_class, "hasNext", "()Z");
    jmethodID Iterator_next = env->GetMethodID(Iterator_class, "next", "()Ljava/lang/Object;");

    while (env->CallBooleanMethod(keyIterator, Iterator_hasNext)) {
        ScopedLocalRef<jstring> key(env,
                (jstring) env->CallObjectMethod(keyIterator, Iterator_next));
        ScopedLocalRef<jstring> value(env,
                (jstring) env->CallObjectMethod(drmInfoRequest, DrmInfoRequest_get, key.get()));

        String8 keyString = Utility::getStringValue(env, key.get());
        String8 valueString = Utility::getStringValue(env, value.get());
        ALOGV("Key: %s | Value: %s", keyString.string(), valueString.string());

        drmInfoReq.put(keyString, valueString);
    }

    DrmInfo* pDrmInfo = getDrmManagerClientImpl(env, thiz)->acquireDrmInfo(uniqueId, &drmInfoReq);

    jobject drmInfoObject = NULL;

    if (NULL != pDrmInfo) {
        jclass localRef = env->FindClass("android/drm/DrmInfo");

        if (NULL != localRef) {
            int length = pDrmInfo->getData().length;

            jbyteArray dataArray = env->NewByteArray(length);
            env->SetByteArrayRegion(dataArray, 0, length, (jbyte*)pDrmInfo->getData().data);

            drmInfoObject
                = env->NewObject(localRef,
                    env->GetMethodID(localRef, "<init>", "(I[BLjava/lang/String;)V"),
                    mInfoType, dataArray, env->NewStringUTF(pDrmInfo->getMimeType().string()));

            DrmInfo::KeyIterator it = pDrmInfo->keyIterator();
            jmethodID putMethodId
                = env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/Object;)V");

            while (it.hasNext()) {
                String8 key = it.next();
                String8 value = pDrmInfo->get(key);
                ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
                ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
                env->CallVoidMethod(drmInfoObject, putMethodId,
                    keyString.get(), valueString.get());
            }
        }
        delete [] pDrmInfo->getData().data;
    }

    delete pDrmInfo; pDrmInfo = NULL;

    ALOGV("acquireDrmInfo Exit");
    return drmInfoObject;
}

static jint android_drm_DrmManagerClient_getDrmObjectType(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring path, jstring mimeType) {
    ALOGV("getDrmObjectType Enter");
    int drmObjectType
        = getDrmManagerClientImpl(env, thiz)
            ->getDrmObjectType(uniqueId, Utility::getStringValue(env, path),
                                Utility::getStringValue(env, mimeType));
    ALOGV("getDrmObjectType Exit");
    return static_cast<jint>(drmObjectType);
}

static jstring android_drm_DrmManagerClient_getOriginalMimeType(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring path, jobject fileDescriptor) {
    ALOGV("getOriginalMimeType Enter");

    int fd = (fileDescriptor == NULL)
                ? -1
                : jniGetFDFromFileDescriptor(env, fileDescriptor);

    String8 mimeType
        = getDrmManagerClientImpl(env, thiz)
            ->getOriginalMimeType(uniqueId,
                                  Utility::getStringValue(env, path), fd);
    ALOGV("getOriginalMimeType Exit");
    return env->NewStringUTF(mimeType.string());
}

static jint android_drm_DrmManagerClient_checkRightsStatus(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring path, int action) {
    ALOGV("checkRightsStatus Enter");
    int rightsStatus
        = getDrmManagerClientImpl(env, thiz)
            ->checkRightsStatus(uniqueId, Utility::getStringValue(env, path), action);
    ALOGV("checkRightsStatus Exit");
    return static_cast<jint>(rightsStatus);
}

static jint android_drm_DrmManagerClient_removeRights(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring path) {
    ALOGV("removeRights");
    return static_cast<jint>(getDrmManagerClientImpl(env, thiz)
               ->removeRights(uniqueId, Utility::getStringValue(env, path)));
}

static jint android_drm_DrmManagerClient_removeAllRights(
            JNIEnv* env, jobject thiz, jint uniqueId) {
    ALOGV("removeAllRights");
    return static_cast<jint>(getDrmManagerClientImpl(env, thiz)
                ->removeAllRights(uniqueId));
}

static jint android_drm_DrmManagerClient_openConvertSession(
            JNIEnv* env, jobject thiz, jint uniqueId, jstring mimeType) {
    ALOGV("openConvertSession Enter");
    int convertId
        = getDrmManagerClientImpl(env, thiz)
            ->openConvertSession(uniqueId, Utility::getStringValue(env, mimeType));
    ALOGV("openConvertSession Exit");
    return static_cast<jint>(convertId);
}

static jobject GetConvertedStatus(JNIEnv* env, DrmConvertedStatus* pDrmConvertedStatus) {
    ALOGV("GetConvertedStatus - Enter");
    jclass localRef = env->FindClass("android/drm/DrmConvertedStatus");

    jobject drmConvertedStatus = NULL;

    if (NULL != localRef && NULL != pDrmConvertedStatus) {
        int statusCode = pDrmConvertedStatus->statusCode;

        jbyteArray dataArray = NULL;
        if (NULL != pDrmConvertedStatus->convertedData) {
            int length = pDrmConvertedStatus->convertedData->length;
            dataArray = env->NewByteArray(length);
            env->SetByteArrayRegion(
                dataArray, 0, length, (jbyte*) pDrmConvertedStatus->convertedData->data);

            delete [] pDrmConvertedStatus->convertedData->data;
            delete pDrmConvertedStatus->convertedData; pDrmConvertedStatus->convertedData = NULL;
        }
        jmethodID constructorId = env->GetMethodID(localRef, "<init>", "(I[BI)V");
        drmConvertedStatus
            = env->NewObject(localRef, constructorId,
                             statusCode, dataArray, pDrmConvertedStatus->offset);
    }

    delete pDrmConvertedStatus; pDrmConvertedStatus = NULL;

    ALOGV("GetConvertedStatus - Exit");
    return drmConvertedStatus;
}

static jobject android_drm_DrmManagerClient_convertData(
            JNIEnv* env, jobject thiz, jint uniqueId, jint convertId, jbyteArray inputData) {
    ALOGV("convertData Enter");

    int dataLength = 0;
    char* mData = Utility::getByteArrayValue(env, inputData, &dataLength);
    const DrmBuffer buffer(mData, dataLength);

    DrmConvertedStatus* pDrmConvertedStatus
            = getDrmManagerClientImpl(env, thiz)->convertData(uniqueId, convertId, &buffer);
    jobject status = GetConvertedStatus(env, pDrmConvertedStatus);

    delete[] mData;
    mData = NULL;

    ALOGV("convertData - Exit");
    return status;
}

static jobject android_drm_DrmManagerClient_closeConvertSession(
            JNIEnv* env, jobject thiz, jint uniqueId, jint convertId) {

    ALOGV("closeConvertSession Enter");

    DrmConvertedStatus* pDrmConvertedStatus
                = getDrmManagerClientImpl(env, thiz)->closeConvertSession(uniqueId, convertId);
    jobject status = GetConvertedStatus(env, pDrmConvertedStatus);

    ALOGV("closeConvertSession - Exit");
    return status;
}

static JNINativeMethod nativeMethods[] = {

    {"_initialize", "()I",
                                    (void*)android_drm_DrmManagerClient_initialize},

    {"_setListeners", "(ILjava/lang/Object;)V",
                                    (void*)android_drm_DrmManagerClient_setListeners},

    {"_release", "(I)V",
                                    (void*)android_drm_DrmManagerClient_release},

    {"_getConstraints", "(ILjava/lang/String;I)Landroid/content/ContentValues;",
                                    (void*)android_drm_DrmManagerClient_getConstraintsFromContent},

    {"_getMetadata", "(ILjava/lang/String;)Landroid/content/ContentValues;",
                                    (void*)android_drm_DrmManagerClient_getMetadataFromContent},

    {"_getAllSupportInfo", "(I)[Landroid/drm/DrmSupportInfo;",
                                    (void*)android_drm_DrmManagerClient_getAllSupportInfo},

    {"_installDrmEngine", "(ILjava/lang/String;)V",
                                    (void*)android_drm_DrmManagerClient_installDrmEngine},

    {"_canHandle", "(ILjava/lang/String;Ljava/lang/String;)Z",
                                    (void*)android_drm_DrmManagerClient_canHandle},

    {"_processDrmInfo", "(ILandroid/drm/DrmInfo;)Landroid/drm/DrmInfoStatus;",
                                    (void*)android_drm_DrmManagerClient_processDrmInfo},

    {"_acquireDrmInfo", "(ILandroid/drm/DrmInfoRequest;)Landroid/drm/DrmInfo;",
                                    (void*)android_drm_DrmManagerClient_acquireDrmInfo},

    {"_saveRights", "(ILandroid/drm/DrmRights;Ljava/lang/String;Ljava/lang/String;)I",
                                    (void*)android_drm_DrmManagerClient_saveRights},

    {"_getDrmObjectType", "(ILjava/lang/String;Ljava/lang/String;)I",
                                    (void*)android_drm_DrmManagerClient_getDrmObjectType},

    {"_getOriginalMimeType", "(ILjava/lang/String;Ljava/io/FileDescriptor;)Ljava/lang/String;",
                                    (void*)android_drm_DrmManagerClient_getOriginalMimeType},

    {"_checkRightsStatus", "(ILjava/lang/String;I)I",
                                    (void*)android_drm_DrmManagerClient_checkRightsStatus},

    {"_removeRights", "(ILjava/lang/String;)I",
                                    (void*)android_drm_DrmManagerClient_removeRights},

    {"_removeAllRights", "(I)I",
                                    (void*)android_drm_DrmManagerClient_removeAllRights},

    {"_openConvertSession", "(ILjava/lang/String;)I",
                                    (void*)android_drm_DrmManagerClient_openConvertSession},

    {"_convertData", "(II[B)Landroid/drm/DrmConvertedStatus;",
                                    (void*)android_drm_DrmManagerClient_convertData},

    {"_closeConvertSession", "(II)Landroid/drm/DrmConvertedStatus;",
                                    (void*)android_drm_DrmManagerClient_closeConvertSession},
};

static int registerNativeMethods(JNIEnv* env) {
    int result = -1;

    /* look up the class */
    jclass clazz = env->FindClass("android/drm/DrmManagerClient");

    if (NULL != clazz) {
        if (env->RegisterNatives(clazz, nativeMethods, sizeof(nativeMethods)
                / sizeof(nativeMethods[0])) == JNI_OK) {
            result = 0;
        }
    }
    return result;
}

jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
        if (NULL != env && registerNativeMethods(env) == 0) {
            result = JNI_VERSION_1_4;
        }
    }
    return result;
}

