Builds libwvmdrmengine.so, which is loaded by the new MediaDrm APIs to support playback of Widevine/CENC protected content. Change-Id: I6f57dd37083dfd96c402cb9dd137c7d74edc8f1c
258 lines
7.1 KiB
C++
258 lines
7.1 KiB
C++
//
|
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
|
//
|
|
|
|
//#define LOG_NDEBUG 0
|
|
#define LOG_TAG "WVCdm"
|
|
#include <utils/Log.h>
|
|
|
|
#include "WVDrmPlugin.h"
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#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<uint8_t>& 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<const uint8_t*>(cdmSessionId.data()),
|
|
cdmSessionId.size());
|
|
|
|
return android::OK;
|
|
}
|
|
|
|
status_t WVDrmPlugin::closeSession(const Vector<uint8_t>& 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<uint8_t>& sessionId,
|
|
const Vector<uint8_t>& initData,
|
|
const String8& mimeType,
|
|
LicenseType licenseType,
|
|
const KeyedVector<String8, String8>& optionalParameters,
|
|
Vector<uint8_t>& 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<const uint8_t*>(keyRequest.data()),
|
|
keyRequest.size());
|
|
|
|
return android::OK;
|
|
}
|
|
|
|
status_t WVDrmPlugin::provideLicenseResponse(
|
|
const Vector<uint8_t>& sessionId,
|
|
const Vector<uint8_t>& 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<uint8_t>& 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<uint8_t>& sessionId,
|
|
KeyedVector<String8, String8>& 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<uint8_t>& 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<const uint8_t*>(
|
|
cdmProvisionRequest.data()),
|
|
cdmProvisionRequest.size());
|
|
|
|
defaultUrl.clear();
|
|
defaultUrl.setTo(cdmDefaultUrl.data(), cdmDefaultUrl.size());
|
|
|
|
return android::OK;
|
|
}
|
|
|
|
status_t WVDrmPlugin::provideProvisionResponse(
|
|
const Vector<uint8_t>& 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<Vector<uint8_t> >& 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<uint8_t> stop;
|
|
stop.appendArray(reinterpret_cast<const uint8_t*>(cdmStop.data()),
|
|
cdmStop.size());
|
|
|
|
secureStops.push_back(stop);
|
|
}
|
|
|
|
return android::OK;
|
|
}
|
|
|
|
status_t WVDrmPlugin::releaseSecureStops(const Vector<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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
|