diff options
| author | Anatol Pomozov <anatol.pomozov@gmail.com> | 2012-03-28 09:12:55 -0700 | 
|---|---|---|
| committer | Anatol Pomozov <anatol.pomozov@gmail.com> | 2012-03-28 12:02:47 -0700 | 
| commit | b0b2b4d890cf3bfb274797a759642b4e733343d7 (patch) | |
| tree | 12ad21cbad346f02d542aa4d672ffd76407d58a9 /drm/drmserver | |
| parent | 51f8eec23a2bcc2cc190373cdd1195972d9b8804 (diff) | |
| parent | 5a5491c17d74bd2c80cf451c6ddbba22d5d5f08a (diff) | |
| download | frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.zip frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.tar.gz frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.tar.bz2  | |
Merge media files with history from frameworks/base.git
Diffstat (limited to 'drm/drmserver')
| -rw-r--r-- | drm/drmserver/Android.mk | 41 | ||||
| -rw-r--r-- | drm/drmserver/DrmManager.cpp | 606 | ||||
| -rw-r--r-- | drm/drmserver/DrmManagerService.cpp | 308 | ||||
| -rw-r--r-- | drm/drmserver/main_drmserver.cpp | 38 | 
4 files changed, 993 insertions, 0 deletions
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk new file mode 100644 index 0000000..fd417cb --- /dev/null +++ b/drm/drmserver/Android.mk @@ -0,0 +1,41 @@ +# +# 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. +# +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ +    main_drmserver.cpp \ +    DrmManager.cpp \ +    DrmManagerService.cpp + +LOCAL_SHARED_LIBRARIES := \ +    libmedia \ +    libutils \ +    libbinder \ +    libdl + +LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon + +LOCAL_C_INCLUDES := \ +    $(TOP)/frameworks/base/include \ +    $(TOP)/frameworks/base/drm/libdrmframework/include \ +    $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include + +LOCAL_MODULE:= drmserver + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_EXECUTABLE) diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp new file mode 100644 index 0000000..999295a --- /dev/null +++ b/drm/drmserver/DrmManager.cpp @@ -0,0 +1,606 @@ +/* + * 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 "DrmManager(Native)" +#include "utils/Log.h" + +#include <utils/String8.h> +#include <drm/DrmInfo.h> +#include <drm/DrmInfoEvent.h> +#include <drm/DrmRights.h> +#include <drm/DrmConstraints.h> +#include <drm/DrmMetadata.h> +#include <drm/DrmInfoStatus.h> +#include <drm/DrmInfoRequest.h> +#include <drm/DrmSupportInfo.h> +#include <drm/DrmConvertedStatus.h> +#include <IDrmEngine.h> + +#include "DrmManager.h" +#include "ReadWriteUtils.h" + +#define DECRYPT_FILE_ERROR -1 + +using namespace android; + +const String8 DrmManager::EMPTY_STRING(""); + +DrmManager::DrmManager() : +    mDecryptSessionId(0), +    mConvertId(0) { + +} + +DrmManager::~DrmManager() { + +} + +int DrmManager::addUniqueId(bool isNative) { +    Mutex::Autolock _l(mLock); + +    int temp = 0; +    bool foundUniqueId = false; +    const int size = mUniqueIdVector.size(); +    const int uniqueIdRange = 0xfff; +    int maxLoopTimes = (uniqueIdRange - 1) / 2; +    srand(time(NULL)); + +    while (!foundUniqueId) { +        temp = rand() & uniqueIdRange; + +        if (isNative) { +            // set a flag to differentiate DrmManagerClient +            // created from native side and java side +            temp |= 0x1000; +        } + +        int index = 0; +        for (; index < size; ++index) { +            if (mUniqueIdVector.itemAt(index) == temp) { +                foundUniqueId = false; +                break; +            } +        } +        if (index == size) { +            foundUniqueId = true; +        } + +        maxLoopTimes --; +        LOG_FATAL_IF(maxLoopTimes <= 0, "cannot find an unique ID for this session"); +    } + +    mUniqueIdVector.push(temp); +    return temp; +} + +void DrmManager::removeUniqueId(int uniqueId) { +    Mutex::Autolock _l(mLock); +    for (unsigned int i = 0; i < mUniqueIdVector.size(); i++) { +        if (uniqueId == mUniqueIdVector.itemAt(i)) { +            mUniqueIdVector.removeAt(i); +            break; +        } +    } +} + +status_t DrmManager::loadPlugIns() { + +    String8 vendorPluginDirPath("/vendor/lib/drm"); +    loadPlugIns(vendorPluginDirPath); + +    String8 pluginDirPath("/system/lib/drm"); +    loadPlugIns(pluginDirPath); +    return DRM_NO_ERROR; + +} + +status_t DrmManager::loadPlugIns(const String8& plugInDirPath) { +    mPlugInManager.loadPlugIns(plugInDirPath); +    Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); +    for (unsigned int i = 0; i < plugInPathList.size(); ++i) { +        String8 plugInPath = plugInPathList[i]; +        DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0); +        if (NULL != info) { +            if (mSupportInfoToPlugInIdMap.indexOfKey(*info) < 0) { +                mSupportInfoToPlugInIdMap.add(*info, plugInPath); +            } +            delete info; +        } +    } +    return DRM_NO_ERROR; +} + +status_t DrmManager::unloadPlugIns() { +    Mutex::Autolock _l(mLock); +    mConvertSessionMap.clear(); +    mDecryptSessionMap.clear(); +    mPlugInManager.unloadPlugIns(); +    mSupportInfoToPlugInIdMap.clear(); +    return DRM_NO_ERROR; +} + +status_t DrmManager::setDrmServiceListener( +            int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) { +    Mutex::Autolock _l(mListenerLock); +    if (NULL != drmServiceListener.get()) { +        mServiceListeners.add(uniqueId, drmServiceListener); +    } else { +        mServiceListeners.removeItem(uniqueId); +    } +    return DRM_NO_ERROR; +} + +void DrmManager::addClient(int uniqueId) { +    Mutex::Autolock _l(mLock); +    if (!mSupportInfoToPlugInIdMap.isEmpty()) { +        Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); +        for (unsigned int index = 0; index < plugInIdList.size(); index++) { +            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); +            rDrmEngine.initialize(uniqueId); +            rDrmEngine.setOnInfoListener(uniqueId, this); +        } +    } +} + +void DrmManager::removeClient(int uniqueId) { +    Mutex::Autolock _l(mLock); +    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); +    for (unsigned int index = 0; index < plugInIdList.size(); index++) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); +        rDrmEngine.terminate(uniqueId); +    } +} + +DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        return rDrmEngine.getConstraints(uniqueId, path, action); +    } +    return NULL; +} + +DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        return rDrmEngine.getMetadata(uniqueId, path); +    } +    return NULL; +} + +status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath) { +    Mutex::Autolock _l(mLock); +    mPlugInManager.loadPlugIn(absolutePath); + +    IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(absolutePath); +    rDrmEngine.initialize(uniqueId); +    rDrmEngine.setOnInfoListener(uniqueId, this); + +    DrmSupportInfo* info = rDrmEngine.getSupportInfo(0); +    mSupportInfoToPlugInIdMap.add(*info, absolutePath); +    delete info; + +    return DRM_NO_ERROR; +} + +bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInId(mimeType); +    bool result = (EMPTY_STRING != plugInId) ? true : false; + +    if (0 < path.length()) { +        if (result) { +            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +            result = rDrmEngine.canHandle(uniqueId, path); +        } else { +            String8 extension = path.getPathExtension(); +            if (String8("") != extension) { +                result = canHandle(uniqueId, path); +            } +        } +    } +    return result; +} + +DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType()); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        return rDrmEngine.processDrmInfo(uniqueId, drmInfo); +    } +    return NULL; +} + +bool DrmManager::canHandle(int uniqueId, const String8& path) { +    bool result = false; +    Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); + +    for (unsigned int i = 0; i < plugInPathList.size(); ++i) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]); +        result = rDrmEngine.canHandle(uniqueId, path); + +        if (result) { +            break; +        } +    } +    return result; +} + +DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType()); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        return rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest); +    } +    return NULL; +} + +status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights, +            const String8& rightsPath, const String8& contentPath) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType()); +    status_t result = DRM_ERROR_UNKNOWN; +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath); +    } +    return result; +} + +String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        return rDrmEngine.getOriginalMimeType(uniqueId, path); +    } +    return EMPTY_STRING; +} + +int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        return rDrmEngine.getDrmObjectType(uniqueId, path, mimeType); +    } +    return DrmObjectType::UNKNOWN; +} + +int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        return rDrmEngine.checkRightsStatus(uniqueId, path, action); +    } +    return RightsStatus::RIGHTS_INVALID; +} + +status_t DrmManager::consumeRights( +    int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { +    status_t result = DRM_ERROR_UNKNOWN; +    Mutex::Autolock _l(mDecryptLock); +    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); +        result = drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve); +    } +    return result; +} + +status_t DrmManager::setPlaybackStatus( +    int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { +    status_t result = DRM_ERROR_UNKNOWN; +    Mutex::Autolock _l(mDecryptLock); +    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); +        result = drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position); +    } +    return result; +} + +bool DrmManager::validateAction( +    int uniqueId, const String8& path, int action, const ActionDescription& description) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        return rDrmEngine.validateAction(uniqueId, path, action, description); +    } +    return false; +} + +status_t DrmManager::removeRights(int uniqueId, const String8& path) { +    Mutex::Autolock _l(mLock); +    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); +    status_t result = DRM_ERROR_UNKNOWN; +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +        result = rDrmEngine.removeRights(uniqueId, path); +    } +    return result; +} + +status_t DrmManager::removeAllRights(int uniqueId) { +    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); +    status_t result = DRM_ERROR_UNKNOWN; +    for (unsigned int index = 0; index < plugInIdList.size(); index++) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); +        result = rDrmEngine.removeAllRights(uniqueId); +        if (DRM_NO_ERROR != result) { +            break; +        } +    } +    return result; +} + +int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) { +    Mutex::Autolock _l(mConvertLock); +    int convertId = -1; + +    const String8 plugInId = getSupportedPlugInId(mimeType); +    if (EMPTY_STRING != plugInId) { +        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); + +        if (DRM_NO_ERROR == rDrmEngine.openConvertSession(uniqueId, mConvertId + 1)) { +            ++mConvertId; +            convertId = mConvertId; +            mConvertSessionMap.add(convertId, &rDrmEngine); +        } +    } +    return convertId; +} + +DrmConvertedStatus* DrmManager::convertData( +            int uniqueId, int convertId, const DrmBuffer* inputData) { +    DrmConvertedStatus *drmConvertedStatus = NULL; + +    Mutex::Autolock _l(mConvertLock); +    if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId); +        drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData); +    } +    return drmConvertedStatus; +} + +DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) { +    Mutex::Autolock _l(mConvertLock); +    DrmConvertedStatus *drmConvertedStatus = NULL; + +    if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId); +        drmConvertedStatus = drmEngine->closeConvertSession(uniqueId, convertId); +        mConvertSessionMap.removeItem(convertId); +    } +    return drmConvertedStatus; +} + +status_t DrmManager::getAllSupportInfo( +                    int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) { +    Mutex::Autolock _l(mLock); +    Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); +    int size = plugInPathList.size(); +    int validPlugins = 0; + +    if (0 < size) { +        Vector<DrmSupportInfo> drmSupportInfoList; + +        for (int i = 0; i < size; ++i) { +            String8 plugInPath = plugInPathList[i]; +            DrmSupportInfo* drmSupportInfo +                = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0); +            if (NULL != drmSupportInfo) { +                drmSupportInfoList.add(*drmSupportInfo); +                delete drmSupportInfo; drmSupportInfo = NULL; +            } +        } + +        validPlugins = drmSupportInfoList.size(); +        if (0 < validPlugins) { +            *drmSupportInfoArray = new DrmSupportInfo[validPlugins]; +            for (int i = 0; i < validPlugins; ++i) { +                (*drmSupportInfoArray)[i] = drmSupportInfoList[i]; +            } +        } +    } +    *length = validPlugins; +    return DRM_NO_ERROR; +} + +DecryptHandle* DrmManager::openDecryptSession( +        int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) { + +    Mutex::Autolock _l(mDecryptLock); +    status_t result = DRM_ERROR_CANNOT_HANDLE; +    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); + +    DecryptHandle* handle = new DecryptHandle(); +    if (NULL != handle) { +        handle->decryptId = mDecryptSessionId + 1; + +        for (unsigned int index = 0; index < plugInIdList.size(); index++) { +            String8 plugInId = plugInIdList.itemAt(index); +            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +            result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length, mime); + +            if (DRM_NO_ERROR == result) { +                ++mDecryptSessionId; +                mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine); +                break; +            } +        } +    } +    if (DRM_NO_ERROR != result) { +        delete handle; handle = NULL; +    } +    return handle; +} + +DecryptHandle* DrmManager::openDecryptSession( +        int uniqueId, const char* uri, const char* mime) { +    Mutex::Autolock _l(mDecryptLock); +    status_t result = DRM_ERROR_CANNOT_HANDLE; +    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); + +    DecryptHandle* handle = new DecryptHandle(); +    if (NULL != handle) { +        handle->decryptId = mDecryptSessionId + 1; + +        for (unsigned int index = 0; index < plugInIdList.size(); index++) { +            String8 plugInId = plugInIdList.itemAt(index); +            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); +            result = rDrmEngine.openDecryptSession(uniqueId, handle, uri, mime); + +            if (DRM_NO_ERROR == result) { +                ++mDecryptSessionId; +                mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine); +                break; +            } +        } +    } +    if (DRM_NO_ERROR != result) { +        delete handle; handle = NULL; +        ALOGV("DrmManager::openDecryptSession: no capable plug-in found"); +    } +    return handle; +} + +status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { +    Mutex::Autolock _l(mDecryptLock); +    status_t result = DRM_ERROR_UNKNOWN; +    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); +        result = drmEngine->closeDecryptSession(uniqueId, decryptHandle); +        if (DRM_NO_ERROR == result) { +            mDecryptSessionMap.removeItem(decryptHandle->decryptId); +        } +    } +    return result; +} + +status_t DrmManager::initializeDecryptUnit( +    int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { +    status_t result = DRM_ERROR_UNKNOWN; +    Mutex::Autolock _l(mDecryptLock); +    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); +        result = drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo); +    } +    return result; +} + +status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, +            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { +    status_t result = DRM_ERROR_UNKNOWN; + +    Mutex::Autolock _l(mDecryptLock); +    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); +        result = drmEngine->decrypt( +                uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV); +    } +    return result; +} + +status_t DrmManager::finalizeDecryptUnit( +            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { +    status_t result = DRM_ERROR_UNKNOWN; +    Mutex::Autolock _l(mDecryptLock); +    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); +        result = drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId); +    } +    return result; +} + +ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle, +            void* buffer, ssize_t numBytes, off64_t offset) { +    ssize_t result = DECRYPT_FILE_ERROR; + +    Mutex::Autolock _l(mDecryptLock); +    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { +        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); +        result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset); +    } +    return result; +} + +String8 DrmManager::getSupportedPlugInId( +            int uniqueId, const String8& path, const String8& mimeType) { +    String8 plugInId(""); + +    if (EMPTY_STRING != mimeType) { +        plugInId = getSupportedPlugInId(mimeType); +    } else { +        plugInId = getSupportedPlugInIdFromPath(uniqueId, path); +    } +    return plugInId; +} + +String8 DrmManager::getSupportedPlugInId(const String8& mimeType) { +    String8 plugInId(""); + +    if (EMPTY_STRING != mimeType) { +        for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) { +            const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index); + +            if (drmSupportInfo.isSupportedMimeType(mimeType)) { +                plugInId = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo); +                break; +            } +        } +    } +    return plugInId; +} + +String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) { +    String8 plugInId(""); +    const String8 fileSuffix = path.getPathExtension(); + +    for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) { +        const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index); + +        if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) { +            String8 key = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo); +            IDrmEngine& drmEngine = mPlugInManager.getPlugIn(key); + +            if (drmEngine.canHandle(uniqueId, path)) { +                plugInId = key; +                break; +            } +        } +    } +    return plugInId; +} + +void DrmManager::onInfo(const DrmInfoEvent& event) { +    Mutex::Autolock _l(mListenerLock); +    for (unsigned int index = 0; index < mServiceListeners.size(); index++) { +        int uniqueId = mServiceListeners.keyAt(index); + +        if (uniqueId == event.getUniqueId()) { +            sp<IDrmServiceListener> serviceListener = mServiceListeners.valueFor(uniqueId); +            serviceListener->notify(event); +        } +    } +} + diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp new file mode 100644 index 0000000..8ba0203 --- /dev/null +++ b/drm/drmserver/DrmManagerService.cpp @@ -0,0 +1,308 @@ +/* + * 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 "DrmManagerService(Native)" +#include <utils/Log.h> + +#include <private/android_filesystem_config.h> +#include <media/MemoryLeakTrackUtil.h> + +#include <errno.h> +#include <utils/threads.h> +#include <binder/IServiceManager.h> +#include <binder/IPCThreadState.h> +#include <sys/stat.h> +#include "DrmManagerService.h" +#include "DrmManager.h" + +using namespace android; + +static Vector<uid_t> trustedUids; + +static bool isProtectedCallAllowed() { +    // TODO +    // Following implementation is just for reference. +    // Each OEM manufacturer should implement/replace with their own solutions. +    bool result = false; + +    IPCThreadState* ipcState = IPCThreadState::self(); +    uid_t uid = ipcState->getCallingUid(); + +    for (unsigned int i = 0; i < trustedUids.size(); ++i) { +        if (trustedUids[i] == uid) { +            result = true; +            break; +        } +    } +    return result; +} + +void DrmManagerService::instantiate() { +    ALOGV("instantiate"); +    defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService()); + +    if (0 >= trustedUids.size()) { +        // TODO +        // Following implementation is just for reference. +        // Each OEM manufacturer should implement/replace with their own solutions. + +        // Add trusted uids here +        trustedUids.push(AID_MEDIA); +    } +} + +DrmManagerService::DrmManagerService() : +        mDrmManager(NULL) { +    ALOGV("created"); +    mDrmManager = new DrmManager(); +    mDrmManager->loadPlugIns(); +} + +DrmManagerService::~DrmManagerService() { +    ALOGV("Destroyed"); +    mDrmManager->unloadPlugIns(); +    delete mDrmManager; mDrmManager = NULL; +} + +int DrmManagerService::addUniqueId(bool isNative) { +    return mDrmManager->addUniqueId(isNative); +} + +void DrmManagerService::removeUniqueId(int uniqueId) { +    mDrmManager->removeUniqueId(uniqueId); +} + +void DrmManagerService::addClient(int uniqueId) { +    mDrmManager->addClient(uniqueId); +} + +void DrmManagerService::removeClient(int uniqueId) { +    mDrmManager->removeClient(uniqueId); +} + +status_t DrmManagerService::setDrmServiceListener( +            int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) { +    ALOGV("Entering setDrmServiceListener"); +    mDrmManager->setDrmServiceListener(uniqueId, drmServiceListener); +    return DRM_NO_ERROR; +} + +status_t DrmManagerService::installDrmEngine(int uniqueId, const String8& drmEngineFile) { +    ALOGV("Entering installDrmEngine"); +    return mDrmManager->installDrmEngine(uniqueId, drmEngineFile); +} + +DrmConstraints* DrmManagerService::getConstraints( +            int uniqueId, const String8* path, const int action) { +    ALOGV("Entering getConstraints from content"); +    return mDrmManager->getConstraints(uniqueId, path, action); +} + +DrmMetadata* DrmManagerService::getMetadata(int uniqueId, const String8* path) { +    ALOGV("Entering getMetadata from content"); +    return mDrmManager->getMetadata(uniqueId, path); +} + +bool DrmManagerService::canHandle(int uniqueId, const String8& path, const String8& mimeType) { +    ALOGV("Entering canHandle"); +    return mDrmManager->canHandle(uniqueId, path, mimeType); +} + +DrmInfoStatus* DrmManagerService::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) { +    ALOGV("Entering processDrmInfo"); +    return mDrmManager->processDrmInfo(uniqueId, drmInfo); +} + +DrmInfo* DrmManagerService::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) { +    ALOGV("Entering acquireDrmInfo"); +    return mDrmManager->acquireDrmInfo(uniqueId, drmInfoRequest); +} + +status_t DrmManagerService::saveRights( +            int uniqueId, const DrmRights& drmRights, +            const String8& rightsPath, const String8& contentPath) { +    ALOGV("Entering saveRights"); +    return mDrmManager->saveRights(uniqueId, drmRights, rightsPath, contentPath); +} + +String8 DrmManagerService::getOriginalMimeType(int uniqueId, const String8& path) { +    ALOGV("Entering getOriginalMimeType"); +    return mDrmManager->getOriginalMimeType(uniqueId, path); +} + +int DrmManagerService::getDrmObjectType( +           int uniqueId, const String8& path, const String8& mimeType) { +    ALOGV("Entering getDrmObjectType"); +    return mDrmManager->getDrmObjectType(uniqueId, path, mimeType); +} + +int DrmManagerService::checkRightsStatus( +            int uniqueId, const String8& path, int action) { +    ALOGV("Entering checkRightsStatus"); +    return mDrmManager->checkRightsStatus(uniqueId, path, action); +} + +status_t DrmManagerService::consumeRights( +            int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { +    ALOGV("Entering consumeRights"); +    if (!isProtectedCallAllowed()) { +        return DRM_ERROR_NO_PERMISSION; +    } +    return mDrmManager->consumeRights(uniqueId, decryptHandle, action, reserve); +} + +status_t DrmManagerService::setPlaybackStatus( +            int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { +    ALOGV("Entering setPlaybackStatus"); +    if (!isProtectedCallAllowed()) { +        return DRM_ERROR_NO_PERMISSION; +    } +    return mDrmManager->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position); +} + +bool DrmManagerService::validateAction( +            int uniqueId, const String8& path, +            int action, const ActionDescription& description) { +    ALOGV("Entering validateAction"); +    return mDrmManager->validateAction(uniqueId, path, action, description); +} + +status_t DrmManagerService::removeRights(int uniqueId, const String8& path) { +    ALOGV("Entering removeRights"); +    return mDrmManager->removeRights(uniqueId, path); +} + +status_t DrmManagerService::removeAllRights(int uniqueId) { +    ALOGV("Entering removeAllRights"); +    return mDrmManager->removeAllRights(uniqueId); +} + +int DrmManagerService::openConvertSession(int uniqueId, const String8& mimeType) { +    ALOGV("Entering openConvertSession"); +    return mDrmManager->openConvertSession(uniqueId, mimeType); +} + +DrmConvertedStatus* DrmManagerService::convertData( +            int uniqueId, int convertId, const DrmBuffer* inputData) { +    ALOGV("Entering convertData"); +    return mDrmManager->convertData(uniqueId, convertId, inputData); +} + +DrmConvertedStatus* DrmManagerService::closeConvertSession(int uniqueId, int convertId) { +    ALOGV("Entering closeConvertSession"); +    return mDrmManager->closeConvertSession(uniqueId, convertId); +} + +status_t DrmManagerService::getAllSupportInfo( +            int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) { +    ALOGV("Entering getAllSupportInfo"); +    return mDrmManager->getAllSupportInfo(uniqueId, length, drmSupportInfoArray); +} + +DecryptHandle* DrmManagerService::openDecryptSession( +            int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) { +    ALOGV("Entering DrmManagerService::openDecryptSession"); +    if (isProtectedCallAllowed()) { +        return mDrmManager->openDecryptSession(uniqueId, fd, offset, length, mime); +    } + +    return NULL; +} + +DecryptHandle* DrmManagerService::openDecryptSession( +            int uniqueId, const char* uri, const char* mime) { +    ALOGV("Entering DrmManagerService::openDecryptSession with uri"); +    if (isProtectedCallAllowed()) { +        return mDrmManager->openDecryptSession(uniqueId, uri, mime); +    } + +    return NULL; +} + +status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { +    ALOGV("Entering closeDecryptSession"); +    if (!isProtectedCallAllowed()) { +        return DRM_ERROR_NO_PERMISSION; +    } +    return mDrmManager->closeDecryptSession(uniqueId, decryptHandle); +} + +status_t DrmManagerService::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, +            int decryptUnitId, const DrmBuffer* headerInfo) { +    ALOGV("Entering initializeDecryptUnit"); +    if (!isProtectedCallAllowed()) { +        return DRM_ERROR_NO_PERMISSION; +    } +    return mDrmManager->initializeDecryptUnit(uniqueId,decryptHandle, decryptUnitId, headerInfo); +} + +status_t DrmManagerService::decrypt( +            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, +            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { +    ALOGV("Entering decrypt"); +    if (!isProtectedCallAllowed()) { +        return DRM_ERROR_NO_PERMISSION; +    } +    return mDrmManager->decrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV); +} + +status_t DrmManagerService::finalizeDecryptUnit( +            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { +    ALOGV("Entering finalizeDecryptUnit"); +    if (!isProtectedCallAllowed()) { +        return DRM_ERROR_NO_PERMISSION; +    } +    return mDrmManager->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId); +} + +ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle, +            void* buffer, ssize_t numBytes, off64_t offset) { +    ALOGV("Entering pread"); +    if (!isProtectedCallAllowed()) { +        return DRM_ERROR_NO_PERMISSION; +    } +    return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset); +} + +status_t DrmManagerService::dump(int fd, const Vector<String16>& args) +{ +    const size_t SIZE = 256; +    char buffer[SIZE]; +    String8 result; +    if (checkCallingPermission(String16("android.permission.DUMP")) == false) { +        snprintf(buffer, SIZE, "Permission Denial: " +                "can't dump DrmManagerService from pid=%d, uid=%d\n", +                IPCThreadState::self()->getCallingPid(), +                IPCThreadState::self()->getCallingUid()); +        result.append(buffer); +    } else { +#if DRM_MEMORY_LEAK_TRACK +        bool dumpMem = false; +        for (size_t i = 0; i < args.size(); i++) { +            if (args[i] == String16("-m")) { +                dumpMem = true; +            } +        } +        if (dumpMem) { +            dumpMemoryAddresses(fd); +        } +#endif +    } +    write(fd, result.string(), result.size()); +    return NO_ERROR; +} + diff --git a/drm/drmserver/main_drmserver.cpp b/drm/drmserver/main_drmserver.cpp new file mode 100644 index 0000000..434d561 --- /dev/null +++ b/drm/drmserver/main_drmserver.cpp @@ -0,0 +1,38 @@ +/* + * 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_TAG "drmserver" +//#define LOG_NDEBUG 0 + +#include <binder/IPCThreadState.h> +#include <binder/ProcessState.h> +#include <binder/IServiceManager.h> +#include <utils/Log.h> + +#include <DrmManagerService.h> + +using namespace android; + +int main(int argc, char** argv) +{ +    sp<ProcessState> proc(ProcessState::self()); +    sp<IServiceManager> sm = defaultServiceManager(); +    ALOGV("ServiceManager: %p", sm.get()); +    DrmManagerService::instantiate(); +    ProcessState::self()->startThreadPool(); +    IPCThreadState::self()->joinThreadPool(); +} +  | 
