DrmConstraints* BpDrmManagerService::getConstraints(
            int uniqueId, const String8* path, const int action) {
    LOGV("Get Constraints");
    Parcel data, reply;

    data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
    data.writeInt32(uniqueId);
    data.writeString8(*path);
    data.writeInt32(action);

    remote()->transact(GET_CONSTRAINTS_FROM_CONTENT, data, &reply);

    DrmConstraints* drmConstraints = NULL;
    if (0 != reply.dataAvail()) {
        //Filling Drm Constraints
        drmConstraints = new DrmConstraints();

        const int size = reply.readInt32();
        for (int index = 0; index < size; ++index) {
            const String8 key(reply.readString8());
            const int bufferSize = reply.readInt32();
            char* data = NULL;
            if (0 < bufferSize) {
                data = new char[bufferSize];
                reply.read(data, bufferSize);
            }
            drmConstraints->put(&key, data);
        }
    }
    return drmConstraints;
}
DrmConstraints* DrmPassthruPlugIn::onGetConstraints(
        int uniqueId, const String8* path, int action) {
    ALOGV("DrmPassthruPlugIn::onGetConstraints From Path: %d", uniqueId);
    DrmConstraints* drmConstraints = new DrmConstraints();

    String8 value("dummy_available_time");
    char* charValue = NULL;
    charValue = new char[value.length() + 1];
    strncpy(charValue, value.string(), value.length());

    //Just add dummy available time for verification
    drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue);

    return drmConstraints;
}
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;
}
status_t BnDrmManagerService::onTransact(
            uint32_t code, const Parcel& data,
            Parcel* reply, uint32_t flags) {
    LOGV("Entering BnDrmManagerService::onTransact with code %d", code);

    switch (code) {
    case ADD_UNIQUEID:
    {
        LOGV("BnDrmManagerService::onTransact :ADD_UNIQUEID");
        CHECK_INTERFACE(IDrmManagerService, data, reply);
        int uniqueId = addUniqueId(data.readInt32());
        reply->writeInt32(uniqueId);
        return DRM_NO_ERROR;
    }

    case REMOVE_UNIQUEID:
    {
        LOGV("BnDrmManagerService::onTransact :REMOVE_UNIQUEID");
        CHECK_INTERFACE(IDrmManagerService, data, reply);
        removeUniqueId(data.readInt32());
        return DRM_NO_ERROR;
    }

    case LOAD_PLUGINS:
    {
        LOGV("BnDrmManagerService::onTransact :LOAD_PLUGINS");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        status_t status = loadPlugIns(data.readInt32());

        reply->writeInt32(status);
        return DRM_NO_ERROR;
    }

    case LOAD_PLUGINS_FROM_PATH:
    {
        LOGV("BnDrmManagerService::onTransact :LOAD_PLUGINS_FROM_PATH");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        status_t status = loadPlugIns(data.readInt32(), data.readString8());

        reply->writeInt32(status);
        return DRM_NO_ERROR;
    }

    case SET_DRM_SERVICE_LISTENER:
    {
        LOGV("BnDrmManagerService::onTransact :SET_DRM_SERVICE_LISTENER");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();
        const sp<IDrmServiceListener> drmServiceListener
            = interface_cast<IDrmServiceListener> (data.readStrongBinder());

        status_t status = setDrmServiceListener(uniqueId, drmServiceListener);

        reply->writeInt32(status);
        return DRM_NO_ERROR;
    }

    case UNLOAD_PLUGINS:
    {
        LOGV("BnDrmManagerService::onTransact :UNLOAD_PLUGINS");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();
        status_t status = unloadPlugIns(uniqueId);

        reply->writeInt32(status);
        return DRM_NO_ERROR;
    }

    case INSTALL_DRM_ENGINE:
    {
        LOGV("BnDrmManagerService::onTransact :INSTALL_DRM_ENGINE");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        status_t status = installDrmEngine(data.readInt32(), data.readString8());

        reply->writeInt32(status);
        return DRM_NO_ERROR;
    }

    case GET_CONSTRAINTS_FROM_CONTENT:
    {
        LOGV("BnDrmManagerService::onTransact :GET_CONSTRAINTS_FROM_CONTENT");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();
        const String8 path = data.readString8();

        DrmConstraints* drmConstraints = getConstraints(uniqueId, &path, data.readInt32());

        if (NULL != drmConstraints) {
            //Filling DRM Constraints contents
            reply->writeInt32(drmConstraints->getCount());

            DrmConstraints::KeyIterator keyIt = drmConstraints->keyIterator();
            while (keyIt.hasNext()) {
                const String8 key = keyIt.next();
                reply->writeString8(key);
                const char* value = drmConstraints->getAsByteArray(&key);
                int bufferSize = 0;
                if (NULL != value) {
                    bufferSize = strlen(value);
                }
                reply->writeInt32(bufferSize + 1);
                reply->write(value, bufferSize + 1);
            }
        }
        delete drmConstraints; drmConstraints = NULL;
        return DRM_NO_ERROR;
    }

    case CAN_HANDLE:
    {
        LOGV("BnDrmManagerService::onTransact :CAN_HANDLE");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();
        const String8 path = data.readString8();
        const String8 mimeType = data.readString8();

        bool result = canHandle(uniqueId, path, mimeType);

        reply->writeInt32(result);
        return DRM_NO_ERROR;
    }

    case PROCESS_DRM_INFO:
    {
        LOGV("BnDrmManagerService::onTransact :PROCESS_DRM_INFO");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        //Filling DRM info
        const int infoType = data.readInt32();
        const int bufferSize = data.readInt32();
        char* buffer = NULL;
        if (0 < bufferSize) {
            buffer = (char *)data.readInplace(bufferSize);
        }
        const DrmBuffer drmBuffer(buffer, bufferSize);
        DrmInfo* drmInfo = new DrmInfo(infoType, drmBuffer, data.readString8());

        const int size = data.readInt32();
        for (int index = 0; index < size; ++index) {
            const String8 key(data.readString8());
            const String8 value(data.readString8());
            drmInfo->put(key, (value == String8("NULL")) ? String8("") : value);
        }

        DrmInfoStatus* drmInfoStatus = processDrmInfo(uniqueId, drmInfo);

        if (NULL != drmInfoStatus) {
            //Filling DRM Info Status contents
            reply->writeInt32(drmInfoStatus->statusCode);
            reply->writeString8(drmInfoStatus->mimeType);

            if (NULL != drmInfoStatus->drmBuffer) {
                const DrmBuffer* drmBuffer = drmInfoStatus->drmBuffer;
                const int bufferSize = drmBuffer->length;
                reply->writeInt32(bufferSize);
                if (0 < bufferSize) {
                    reply->write(drmBuffer->data, bufferSize);
                }
                delete [] drmBuffer->data;
                delete drmBuffer; drmBuffer = NULL;
            }
        }
        delete drmInfo; drmInfo = NULL;
        delete drmInfoStatus; drmInfoStatus = NULL;
        return DRM_NO_ERROR;
    }

    case ACQUIRE_DRM_INFO:
    {
        LOGV("BnDrmManagerService::onTransact :ACQUIRE_DRM_INFO");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        //Filling DRM info Request
        DrmInfoRequest* drmInfoRequest = new DrmInfoRequest(data.readInt32(), data.readString8());

        const int size = data.readInt32();
        for (int index = 0; index < size; ++index) {
            const String8 key(data.readString8());
            const String8 value(data.readString8());
            drmInfoRequest->put(key, (value == String8("NULL")) ? String8("") : value);
        }

        DrmInfo* drmInfo = acquireDrmInfo(uniqueId, drmInfoRequest);

        if (NULL != drmInfo) {
            //Filling DRM Info
            const DrmBuffer drmBuffer = drmInfo->getData();
            reply->writeInt32(drmInfo->getInfoType());

            const int bufferSize = drmBuffer.length;
            reply->writeInt32(bufferSize);
            if (0 < bufferSize) {
                reply->write(drmBuffer.data, bufferSize);
            }
            reply->writeString8(drmInfo->getMimeType());
            reply->writeInt32(drmInfo->getCount());

            DrmInfo::KeyIterator keyIt = drmInfo->keyIterator();
            while (keyIt.hasNext()) {
                const String8 key = keyIt.next();
                reply->writeString8(key);
                const String8 value = drmInfo->get(key);
                reply->writeString8((value == String8("")) ? String8("NULL") : value);
            }
            delete [] drmBuffer.data;
        }
        delete drmInfoRequest; drmInfoRequest = NULL;
        delete drmInfo; drmInfo = NULL;
        return DRM_NO_ERROR;
    }

    case SAVE_RIGHTS:
    {
        LOGV("BnDrmManagerService::onTransact :SAVE_RIGHTS");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        //Filling DRM Rights
        const int bufferSize = data.readInt32();
        const DrmBuffer drmBuffer((char *)data.readInplace(bufferSize), bufferSize);

        const String8 mimeType(data.readString8());
        const String8 accountId(data.readString8());
        const String8 subscriptionId(data.readString8());
        const String8 rightsPath(data.readString8());
        const String8 contentPath(data.readString8());

        DrmRights drmRights(drmBuffer,
                            ((mimeType == String8("NULL")) ? String8("") : mimeType),
                            ((accountId == String8("NULL")) ? String8("") : accountId),
                            ((subscriptionId == String8("NULL")) ? String8("") : subscriptionId));

        const status_t status = saveRights(uniqueId, drmRights,
                            ((rightsPath == String8("NULL")) ? String8("") : rightsPath),
                            ((contentPath == String8("NULL")) ? String8("") : contentPath));

        reply->writeInt32(status);
        return DRM_NO_ERROR;
    }

    case GET_ORIGINAL_MIMETYPE:
    {
        LOGV("BnDrmManagerService::onTransact :GET_ORIGINAL_MIMETYPE");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const String8 originalMimeType = getOriginalMimeType(data.readInt32(), data.readString8());

        reply->writeString8(originalMimeType);
        return DRM_NO_ERROR;
    }

    case GET_DRM_OBJECT_TYPE:
    {
        LOGV("BnDrmManagerService::onTransact :GET_DRM_OBJECT_TYPE");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int drmObjectType
            = getDrmObjectType(data.readInt32(), data.readString8(), data.readString8());

        reply->writeInt32(drmObjectType);
        return DRM_NO_ERROR;
    }

    case CHECK_RIGHTS_STATUS:
    {
        LOGV("BnDrmManagerService::onTransact :CHECK_RIGHTS_STATUS");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int result
            = checkRightsStatus(data.readInt32(), data.readString8(), data.readInt32());

        reply->writeInt32(result);
        return DRM_NO_ERROR;
    }

    case CONSUME_RIGHTS:
    {
        LOGV("BnDrmManagerService::onTransact :CONSUME_RIGHTS");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        DecryptHandle handle;
        handle.decryptId = data.readInt32();
        handle.mimeType = data.readString8();
        handle.decryptApiType = data.readInt32();
        handle.status = data.readInt32();
        handle.decryptInfo = NULL;

        const int bufferLength = data.readInt32();
        if (INVALID_BUFFER_LENGTH != bufferLength) {
            handle.decryptInfo = new DecryptInfo();
            handle.decryptInfo->decryptBufferLength = bufferLength;
        }

        const status_t status
            = consumeRights(uniqueId, &handle, data.readInt32(),
                static_cast<bool>(data.readInt32()));
        reply->writeInt32(status);

        delete handle.decryptInfo; handle.decryptInfo = NULL;
        return DRM_NO_ERROR;
    }

    case SET_PLAYBACK_STATUS:
    {
        LOGV("BnDrmManagerService::onTransact :SET_PLAYBACK_STATUS");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        DecryptHandle handle;
        handle.decryptId = data.readInt32();
        handle.mimeType = data.readString8();
        handle.decryptApiType = data.readInt32();
        handle.status = data.readInt32();
        handle.decryptInfo = NULL;

        const int bufferLength = data.readInt32();
        if (INVALID_BUFFER_LENGTH != bufferLength) {
            handle.decryptInfo = new DecryptInfo();
            handle.decryptInfo->decryptBufferLength = bufferLength;
        }

        const status_t status
            = setPlaybackStatus(uniqueId, &handle, data.readInt32(), data.readInt32());
        reply->writeInt32(status);

        delete handle.decryptInfo; handle.decryptInfo = NULL;
        return DRM_NO_ERROR;
    }

    case VALIDATE_ACTION:
    {
        LOGV("BnDrmManagerService::onTransact :VALIDATE_ACTION");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        bool result = validateAction(
                                data.readInt32(),
                                data.readString8(),
                                data.readInt32(),
                                ActionDescription(data.readInt32(), data.readInt32()));

        reply->writeInt32(result);
        return DRM_NO_ERROR;
    }

    case REMOVE_RIGHTS:
    {
        LOGV("BnDrmManagerService::onTransact :REMOVE_RIGHTS");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const status_t status = removeRights(data.readInt32(), data.readString8());
        reply->writeInt32(status);

        return DRM_NO_ERROR;
    }

    case REMOVE_ALL_RIGHTS:
    {
        LOGV("BnDrmManagerService::onTransact :REMOVE_ALL_RIGHTS");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const status_t status = removeAllRights(data.readInt32());
        reply->writeInt32(status);

        return DRM_NO_ERROR;
    }

    case OPEN_CONVERT_SESSION:
    {
        LOGV("BnDrmManagerService::onTransact :OPEN_CONVERT_SESSION");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int convertId = openConvertSession(data.readInt32(), data.readString8());

        reply->writeInt32(convertId);
        return DRM_NO_ERROR;
    }

    case CONVERT_DATA:
    {
        LOGV("BnDrmManagerService::onTransact :CONVERT_DATA");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();
        const int convertId = data.readInt32();

        //Filling input data
        const int bufferSize = data.readInt32();
        DrmBuffer* inputData = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);

        DrmConvertedStatus*    drmConvertedStatus = convertData(uniqueId, convertId, inputData);

        if (NULL != drmConvertedStatus) {
            //Filling Drm Converted Ststus
            reply->writeInt32(drmConvertedStatus->statusCode);
            reply->writeInt32(drmConvertedStatus->offset);

            if (NULL != drmConvertedStatus->convertedData) {
                const DrmBuffer* convertedData = drmConvertedStatus->convertedData;
                const int bufferSize = convertedData->length;
                reply->writeInt32(bufferSize);
                if (0 < bufferSize) {
                    reply->write(convertedData->data, bufferSize);
                }
                delete [] convertedData->data;
                delete convertedData; convertedData = NULL;
            }
        }
        delete inputData; inputData = NULL;
        delete drmConvertedStatus; drmConvertedStatus = NULL;
        return DRM_NO_ERROR;
    }

    case CLOSE_CONVERT_SESSION:
    {
        LOGV("BnDrmManagerService::onTransact :CLOSE_CONVERT_SESSION");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        DrmConvertedStatus*    drmConvertedStatus
            = closeConvertSession(data.readInt32(), data.readInt32());

        if (NULL != drmConvertedStatus) {
            //Filling Drm Converted Ststus
            reply->writeInt32(drmConvertedStatus->statusCode);
            reply->writeInt32(drmConvertedStatus->offset);

            if (NULL != drmConvertedStatus->convertedData) {
                const DrmBuffer* convertedData = drmConvertedStatus->convertedData;
                const int bufferSize = convertedData->length;
                reply->writeInt32(bufferSize);
                if (0 < bufferSize) {
                    reply->write(convertedData->data, bufferSize);
                }
                delete [] convertedData->data;
                delete convertedData; convertedData = NULL;
            }
        }
        delete drmConvertedStatus; drmConvertedStatus = NULL;
        return DRM_NO_ERROR;
    }

    case GET_ALL_SUPPORT_INFO:
    {
        LOGV("BnDrmManagerService::onTransact :GET_ALL_SUPPORT_INFO");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();
        int length = 0;
        DrmSupportInfo* drmSupportInfoArray = NULL;

        status_t status = getAllSupportInfo(uniqueId, &length, &drmSupportInfoArray);

        reply->writeInt32(length);
        for (int i = 0; i < length; ++i) {
            DrmSupportInfo drmSupportInfo = drmSupportInfoArray[i];

            reply->writeInt32(drmSupportInfo.getFileSuffixCount());
            DrmSupportInfo::FileSuffixIterator fileSuffixIt
                = drmSupportInfo.getFileSuffixIterator();
            while (fileSuffixIt.hasNext()) {
                reply->writeString8(fileSuffixIt.next());
            }

            reply->writeInt32(drmSupportInfo.getMimeTypeCount());
            DrmSupportInfo::MimeTypeIterator mimeTypeIt = drmSupportInfo.getMimeTypeIterator();
            while (mimeTypeIt.hasNext()) {
                reply->writeString8(mimeTypeIt.next());
            }
            reply->writeString8(drmSupportInfo.getDescription());
        }
        delete [] drmSupportInfoArray; drmSupportInfoArray = NULL;
        reply->writeInt32(status);
        return DRM_NO_ERROR;
    }

    case OPEN_DECRYPT_SESSION:
    {
        LOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();
        const int fd = data.readFileDescriptor();

        DecryptHandle* handle
            = openDecryptSession(uniqueId, fd, data.readInt32(), data.readInt32());

        if (NULL != handle) {
            reply->writeInt32(handle->decryptId);
            reply->writeString8(handle->mimeType);
            reply->writeInt32(handle->decryptApiType);
            reply->writeInt32(handle->status);
            if (NULL != handle->decryptInfo) {
                reply->writeInt32(handle->decryptInfo->decryptBufferLength);
                delete handle->decryptInfo; handle->decryptInfo = NULL;
            }
        } else {
            LOGE("NULL decryptHandle is returned");
        }
        delete handle; handle = NULL;
        return DRM_NO_ERROR;
    }

    case CLOSE_DECRYPT_SESSION:
    {
        LOGV("BnDrmManagerService::onTransact :CLOSE_DECRYPT_SESSION");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        DecryptHandle* handle = new DecryptHandle();
        handle->decryptId = data.readInt32();
        handle->mimeType = data.readString8();
        handle->decryptApiType = data.readInt32();
        handle->status = data.readInt32();
        handle->decryptInfo = NULL;

        const int bufferLength = data.readInt32();
        if (INVALID_BUFFER_LENGTH != bufferLength) {
            handle->decryptInfo = new DecryptInfo();
            handle->decryptInfo->decryptBufferLength = bufferLength;
        }

        const status_t status = closeDecryptSession(uniqueId, handle);
        reply->writeInt32(status);
        return DRM_NO_ERROR;
    }

    case INITIALIZE_DECRYPT_UNIT:
    {
        LOGV("BnDrmManagerService::onTransact :INITIALIZE_DECRYPT_UNIT");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        DecryptHandle handle;
        handle.decryptId = data.readInt32();
        handle.mimeType = data.readString8();
        handle.decryptApiType = data.readInt32();
        handle.status = data.readInt32();
        handle.decryptInfo = NULL;

        const int bufferLength = data.readInt32();
        if (INVALID_BUFFER_LENGTH != bufferLength) {
            handle.decryptInfo = new DecryptInfo();
            handle.decryptInfo->decryptBufferLength = bufferLength;
        }
        const int decryptUnitId = data.readInt32();

        //Filling Header info
        const int bufferSize = data.readInt32();
        DrmBuffer* headerInfo = NULL;
        headerInfo = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);

        const status_t status
            = initializeDecryptUnit(uniqueId, &handle, decryptUnitId, headerInfo);
        reply->writeInt32(status);

        delete handle.decryptInfo; handle.decryptInfo = NULL;
        delete headerInfo; headerInfo = NULL;
        return DRM_NO_ERROR;
    }

    case DECRYPT:
    {
        LOGV("BnDrmManagerService::onTransact :DECRYPT");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        DecryptHandle handle;
        handle.decryptId = data.readInt32();
        handle.mimeType = data.readString8();
        handle.decryptApiType = data.readInt32();
        handle.status = data.readInt32();
        handle.decryptInfo = NULL;

        const int bufferLength = data.readInt32();
        if (INVALID_BUFFER_LENGTH != bufferLength) {
            handle.decryptInfo = new DecryptInfo();
            handle.decryptInfo->decryptBufferLength = bufferLength;
        }
        const int decryptUnitId = data.readInt32();
        const int decBufferSize = data.readInt32();

        const int encBufferSize = data.readInt32();
        DrmBuffer* encBuffer
            = new DrmBuffer((char *)data.readInplace(encBufferSize), encBufferSize);

        char* buffer = NULL;
        buffer = new char[decBufferSize];
        DrmBuffer* decBuffer = new DrmBuffer(buffer, decBufferSize);

        DrmBuffer* IV = NULL;
        if (0 != data.dataAvail()) {
            const int ivBufferlength = data.readInt32();
            IV = new DrmBuffer((char *)data.readInplace(ivBufferlength), ivBufferlength);
        }

        const status_t status
            = decrypt(uniqueId, &handle, decryptUnitId, encBuffer, &decBuffer, IV);

        reply->writeInt32(status);

        const int size = decBuffer->length;
        reply->writeInt32(size);
        reply->write(decBuffer->data, size);

        delete handle.decryptInfo; handle.decryptInfo = NULL;
        delete encBuffer; encBuffer = NULL;
        delete decBuffer; decBuffer = NULL;
        delete [] buffer; buffer = NULL;
        delete IV; IV = NULL;
        return DRM_NO_ERROR;
    }

    case FINALIZE_DECRYPT_UNIT:
    {
        LOGV("BnDrmManagerService::onTransact :FINALIZE_DECRYPT_UNIT");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        DecryptHandle handle;
        handle.decryptId = data.readInt32();
        handle.mimeType = data.readString8();
        handle.decryptApiType = data.readInt32();
        handle.status = data.readInt32();
        handle.decryptInfo = NULL;

        const int bufferLength = data.readInt32();
        if (INVALID_BUFFER_LENGTH != bufferLength) {
            handle.decryptInfo = new DecryptInfo();
            handle.decryptInfo->decryptBufferLength = bufferLength;
        }

        const status_t status = finalizeDecryptUnit(uniqueId, &handle, data.readInt32());
        reply->writeInt32(status);

        delete handle.decryptInfo; handle.decryptInfo = NULL;
        return DRM_NO_ERROR;
    }

    case PREAD:
    {
        LOGV("BnDrmManagerService::onTransact :READ");
        CHECK_INTERFACE(IDrmManagerService, data, reply);

        const int uniqueId = data.readInt32();

        DecryptHandle handle;
        handle.decryptId = data.readInt32();
        handle.mimeType = data.readString8();
        handle.decryptApiType = data.readInt32();
        handle.status = data.readInt32();
        handle.decryptInfo = NULL;

        const int bufferLength = data.readInt32();
        if (INVALID_BUFFER_LENGTH != bufferLength) {
            handle.decryptInfo = new DecryptInfo();
            handle.decryptInfo->decryptBufferLength = bufferLength;
        }

        const int numBytes = data.readInt32();
        char* buffer = new char[numBytes];

        const off_t offset = data.readInt32();

        ssize_t result = pread(uniqueId, &handle, buffer, numBytes, offset);
        reply->writeInt32(result);
        if (0 < result) {
            reply->write(buffer, result);
        }

        delete handle.decryptInfo; handle.decryptInfo = NULL;
        delete [] buffer, buffer = NULL;
        return DRM_NO_ERROR;
    }

    default:
        return BBinder::onTransact(code, data, reply, flags);
    }
}