FwdLockEngine.cpp revision fdd65a0fc7df2c878cc601e4c0f4021cb264f051
15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/*
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Copyright (C) 2010 The Android Open Source Project
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Licensed under the Apache License, Version 2.0 (the "License");
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * you may not use this file except in compliance with the License.
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * You may obtain a copy of the License at
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *      http://www.apache.org/licenses/LICENSE-2.0
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Unless required by applicable law or agreed to in writing, software
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * distributed under the License is distributed on an "AS IS" BASIS,
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * See the License for the specific language governing permissions and
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * limitations under the License.
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "SessionMap.h"
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "FwdLockEngine.h"
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <utils/Log.h>
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <errno.h>
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <stdio.h>
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <unistd.h>
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "drm_framework_common.h"
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <fcntl.h>
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <limits.h>
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <DrmRights.h>
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <DrmConstraints.h>
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <DrmMetadata.h>
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <DrmInfo.h>
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <DrmInfoStatus.h>
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <DrmInfoRequest.h>
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <DrmSupportInfo.h>
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <DrmConvertedStatus.h>
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <utils/String8.h>
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "FwdLockConv.h"
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "FwdLockFile.h"
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "FwdLockGlue.h"
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "FwdLockEngineConst.h"
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "MimeTypeUtil.h"
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#undef LOG_TAG
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define LOG_TAG "FwdLockEngine"
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing namespace android;
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// This extern "C" is mandatory to be managed by TPlugInManager
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdochextern "C" IDrmEngine* create() {
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return new FwdLockEngine();
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// This extern "C" is mandatory to be managed by TPlugInManager
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuextern "C" void destroy(IDrmEngine* plugIn) {
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    delete plugIn;
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuFwdLockEngine::FwdLockEngine() {
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LOGD("FwdLockEngine Construction");
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
59116680a4aac90f2aa7413d9095a592090648e557Ben MurdochFwdLockEngine::~FwdLockEngine() {
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOGD("FwdLockEngine Destruction");
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    convertSessionMap.destroyMap();
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    decodeSessionMap.destroyMap();
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    int retStatus = DrmConvertedStatus::STATUS_ERROR;
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    switch(status) {
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        case FwdLockConv_Status_OK:
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            retStatus = DrmConvertedStatus::STATUS_OK;
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            break;
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        case FwdLockConv_Status_SyntaxError:
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        case FwdLockConv_Status_InvalidArgument:
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        case FwdLockConv_Status_UnsupportedFileFormat:
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        case FwdLockConv_Status_UnsupportedContentTransferEncoding:
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                  "Returning STATUS_INPUTDATA_ERROR", status);
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR;
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            break;
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        default:
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                  "Returning STATUS_ERROR", status);
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            retStatus = DrmConvertedStatus::STATUS_ERROR;
8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            break;
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return retStatus;
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuDrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DrmConstraints* drmConstraints = NULL;
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LOGD("FwdLockEngine::onGetConstraints");
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (NULL != path &&
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // Return the empty constraints to show no error condition.
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        drmConstraints = new DrmConstraints();
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return drmConstraints;
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DrmMetadata* drmMetadata = NULL;
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOGD("FwdLockEngine::onGetMetadata");
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (NULL != path) {
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // Returns empty metadata to show no error condition.
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        drmMetadata = new DrmMetadata();
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return drmMetadata;
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)android::status_t FwdLockEngine::onInitialize(int uniqueId) {
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOGD("FwdLockEngine::onInitialize");
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (FwdLockGlue_InitializeKeyEncryption()) {
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu             "errno = %d", errno);
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return DRM_NO_ERROR;
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuandroid::status_t
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuFwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Not used
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOGD("FwdLockEngine::onSetOnInfoListener");
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return DRM_NO_ERROR;
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdochandroid::status_t FwdLockEngine::onTerminate(int uniqueId) {
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOGD("FwdLockEngine::onTerminate");
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return DRM_NO_ERROR;
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOGD("FwdLockEngine::onGetSupportInfo");
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // fill all Forward Lock mimetypes and extensions
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (NULL != pSupportInfo) {
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pSupportInfo->addMimeType(String8(FWDLOCK_MIMETYPE_FL));
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pSupportInfo->addFileSuffix(String8(FWDLOCK_DOTEXTENSION_FL));
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        pSupportInfo->addMimeType(String8(FWDLOCK_MIMETYPE_DM));
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pSupportInfo->addFileSuffix(String8(FWDLOCK_DOTEXTENSION_DM));
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pSupportInfo->setDescription(String8(FWDLOCK_DESCRIPTION));
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return pSupportInfo;
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool result = false;
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    String8 extString = path.getPathExtension();
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    extString.toLower();
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if ((extString == String8(FWDLOCK_DOTEXTENSION_FL)) ||
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        (extString == String8(FWDLOCK_DOTEXTENSION_DM))) {
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        result = true;
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return result;
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DrmInfoStatus *drmInfoStatus = NULL;
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Nothing to process
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LOGD("FwdLockEngine::onProcessDrmInfo");
1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return drmInfoStatus;
1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatus_t FwdLockEngine::onSaveRights(
1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            int uniqueId,
1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            const DrmRights& drmRights,
1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            const String8& rightsPath,
1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            const String8& contentPath) {
195    // No rights to save. Return
196    LOGD("FwdLockEngine::onSaveRights");
197    return DRM_ERROR_UNKNOWN;
198}
199
200DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
201    DrmInfo* drmInfo = NULL;
202
203    // Nothing to be done for Forward Lock file
204    LOGD("FwdLockEngine::onAcquireDrmInfo");
205
206    return drmInfo;
207}
208
209int FwdLockEngine::onCheckRightsStatus(int uniqueId,
210                                       const String8& path,
211                                       int action) {
212    int result = RightsStatus::RIGHTS_INVALID;
213
214    LOGD("FwdLockEngine::onCheckRightsStatus");
215
216    // Only Transfer action is not allowed for forward Lock files.
217    if (onCanHandle(uniqueId, path)) {
218        switch(action) {
219            case Action::DEFAULT:
220            case Action::PLAY:
221            case Action::RINGTONE:
222            case Action::OUTPUT:
223            case Action::PREVIEW:
224            case Action::EXECUTE:
225            case Action::DISPLAY:
226                result = RightsStatus::RIGHTS_VALID;
227                break;
228
229            case Action::TRANSFER:
230            default:
231                result = RightsStatus::RIGHTS_INVALID;
232                break;
233        }
234    }
235
236    return result;
237}
238
239status_t FwdLockEngine::onConsumeRights(int uniqueId,
240                                        DecryptHandle* decryptHandle,
241                                        int action,
242                                        bool reserve) {
243    // No rights consumption
244    LOGD("FwdLockEngine::onConsumeRights");
245    return DRM_NO_ERROR;
246}
247
248bool FwdLockEngine::onValidateAction(int uniqueId,
249                                     const String8& path,
250                                     int action,
251                                     const ActionDescription& description) {
252    LOGD("FwdLockEngine::onValidateAction");
253
254    // For the forwardlock engine checkRights and ValidateAction are the same.
255    return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
256}
257
258String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
259    LOGD("FwdLockEngine::onGetOriginalMimeType");
260    String8 mimeString = String8("");
261    int fileDesc = FwdLockFile_open(path.string());
262
263    if (-1 < fileDesc) {
264        const char* pMimeType = FwdLockFile_GetContentType(fileDesc);
265
266        if (NULL != pMimeType) {
267            String8 contentType = String8(pMimeType);
268            contentType.toLower();
269            mimeString = MimeTypeUtil::convertMimeType(contentType);
270        }
271
272        FwdLockFile_close(fileDesc);
273    }
274
275    return mimeString;
276}
277
278int FwdLockEngine::onGetDrmObjectType(int uniqueId,
279                                      const String8& path,
280                                      const String8& mimeType) {
281    String8 mimeStr = String8(mimeType);
282
283    LOGD("FwdLockEngine::onGetDrmObjectType");
284
285    mimeStr.toLower();
286
287    /* Checks whether
288    * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown
289    * 2. if one of them is empty string and if other is known then its a DRM Content Object.
290    * 3. if both of them are available, then both may be of known type
291    *    (regardless of the relation between them to make it compatible with other DRM Engines)
292    */
293    if (((0 == path.length()) || onCanHandle(uniqueId, path)) &&
294        ((0 == mimeType.length()) || ((mimeStr == String8(FWDLOCK_MIMETYPE_FL)) ||
295        (mimeStr == String8(FWDLOCK_MIMETYPE_DM)))) && (mimeType != path) ) {
296            return DrmObjectType::CONTENT;
297    }
298
299    return DrmObjectType::UNKNOWN;
300}
301
302status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
303    // No Rights to remove
304    LOGD("FwdLockEngine::onRemoveRights");
305    return DRM_NO_ERROR;
306}
307
308status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
309    // No rights to remove
310    LOGD("FwdLockEngine::onRemoveAllRights");
311    return DRM_NO_ERROR;
312}
313
314#ifdef USE_64BIT_DRM_API
315status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
316                                            int playbackStatus, int64_t position) {
317#else
318status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
319                                            int playbackStatus, int position) {
320#endif
321    // Not used
322    LOGD("FwdLockEngine::onSetPlaybackStatus");
323    return DRM_NO_ERROR;
324}
325
326status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
327                                         int convertId) {
328    status_t result = DRM_ERROR_UNKNOWN;
329    LOGD("FwdLockEngine::onOpenConvertSession");
330    if (!convertSessionMap.isCreated(convertId)) {
331        ConvertSession *newSession = new ConvertSession();
332        if (FwdLockConv_Status_OK ==
333            FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) {
334            convertSessionMap.addValue(convertId, newSession);
335            result = DRM_NO_ERROR;
336        } else {
337            LOGD("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
338            delete newSession;
339        }
340    }
341    return result;
342}
343
344DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId,
345                                                 int convertId,
346                                                 const DrmBuffer* inputData) {
347    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
348    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
349    int offset = -1;
350
351    if (NULL != inputData && convertSessionMap.isCreated(convertId)) {
352        ConvertSession *convSession = convertSessionMap.getValue(convertId);
353
354        if (NULL != convSession) {
355            retStatus = FwdLockConv_ConvertData(convSession->uniqueId,
356                                                inputData->data,
357                                                inputData->length,
358                                                &(convSession->output));
359
360            if (FwdLockConv_Status_OK == retStatus) {
361                // return bytes from conversion if available
362                if (convSession->output.fromConvertData.numBytes > 0) {
363                    convResult->data = new char[convSession->output.fromConvertData.numBytes];
364
365                    if (NULL != convResult->data) {
366                        convResult->length = convSession->output.fromConvertData.numBytes;
367                        memcpy(convResult->data,
368                               (char *)convSession->output.fromConvertData.pBuffer,
369                               convResult->length);
370                    }
371                }
372            } else {
373                offset = convSession->output.fromConvertData.errorPos;
374            }
375        }
376    }
377    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
378}
379
380DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
381                                                         int convertId) {
382    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
383    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
384    int offset = -1;
385
386    LOGD("FwdLockEngine::onCloseConvertSession");
387
388    if (convertSessionMap.isCreated(convertId)) {
389        ConvertSession *convSession = convertSessionMap.getValue(convertId);
390
391        if (NULL != convSession) {
392            retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
393
394            if (FwdLockConv_Status_OK == retStatus) {
395                offset = convSession->output.fromCloseSession.fileOffset;
396                convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE];
397
398                if (NULL != convResult->data) {
399                      convResult->length = FWD_LOCK_SIGNATURES_SIZE;
400                      memcpy(convResult->data,
401                             (char *)convSession->output.fromCloseSession.signatures,
402                             convResult->length);
403                }
404            }
405        }
406        convertSessionMap.removeValue(convertId);
407    }
408    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
409}
410
411#ifdef USE_64BIT_DRM_API
412status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
413                                             DecryptHandle* decryptHandle,
414                                             int fd,
415                                             off64_t offset,
416                                             off64_t length) {
417#else
418status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
419                                             DecryptHandle* decryptHandle,
420                                             int fd,
421                                             int offset,
422                                             int length) {
423#endif
424    status_t result = DRM_ERROR_CANNOT_HANDLE;
425    int fileDesc = -1;
426
427    LOGD("FwdLockEngine::onOpenDecryptSession");
428
429    if ((-1 < fd) &&
430        (NULL != decryptHandle) &&
431        (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
432        fileDesc = dup(fd);
433    } else {
434        LOGD("FwdLockEngine::onOpenDecryptSession parameter error");
435        return result;
436    }
437
438    if (-1 < fileDesc &&
439        -1 < ::lseek(fileDesc, offset, SEEK_SET) &&
440        -1 < FwdLockFile_attach(fileDesc)) {
441        // check for file integrity. This must be done to protect the content mangling.
442        int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc);
443        DecodeSession* decodeSession = new DecodeSession(fileDesc);
444
445        if (retVal && NULL != decodeSession) {
446            decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession);
447            const char *pmime= FwdLockFile_GetContentType(fileDesc);
448            String8 contentType = String8(pmime == NULL ? "" : pmime);
449            contentType.toLower();
450            decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType);
451            decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED;
452            decryptHandle->status = RightsStatus::RIGHTS_VALID;
453            decryptHandle->decryptInfo = NULL;
454            result = DRM_NO_ERROR;
455        } else {
456            LOGD("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
457            FwdLockFile_detach(fileDesc);
458            ::close(fileDesc);
459            delete decodeSession;
460        }
461    }
462
463    LOGD("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
464
465    return result;
466}
467
468status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
469                                             DecryptHandle* decryptHandle,
470                                             const char* uri) {
471    status_t result = DRM_ERROR_CANNOT_HANDLE;
472    const char fileTag [] = "file://";
473
474    if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) {
475        String8 uriTag = String8(uri);
476        uriTag.toLower();
477
478        if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
479            const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
480            if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
481                int fd = open(filePath, O_RDONLY);
482
483                if (-1 < fd) {
484                    // offset is always 0 and length is not used. so any positive size.
485                    result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1);
486
487                    // fd is duplicated already if success. closing the file
488                    close(fd);
489                }
490            }
491        }
492    }
493
494    return result;
495}
496
497status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
498                                              DecryptHandle* decryptHandle) {
499    status_t result = DRM_ERROR_UNKNOWN;
500    LOGD("FwdLockEngine::onCloseDecryptSession");
501
502    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
503        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
504        if (NULL != session && session->fileDesc > -1) {
505            FwdLockFile_detach(session->fileDesc);
506            ::close(session->fileDesc);
507            decodeSessionMap.removeValue(decryptHandle->decryptId);
508            result = DRM_NO_ERROR;
509        }
510    }
511
512    LOGD("FwdLockEngine::onCloseDecryptSession Exit");
513    return result;
514}
515
516status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
517                                                DecryptHandle* decryptHandle,
518                                                int decryptUnitId,
519                                                const DrmBuffer* headerInfo) {
520    LOGD("FwdLockEngine::onInitializeDecryptUnit");
521    return DRM_ERROR_UNKNOWN;
522}
523
524status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
525            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
526    LOGD("FwdLockEngine::onDecrypt");
527    return DRM_ERROR_UNKNOWN;
528}
529
530status_t FwdLockEngine::onDecrypt(int uniqueId,
531                                  DecryptHandle* decryptHandle,
532                                  int decryptUnitId,
533                                  const DrmBuffer* encBuffer,
534                                  DrmBuffer** decBuffer) {
535    LOGD("FwdLockEngine::onDecrypt");
536    return DRM_ERROR_UNKNOWN;
537}
538
539status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
540                                              DecryptHandle* decryptHandle,
541                                              int decryptUnitId) {
542    LOGD("FwdLockEngine::onFinalizeDecryptUnit");
543    return DRM_ERROR_UNKNOWN;
544}
545
546ssize_t FwdLockEngine::onRead(int uniqueId,
547                              DecryptHandle* decryptHandle,
548                              void* buffer,
549                              int numBytes) {
550    ssize_t size = -1;
551
552    if (NULL != decryptHandle &&
553       decodeSessionMap.isCreated(decryptHandle->decryptId) &&
554        NULL != buffer &&
555        numBytes > -1) {
556        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
557        if (NULL != session && session->fileDesc > -1) {
558            size = FwdLockFile_read(session->fileDesc, buffer, numBytes);
559
560            if (0 > size) {
561                session->offset = ((off_t)-1);
562            } else {
563                session->offset += size;
564            }
565        }
566    }
567
568    return size;
569}
570
571#ifdef USE_64BIT_DRM_API
572off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
573                               off64_t offset, int whence) {
574#else
575off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
576                             off_t offset, int whence) {
577#endif
578    off_t offval = -1;
579
580    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
581        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
582        if (NULL != session && session->fileDesc > -1) {
583            offval = FwdLockFile_lseek(session->fileDesc, offset, whence);
584            session->offset = offval;
585        }
586    }
587
588    return offval;
589}
590
591#ifdef USE_64BIT_DRM_API
592ssize_t FwdLockEngine::onPread(int uniqueId,
593                               DecryptHandle* decryptHandle,
594                               void* buffer,
595                               ssize_t numBytes,
596                               off64_t offset) {
597#else
598ssize_t FwdLockEngine::onPread(int uniqueId,
599                               DecryptHandle* decryptHandle,
600                               void* buffer,
601                               ssize_t numBytes,
602                               off_t offset) {
603#endif
604    ssize_t bytesRead = -1;
605
606    DecodeSession* decoderSession = NULL;
607
608    if ((NULL != decryptHandle) &&
609        (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) &&
610        (NULL != buffer) &&
611        (numBytes > -1) &&
612        (offset > -1)) {
613        if (offset != decoderSession->offset) {
614            decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET);
615        }
616
617        if (((off_t)-1) != decoderSession->offset) {
618            bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
619            if (bytesRead < 0) {
620                LOGD("FwdLockEngine::onPread error reading");
621            }
622        }
623    } else {
624        LOGD("FwdLockEngine::onPread decryptId not found");
625    }
626
627    return bytesRead;
628}
629