/*
 * 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.
 */

#include "SessionMap.h"
#include "FwdLockEngine.h"
#include <utils/Log.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include "drm_framework_common.h"
#include <fcntl.h>
#include <limits.h>
#include <DrmRights.h>
#include <DrmConstraints.h>
#include <DrmMetadata.h>
#include <DrmInfo.h>
#include <DrmInfoStatus.h>
#include <DrmInfoRequest.h>
#include <DrmSupportInfo.h>
#include <DrmConvertedStatus.h>
#include <utils/String8.h>
#include "FwdLockConv.h"
#include "FwdLockFile.h"
#include "FwdLockGlue.h"
#include "MimeTypeUtil.h"

#undef LOG_TAG
#define LOG_TAG "FwdLockEngine"

#ifdef DRM_OMA_FL_ENGINE_DEBUG
#define LOG_NDEBUG 0
#define LOG_VERBOSE(...) ALOGV(__VA_ARGS__)
#else
#define LOG_VERBOSE(...)
#endif

using namespace android;
// This extern "C" is mandatory to be managed by TPlugInManager
extern "C" IDrmEngine* create() {
    return new FwdLockEngine();
}

// This extern "C" is mandatory to be managed by TPlugInManager
extern "C" void destroy(IDrmEngine* plugIn) {
    delete plugIn;
}

FwdLockEngine::FwdLockEngine() {
    LOG_VERBOSE("FwdLockEngine Construction");
}

FwdLockEngine::~FwdLockEngine() {
    LOG_VERBOSE("FwdLockEngine Destruction");

    int size = decodeSessionMap.getSize();

    for (int i = 0; i < size; i++) {
        DecodeSession *session = (DecodeSession*) decodeSessionMap.getValueAt(i);
        FwdLockFile_detach(session->fileDesc);
        ::close(session->fileDesc);
    }

    size = convertSessionMap.getSize();
    for (int i = 0; i < size; i++) {
        ConvertSession *convSession = (ConvertSession*) convertSessionMap.getValueAt(i);
        FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
    }
}

int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
    int retStatus = DrmConvertedStatus::STATUS_ERROR;

    switch(status) {
        case FwdLockConv_Status_OK:
            retStatus = DrmConvertedStatus::STATUS_OK;
            break;
        case FwdLockConv_Status_SyntaxError:
        case FwdLockConv_Status_InvalidArgument:
        case FwdLockConv_Status_UnsupportedFileFormat:
        case FwdLockConv_Status_UnsupportedContentTransferEncoding:
            ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
                  "Returning STATUS_INPUTDATA_ERROR", status);
            retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR;
            break;
        default:
            ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
                  "Returning STATUS_ERROR", status);
            retStatus = DrmConvertedStatus::STATUS_ERROR;
            break;
    }

    return retStatus;
}

DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
    DrmConstraints* drmConstraints = NULL;

    LOG_VERBOSE("FwdLockEngine::onGetConstraints");

    if (NULL != path &&
        (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
        // Return the empty constraints to show no error condition.
        drmConstraints = new DrmConstraints();
    }

    return drmConstraints;
}

DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
    DrmMetadata* drmMetadata = NULL;

    LOG_VERBOSE("FwdLockEngine::onGetMetadata");

    if (NULL != path) {
        // Returns empty metadata to show no error condition.
        drmMetadata = new DrmMetadata();
    }

    return drmMetadata;
}

android::status_t FwdLockEngine::onInitialize(int uniqueId) {
    LOG_VERBOSE("FwdLockEngine::onInitialize");

    if (FwdLockGlue_InitializeKeyEncryption()) {
        LOG_VERBOSE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
    } else {
        ALOGE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
             "errno = %d", errno);
    }

    return DRM_NO_ERROR;
}

android::status_t
FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
    // Not used
    LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener");

    return DRM_NO_ERROR;
}

android::status_t FwdLockEngine::onTerminate(int uniqueId) {
    LOG_VERBOSE("FwdLockEngine::onTerminate");

    return DRM_NO_ERROR;
}

// make sure that lower-case letters are used.
const String8 FwdLockEngine::FileSuffixes[] = {
    String8(".fl"),
    String8(".dm"),
};

// make sure that lower-case letters are used.
const String8 FwdLockEngine::MimeTypes[] = {
    String8("application/x-android-drm-fl"),
    String8("application/vnd.oma.drm.message"),
};

const String8 FwdLockEngine::Description("OMA V1 Forward Lock");

void FwdLockEngine::AddSupportedMimeTypes(DrmSupportInfo *info) {
    for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) {
        info->addMimeType(MimeTypes[i]);
    }
}

void FwdLockEngine::AddSupportedFileSuffixes(DrmSupportInfo *info) {
    for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) {
        info->addFileSuffix(FileSuffixes[i]);
    }
}

bool FwdLockEngine::IsMimeTypeSupported(const String8& mime) {
    String8 tmp(mime);
    tmp.toLower();
    for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) {
        if (tmp == MimeTypes[i]) {
            return true;
        }
    }
    return false;
}

bool FwdLockEngine::IsFileSuffixSupported(const String8& suffix) {
    String8 tmp(suffix);
    tmp.toLower();
    for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) {
        if (tmp == FileSuffixes[i]) {
            return true;
        }
    }
    return false;
}

DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
    DrmSupportInfo* pSupportInfo = new DrmSupportInfo();

    LOG_VERBOSE("FwdLockEngine::onGetSupportInfo");

    // fill all Forward Lock mimetypes and extensions
    if (NULL != pSupportInfo) {
        AddSupportedMimeTypes(pSupportInfo);
        AddSupportedFileSuffixes(pSupportInfo);
        pSupportInfo->setDescription(Description);
    }

    return pSupportInfo;
}

bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
    bool result = false;

    String8 extString = path.getPathExtension();
    return IsFileSuffixSupported(extString);
}

DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
    DrmInfoStatus *drmInfoStatus = NULL;

    // Nothing to process

    drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));

    LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo");

    return drmInfoStatus;
}

status_t FwdLockEngine::onSaveRights(
            int uniqueId,
            const DrmRights& drmRights,
            const String8& rightsPath,
            const String8& contentPath) {
    // No rights to save. Return
    LOG_VERBOSE("FwdLockEngine::onSaveRights");
    return DRM_ERROR_UNKNOWN;
}

DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
    DrmInfo* drmInfo = NULL;

    // Nothing to be done for Forward Lock file
    LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo");

    return drmInfo;
}

int FwdLockEngine::onCheckRightsStatus(int uniqueId,
                                       const String8& path,
                                       int action) {
    int result = RightsStatus::RIGHTS_INVALID;

    LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus");

    // Only Transfer action is not allowed for forward Lock files.
    if (onCanHandle(uniqueId, path)) {
        switch(action) {
            case Action::DEFAULT:
            case Action::PLAY:
            case Action::RINGTONE:
            case Action::OUTPUT:
            case Action::PREVIEW:
            case Action::EXECUTE:
            case Action::DISPLAY:
                result = RightsStatus::RIGHTS_VALID;
                break;

            case Action::TRANSFER:
            default:
                result = RightsStatus::RIGHTS_INVALID;
                break;
        }
    }

    return result;
}

status_t FwdLockEngine::onConsumeRights(int uniqueId,
                                        DecryptHandle* decryptHandle,
                                        int action,
                                        bool reserve) {
    // No rights consumption
    LOG_VERBOSE("FwdLockEngine::onConsumeRights");
    return DRM_NO_ERROR;
}

bool FwdLockEngine::onValidateAction(int uniqueId,
                                     const String8& path,
                                     int action,
                                     const ActionDescription& description) {
    LOG_VERBOSE("FwdLockEngine::onValidateAction");

    // For the forwardlock engine checkRights and ValidateAction are the same.
    return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
}

String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path, int fd) {
    LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType");
    String8 mimeString = String8("");
    int fileDesc = dup(fd);

    if (-1 < fileDesc) {
        if (FwdLockFile_attach(fileDesc) < 0) {
            close(fileDesc);
            return mimeString;
        }
        const char* pMimeType = FwdLockFile_GetContentType(fileDesc);

        if (NULL != pMimeType) {
            String8 contentType = String8(pMimeType);
            contentType.toLower();
            mimeString = MimeTypeUtil::convertMimeType(contentType);
        }

        FwdLockFile_close(fileDesc);
    }

    return mimeString;
}

int FwdLockEngine::onGetDrmObjectType(int uniqueId,
                                      const String8& path,
                                      const String8& mimeType) {
    String8 mimeStr = String8(mimeType);

    LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType");

    /* Checks whether
    * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown
    * 2. if one of them is empty string and if other is known then its a DRM Content Object.
    * 3. if both of them are available, then both may be of known type
    *    (regardless of the relation between them to make it compatible with other DRM Engines)
    */
    if (((0 == path.length()) || onCanHandle(uniqueId, path)) &&
        ((0 == mimeType.length()) || IsMimeTypeSupported(mimeType)) && (mimeType != path) ) {
            return DrmObjectType::CONTENT;
    }

    return DrmObjectType::UNKNOWN;
}

status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
    // No Rights to remove
    LOG_VERBOSE("FwdLockEngine::onRemoveRights");
    return DRM_NO_ERROR;
}

status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
    // No rights to remove
    LOG_VERBOSE("FwdLockEngine::onRemoveAllRights");
    return DRM_NO_ERROR;
}

#ifdef USE_64BIT_DRM_API
status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
                                            int playbackStatus, int64_t position) {
#else
status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
                                            int playbackStatus, int position) {
#endif
    // Not used
    LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus");
    return DRM_NO_ERROR;
}

status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
                                         int convertId) {
    status_t result = DRM_ERROR_UNKNOWN;
    LOG_VERBOSE("FwdLockEngine::onOpenConvertSession");
    if (!convertSessionMap.isCreated(convertId)) {
        ConvertSession *newSession = new ConvertSession();
        if (FwdLockConv_Status_OK ==
            FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) {
            convertSessionMap.addValue(convertId, newSession);
            result = DRM_NO_ERROR;
        } else {
            ALOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
            delete newSession;
        }
    }
    return result;
}

DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId,
                                                 int convertId,
                                                 const DrmBuffer* inputData) {
    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
    int offset = -1;

    if (NULL != inputData && convertSessionMap.isCreated(convertId)) {
        ConvertSession *convSession = convertSessionMap.getValue(convertId);

        if (NULL != convSession) {
            retStatus = FwdLockConv_ConvertData(convSession->uniqueId,
                                                inputData->data,
                                                inputData->length,
                                                &(convSession->output));

            if (FwdLockConv_Status_OK == retStatus) {
                // return bytes from conversion if available
                if (convSession->output.fromConvertData.numBytes > 0) {
                    convResult->data = new char[convSession->output.fromConvertData.numBytes];

                    if (NULL != convResult->data) {
                        convResult->length = convSession->output.fromConvertData.numBytes;
                        memcpy(convResult->data,
                               (char *)convSession->output.fromConvertData.pBuffer,
                               convResult->length);
                    }
                }
            } else {
                offset = convSession->output.fromConvertData.errorPos;
            }
        }
    }
    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
}

DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
                                                         int convertId) {
    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
    int offset = -1;

    LOG_VERBOSE("FwdLockEngine::onCloseConvertSession");

    if (convertSessionMap.isCreated(convertId)) {
        ConvertSession *convSession = convertSessionMap.getValue(convertId);

        if (NULL != convSession) {
            retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));

            if (FwdLockConv_Status_OK == retStatus) {
                offset = convSession->output.fromCloseSession.fileOffset;
                convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE];

                if (NULL != convResult->data) {
                      convResult->length = FWD_LOCK_SIGNATURES_SIZE;
                      memcpy(convResult->data,
                             (char *)convSession->output.fromCloseSession.signatures,
                             convResult->length);
                }
            }
        }
        convertSessionMap.removeValue(convertId);
    }
    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
}

#ifdef USE_64BIT_DRM_API
status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
                                             DecryptHandle* decryptHandle,
                                             int fd,
                                             off64_t offset,
                                             off64_t length) {
#else
status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
                                             DecryptHandle* decryptHandle,
                                             int fd,
                                             int offset,
                                             int length) {
#endif
    status_t result = DRM_ERROR_CANNOT_HANDLE;
    int fileDesc = -1;

    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession");

    if ((-1 < fd) &&
        (NULL != decryptHandle) &&
        (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
        fileDesc = dup(fd);
    } else {
        ALOGE("FwdLockEngine::onOpenDecryptSession parameter error");
        return result;
    }

    if (-1 < fileDesc &&
        -1 < ::lseek(fileDesc, offset, SEEK_SET) &&
        -1 < FwdLockFile_attach(fileDesc)) {
        // check for file integrity. This must be done to protect the content mangling.
        int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc);
        DecodeSession* decodeSession = new DecodeSession(fileDesc);

        if (retVal && NULL != decodeSession) {
            decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession);
            const char *pmime= FwdLockFile_GetContentType(fileDesc);
            String8 contentType = String8(pmime == NULL ? "" : pmime);
            contentType.toLower();
            decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType);
            decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED;
            decryptHandle->status = RightsStatus::RIGHTS_VALID;
            decryptHandle->decryptInfo = NULL;
            result = DRM_NO_ERROR;
        } else {
            LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
            FwdLockFile_detach(fileDesc);
            delete decodeSession;
        }
    }

    if (DRM_NO_ERROR != result && -1 < fileDesc) {
        ::close(fileDesc);
    }

    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);

    return result;
}

status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
                                             DecryptHandle* decryptHandle,
                                             const char* uri) {
    status_t result = DRM_ERROR_CANNOT_HANDLE;
    const char fileTag [] = "file://";

    if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) {
        String8 uriTag = String8(uri);
        uriTag.toLower();

        if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
            const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
            if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
                int fd = open(filePath, O_RDONLY);

                if (-1 < fd) {
                    // offset is always 0 and length is not used. so any positive size.
                    result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1);

                    // fd is duplicated already if success. closing the file
                    close(fd);
                }
            }
        }
    }

    return result;
}

status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
                                              DecryptHandle* decryptHandle) {
    status_t result = DRM_ERROR_UNKNOWN;
    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession");

    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
        if (NULL != session && session->fileDesc > -1) {
            FwdLockFile_detach(session->fileDesc);
            ::close(session->fileDesc);
            decodeSessionMap.removeValue(decryptHandle->decryptId);
            result = DRM_NO_ERROR;
        }
    }

    if (NULL != decryptHandle) {
        if (NULL != decryptHandle->decryptInfo) {
            delete decryptHandle->decryptInfo;
            decryptHandle->decryptInfo = NULL;
        }

        decryptHandle->copyControlVector.clear();
        decryptHandle->extendedData.clear();

        delete decryptHandle;
        decryptHandle = NULL;
    }

    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit");
    return result;
}

status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
                                                DecryptHandle* decryptHandle,
                                                int decryptUnitId,
                                                const DrmBuffer* headerInfo) {
    ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme");
    return DRM_ERROR_UNKNOWN;
}

status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
    ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
    return DRM_ERROR_UNKNOWN;
}

status_t FwdLockEngine::onDecrypt(int uniqueId,
                                  DecryptHandle* decryptHandle,
                                  int decryptUnitId,
                                  const DrmBuffer* encBuffer,
                                  DrmBuffer** decBuffer) {
    ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
    return DRM_ERROR_UNKNOWN;
}

status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
                                              DecryptHandle* decryptHandle,
                                              int decryptUnitId) {
    ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme");
    return DRM_ERROR_UNKNOWN;
}

ssize_t FwdLockEngine::onRead(int uniqueId,
                              DecryptHandle* decryptHandle,
                              void* buffer,
                              int numBytes) {
    ssize_t size = -1;

    if (NULL != decryptHandle &&
       decodeSessionMap.isCreated(decryptHandle->decryptId) &&
        NULL != buffer &&
        numBytes > -1) {
        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
        if (NULL != session && session->fileDesc > -1) {
            size = FwdLockFile_read(session->fileDesc, buffer, numBytes);

            if (0 > size) {
                session->offset = ((off_t)-1);
            } else {
                session->offset += size;
            }
        }
    }

    return size;
}

#ifdef USE_64BIT_DRM_API
off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
                               off64_t offset, int whence) {
#else
off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
                             off_t offset, int whence) {
#endif
    off_t offval = -1;

    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
        if (NULL != session && session->fileDesc > -1) {
            offval = FwdLockFile_lseek(session->fileDesc, offset, whence);
            session->offset = offval;
        }
    }

    return offval;
}

#ifdef USE_64BIT_DRM_API
ssize_t FwdLockEngine::onPread(int uniqueId,
                               DecryptHandle* decryptHandle,
                               void* buffer,
                               ssize_t numBytes,
                               off64_t offset) {
#else
ssize_t FwdLockEngine::onPread(int uniqueId,
                               DecryptHandle* decryptHandle,
                               void* buffer,
                               ssize_t numBytes,
                               off_t offset) {
#endif
    ssize_t bytesRead = -1;

    DecodeSession* decoderSession = NULL;

    if ((NULL != decryptHandle) &&
        (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) &&
        (NULL != buffer) &&
        (numBytes > -1) &&
        (offset > -1)) {
        if (offset != decoderSession->offset) {
            decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET);
        }

        if (((off_t)-1) != decoderSession->offset) {
            bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
            if (bytesRead < 0) {
                ALOGE("FwdLockEngine::onPread error reading");
            }
        }
    } else {
        ALOGE("FwdLockEngine::onPread decryptId not found");
    }

    return bytesRead;
}
