// // Copyright 2013 Google Inc. All Rights Reserved. // //#define LOG_NDEBUG 0 #define LOG_TAG "WVCdm" #include #include "WVDrmPlugin.h" #include #include #include "utils/Errors.h" #include "wv_cdm_constants.h" namespace wvdrm { using namespace android; using namespace std; using namespace wvcdm; WVDrmPlugin::WVDrmPlugin(WvContentDecryptionModule* cdm) : mCDM(cdm) {} status_t WVDrmPlugin::openSession(Vector& sessionId) { CdmSessionId cdmSessionId; CdmResponseType res = mCDM->OpenSession("com.widevine", &cdmSessionId); if (res != wvcdm::NO_ERROR) { return android::UNKNOWN_ERROR; } sessionId.clear(); sessionId.appendArray(reinterpret_cast(cdmSessionId.data()), cdmSessionId.size()); return android::OK; } status_t WVDrmPlugin::closeSession(const Vector& sessionId) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); CdmResponseType res = mCDM->CloseSession(cdmSessionId); if (res == wvcdm::NO_ERROR) { return android::OK; } else { return android::UNKNOWN_ERROR; } } status_t WVDrmPlugin::getLicenseRequest( const Vector& sessionId, const Vector& initData, const String8& mimeType, LicenseType licenseType, const KeyedVector& optionalParameters, Vector& request, String8& defaultUrl) { CdmLicenseType cdmLicenseType; if (licenseType == kLicenseType_Offline) { cdmLicenseType = kLicenseTypeOffline; } else if (licenseType == kLicenseType_Streaming) { cdmLicenseType = kLicenseTypeStreaming; } else { return BAD_TYPE; } CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); CdmInitData cdmInitData(initData.begin(), initData.end()); // TODO: Do something with mimeType? CdmNameValueMap cdmParameters; for (size_t i = 0; i < optionalParameters.size(); ++i) { const String8& key = optionalParameters.keyAt(i); const String8& value = optionalParameters.valueAt(i); string cdmKey(key.string(), key.size()); string cdmValue(value.string(), value.size()); cdmParameters[cdmKey] = cdmValue; } CdmKeyMessage keyRequest; CdmResponseType res = mCDM->GenerateKeyRequest(cdmSessionId, cdmInitData, cdmLicenseType, cdmParameters, &keyRequest); if (res != wvcdm::KEY_MESSAGE) { return android::UNKNOWN_ERROR; } // TODO: Do something more with defaultUrl? defaultUrl.clear(); request.clear(); request.appendArray(reinterpret_cast(keyRequest.data()), keyRequest.size()); return android::OK; } status_t WVDrmPlugin::provideLicenseResponse( const Vector& sessionId, const Vector& response) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); CdmKeyResponse cdmResponse(response.begin(), response.end()); CdmResponseType res = mCDM->AddKey(cdmSessionId, cdmResponse); if (res == wvcdm::KEY_ADDED || res == wvcdm::NO_ERROR) { return android::OK; } else { return android::UNKNOWN_ERROR; } } status_t WVDrmPlugin::removeLicense(const Vector& sessionId) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); CdmResponseType res = mCDM->CancelKeyRequest(cdmSessionId); if (res == wvcdm::NO_ERROR) { return android::OK; } else { return android::UNKNOWN_ERROR; } } status_t WVDrmPlugin::queryLicenseStatus( const Vector& sessionId, KeyedVector& infoMap) const { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); CdmNameValueMap cdmLicenseInfo; CdmResponseType res = mCDM->QueryKeyStatus(cdmSessionId, &cdmLicenseInfo); if (res != wvcdm::NO_ERROR) { return android::UNKNOWN_ERROR; } infoMap.clear(); for (CdmNameValueMap::const_iterator iter = cdmLicenseInfo.begin(); iter != cdmLicenseInfo.end(); ++iter) { const string& cdmKey = iter->first; const string& cdmValue = iter->second; String8 key(cdmKey.data(), cdmKey.size()); String8 value(cdmValue.data(), cdmValue.size()); infoMap.add(key, value); } return android::OK; } status_t WVDrmPlugin::getProvisionRequest(Vector& request, String8& defaultUrl) { CdmProvisioningRequest cdmProvisionRequest; string cdmDefaultUrl; CdmResponseType res = mCDM->GetProvisioningRequest(&cdmProvisionRequest, &cdmDefaultUrl); if (res != wvcdm::NO_ERROR) { return android::UNKNOWN_ERROR; } request.clear(); request.appendArray(reinterpret_cast( cdmProvisionRequest.data()), cdmProvisionRequest.size()); defaultUrl.clear(); defaultUrl.setTo(cdmDefaultUrl.data(), cdmDefaultUrl.size()); return android::OK; } status_t WVDrmPlugin::provideProvisionResponse( const Vector& response) { CdmProvisioningResponse cdmResponse(response.begin(), response.end()); CdmResponseType res = mCDM->HandleProvisioningResponse(cdmResponse); if (res == wvcdm::NO_ERROR) { return android::OK; } else { return android::UNKNOWN_ERROR; } } status_t WVDrmPlugin::getSecureStops(List >& secureStops) { CdmSecureStops cdmSecureStops; CdmResponseType res = mCDM->GetSecureStops(&cdmSecureStops); if (res != wvcdm::NO_ERROR) { return android::UNKNOWN_ERROR; } secureStops.clear(); for (CdmSecureStops::const_iterator iter = cdmSecureStops.begin(); iter != cdmSecureStops.end(); ++iter) { const string& cdmStop = *iter; Vector stop; stop.appendArray(reinterpret_cast(cdmStop.data()), cdmStop.size()); secureStops.push_back(stop); } return android::OK; } status_t WVDrmPlugin::releaseSecureStops(const Vector& ssRelease) { CdmSecureStopReleaseMessage cdmMessage(ssRelease.begin(), ssRelease.end()); CdmResponseType res = mCDM->ReleaseSecureStops(cdmMessage); if (res == wvcdm::NO_ERROR) { return android::OK; } else { return android::UNKNOWN_ERROR; } } status_t WVDrmPlugin::getPropertyString(const String8& name, String8& value) const { // TODO: Implement this function once the CDM query API is finalized. return -EPERM; } status_t WVDrmPlugin::getPropertyByteArray(const String8& name, Vector& value) const { // TODO: Implement this function once the CDM query API is finalized. return -EPERM; } status_t WVDrmPlugin::setPropertyString(const String8& name, const String8& value) { // TODO: Implement this function once the CDM query API is finalized. return -EPERM; } status_t WVDrmPlugin::setPropertyByteArray(const String8& name, const Vector& value) { // TODO: Implement this function once the CDM query API is finalized. return -EPERM; } // TODO: Hook up to event listener methods on CDM once Android API for // eventing is finalized. } // namespace wvdrm