Fix for b/3501089 Require an API in the DRM client to specify the license type (offline/streaming) and b/4084670 Define events in DRM API to support license expiration, revocation, license failure. Implements events and license changes as documented in the Widevine_Java_API_for_Android_DRM_Framework spec
Change-Id: I3d0440e4f64d2279ab3b272a5287db5144e41eb1
This commit is contained in:
@@ -1,17 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
* Copyright 2011 Widevine Technologies, Inc., All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
* Declarations for Widevine DRM Plugin API
|
||||
*/
|
||||
|
||||
#ifndef __WVMDRMPLUGIN_API_H__
|
||||
@@ -38,6 +28,12 @@ class WVDRMPluginAPI {
|
||||
PLAYBACK_INVALID
|
||||
};
|
||||
|
||||
static const int PlaybackMode_Default = 0;
|
||||
static const int PlaybackMode_Streaming = 1;
|
||||
static const int PlaybackMode_Offline = 2;
|
||||
static const int PlaybackMode_Any = PlaybackMode_Streaming |
|
||||
PlaybackMode_Offline;
|
||||
|
||||
static WVDRMPluginAPI *create();
|
||||
static void destroy(WVDRMPluginAPI *plugin);
|
||||
|
||||
@@ -48,19 +44,35 @@ class WVDRMPluginAPI {
|
||||
virtual bool RegisterDrmInfo(std::string &portal, std::string &dsPath) = 0;
|
||||
virtual bool UnregisterDrmInfo(std::string &portal, std::string &dsPath) = 0;
|
||||
virtual bool AcquireDrmInfo(std::string &assetPath, WVCredentials &credentials,
|
||||
std::string &dsPath,
|
||||
const std::string &assetIdStr, const std::string &systemIdStr,
|
||||
std::string &dsPath, const std::string &assetIdStr,
|
||||
const std::string &systemIdStr,
|
||||
const std::string &keyIdStr,
|
||||
uint32_t *assetId, uint32_t *systemId, uint32_t *keyId) = 0;
|
||||
virtual bool ProcessDrmInfo(std::string &assetPath) = 0;
|
||||
uint32_t *assetId, uint32_t *systemId,
|
||||
uint32_t *keyId) = 0;
|
||||
|
||||
virtual bool ProcessDrmInfo(std::string &assetPath, int playbackMode) = 0;
|
||||
virtual int CheckRightsStatus(std::string &path) = 0;
|
||||
virtual bool GetConstraints(std::string &path, uint32_t *timeSincePlayback, uint32_t *timeRemaining, uint32_t *licenseDuration) = 0;
|
||||
virtual bool GetConstraints(std::string &path, uint32_t *timeSincePlayback,
|
||||
uint32_t *timeRemaining,
|
||||
uint32_t *licenseDuration, std::string &lastError,
|
||||
bool &allowOffline, bool &allowStreaming,
|
||||
bool &denyHD) = 0;
|
||||
virtual bool SetPlaybackStatus(int playbackStatus, off64_t position) = 0;
|
||||
virtual bool RemoveRights(std::string &path) = 0;
|
||||
virtual bool RemoveAllRights() = 0;
|
||||
virtual bool Prepare(char *data, int len) = 0;
|
||||
virtual bool Operate(char *in, char *out, int len, char *iv) = 0;
|
||||
|
||||
enum EventType {
|
||||
EventType_AcquireDrmInfoFailed,
|
||||
EventType_ProcessDrmInfoFailed,
|
||||
EventType_RightsInstalled,
|
||||
EventType_RightsRemoved
|
||||
};
|
||||
|
||||
typedef void (*EventHandler)(EventType type, const std::string &path);
|
||||
virtual void SetEventHandler(EventHandler handler) = 0;
|
||||
|
||||
protected:
|
||||
// use create factory method, don't construct directly
|
||||
WVDRMPluginAPI() {}
|
||||
|
||||
@@ -101,7 +101,10 @@ protected:
|
||||
void* buffer, ssize_t numBytes, off64_t offset);
|
||||
|
||||
private:
|
||||
const IDrmEngine::OnInfoListener *mOnInfoListener;
|
||||
static void SendEvent(WVDRMPluginAPI::EventType code, const std::string &path);
|
||||
static IDrmEngine::OnInfoListener *sOnInfoListener;
|
||||
static int sUniqueId;
|
||||
|
||||
WVDRMPluginAPI *mDrmPluginImpl;
|
||||
};
|
||||
|
||||
|
||||
Binary file not shown.
@@ -21,6 +21,7 @@
|
||||
#include <drm/DrmRights.h>
|
||||
#include <drm/DrmConstraints.h>
|
||||
#include <drm/DrmInfo.h>
|
||||
#include <drm/DrmInfoEvent.h>
|
||||
#include <drm/DrmInfoStatus.h>
|
||||
#include <drm/DrmConvertedStatus.h>
|
||||
#include <drm/DrmInfoRequest.h>
|
||||
@@ -45,11 +46,15 @@ extern "C" void destroy(IDrmEngine* pPlugIn) {
|
||||
delete pPlugIn;
|
||||
}
|
||||
|
||||
// Needed for event callout from implementation object
|
||||
IDrmEngine::OnInfoListener *WVMDrmPlugin::sOnInfoListener = NULL;
|
||||
int WVMDrmPlugin::sUniqueId;
|
||||
|
||||
WVMDrmPlugin::WVMDrmPlugin()
|
||||
: DrmEngineBase(),
|
||||
mOnInfoListener(NULL),
|
||||
mDrmPluginImpl(WVDRMPluginAPI::create())
|
||||
{
|
||||
mDrmPluginImpl->SetEventHandler(&SendEvent);
|
||||
}
|
||||
|
||||
WVMDrmPlugin::~WVMDrmPlugin() {
|
||||
@@ -96,10 +101,38 @@ status_t WVMDrmPlugin::onTerminate(int uniqueId) {
|
||||
status_t WVMDrmPlugin::onSetOnInfoListener(
|
||||
int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
|
||||
//LOGD("WVMDrmPlugin::onSetOnInfoListener : %d", uniqueId);
|
||||
mOnInfoListener = infoListener;
|
||||
sOnInfoListener = const_cast<IDrmEngine::OnInfoListener *>(infoListener);
|
||||
sUniqueId = uniqueId;
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
void WVMDrmPlugin::SendEvent(WVDRMPluginAPI::EventType type, const std::string &path)
|
||||
{
|
||||
int code = -1;
|
||||
|
||||
switch(type) {
|
||||
EventType_AcquireFailed:
|
||||
code = DrmInfoEvent::TYPE_ACQUIRE_DRM_INFO_FAILED;
|
||||
break;
|
||||
EventType_ProcessDrmInfoFailed:
|
||||
code = DrmInfoEvent::TYPE_PROCESS_DRM_INFO_FAILED;
|
||||
break;
|
||||
EventType_RightsInstalled:
|
||||
code = DrmInfoEvent::TYPE_RIGHTS_INSTALLED;
|
||||
break;
|
||||
EventType_RightsRemoved:
|
||||
code = DrmInfoEvent::TYPE_RIGHTS_REMOVED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sOnInfoListener) {
|
||||
DrmInfoEvent event(sUniqueId, code, String8(path.c_str()));
|
||||
sOnInfoListener->onInfo(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves necessary information for registration, unregistration or rights
|
||||
* acquisition information.
|
||||
@@ -141,6 +174,7 @@ DrmInfo* WVMDrmPlugin::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmI
|
||||
string systemIdStr = drmInfoRequest->get(String8("WVSystemIDKey")).string();
|
||||
string assetIdStr = drmInfoRequest->get(String8("WVAssetIDKey")).string();
|
||||
string keyIdStr = drmInfoRequest->get(String8("WVKeyIDKey")).string();
|
||||
string licenseTypeStr = drmInfoRequest->get(String8("WVLicenseTypeKey")).string();
|
||||
|
||||
uint32_t systemId, assetId, keyId;
|
||||
|
||||
@@ -166,6 +200,7 @@ DrmInfo* WVMDrmPlugin::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmI
|
||||
drmInfo->put(String8("WVCAUserDataKey"), String8(credentials.userData.c_str()));
|
||||
drmInfo->put(String8("WVDeviceIDKey"), String8(credentials.deviceID.c_str()));
|
||||
drmInfo->put(String8("WVStreamIDKey"), String8(credentials.streamID.c_str()));
|
||||
drmInfo->put(String8("WVLicenseTypeKey"), String8(licenseTypeStr.c_str()));
|
||||
|
||||
char buffer[16];
|
||||
sprintf(buffer, "%lu", (unsigned long)systemId);
|
||||
@@ -239,8 +274,9 @@ DrmInfoStatus* WVMDrmPlugin::onProcessDrmInfo(int uniqueId, const DrmInfo* drmIn
|
||||
if (NULL != drmInfo) {
|
||||
if (drmInfo->getInfoType() == DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO) {
|
||||
std::string assetPath = drmInfo->get(String8("WVAssetURIKey")).string();
|
||||
int playbackMode = atol(drmInfo->get(String8("WVLicenseTypeKey")).string());
|
||||
|
||||
if (mDrmPluginImpl->ProcessDrmInfo(assetPath))
|
||||
if (mDrmPluginImpl->ProcessDrmInfo(assetPath, playbackMode))
|
||||
status = DrmInfoStatus::STATUS_OK;
|
||||
} else if ((drmInfo->getInfoType() == DrmInfoRequest::TYPE_REGISTRATION_INFO) ||
|
||||
(drmInfo->getInfoType() == DrmInfoRequest::TYPE_UNREGISTRATION_INFO)) {
|
||||
@@ -288,9 +324,15 @@ DrmConstraints* WVMDrmPlugin::onGetConstraints(int uniqueId, const String8* path
|
||||
uint32_t licenseDuration = 0;
|
||||
uint32_t timeSincePlayback = 0;
|
||||
uint32_t timeRemaining = 0;
|
||||
std::string lastError;
|
||||
bool allowOffline;
|
||||
bool allowStreaming;
|
||||
bool denyHD;
|
||||
|
||||
std::string assetPath(path->string());
|
||||
if (!mDrmPluginImpl->GetConstraints(assetPath, &timeSincePlayback, &timeRemaining, &licenseDuration))
|
||||
if (!mDrmPluginImpl->GetConstraints(assetPath, &timeSincePlayback, &timeRemaining,
|
||||
&licenseDuration, lastError, allowOffline,
|
||||
allowStreaming, denyHD))
|
||||
return NULL;
|
||||
|
||||
DrmConstraints* drmConstraints = new DrmConstraints();
|
||||
@@ -308,6 +350,16 @@ DrmConstraints* WVMDrmPlugin::onGetConstraints(int uniqueId, const String8* path
|
||||
sprintf(charValue, "%lu", (unsigned long)licenseDuration);
|
||||
drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue);
|
||||
|
||||
String8 key = String8("WVLicenseTypeKey");
|
||||
sprintf(charValue, "%u", (allowStreaming ? 1 : 0) | (allowOffline ? 2 : 0));
|
||||
drmConstraints->put(&key, charValue);
|
||||
|
||||
key = String8("WVLicensedResolutionKey");
|
||||
sprintf(charValue, "%u", (denyHD ? 1 : 2));
|
||||
drmConstraints->put(&key, charValue);
|
||||
|
||||
key = String8("WVLastErrorKey");
|
||||
drmConstraints->put(&key, lastError.c_str());
|
||||
return drmConstraints;
|
||||
}
|
||||
|
||||
@@ -755,4 +807,3 @@ DrmConvertedStatus* WVMDrmPlugin::onCloseConvertSession(int uniqueId, int conver
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,15 +35,22 @@ public:
|
||||
|
||||
void TestAsset(IDrmEngine *plugin, String8 &url);
|
||||
|
||||
void TestRemoveAllRights(IDrmEngine *plugin);
|
||||
void TestAcquireRights(IDrmEngine *plugin, String8 &url);
|
||||
void TestRegister(IDrmEngine *plugin);
|
||||
void TestAcquireRights(IDrmEngine *plugin, String8 &url, int playbackMode);
|
||||
void TestCheckRightsNotAcquired(IDrmEngine *plugin, String8 &url);
|
||||
void TestCheckValidRights(IDrmEngine *plugin, String8 &url);
|
||||
void TestGetConstraints(IDrmEngine *plugin, String8 &url);
|
||||
void TestGetConstraints(IDrmEngine *plugin, String8 &url, int playbackMode);
|
||||
void TestRemoveRights(IDrmEngine *plugin, String8 &url);
|
||||
void TestRemoveAllRights(IDrmEngine *plugin);
|
||||
|
||||
// Tests
|
||||
void Run();
|
||||
|
||||
private:
|
||||
static const int PlaybackMode_Default = 0;
|
||||
static const int PlaybackMode_Streaming = 1;
|
||||
static const int PlaybackMode_Offline = 2;
|
||||
static const int PlaybackMode_Any = PlaybackMode_Streaming | PlaybackMode_Offline;
|
||||
};
|
||||
|
||||
void WVMDrmPluginTest::Run()
|
||||
@@ -101,9 +108,25 @@ void WVMDrmPluginTest::Run()
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestAcquireRights(IDrmEngine *plugin, String8 &url)
|
||||
void WVMDrmPluginTest::TestRegister(IDrmEngine *plugin)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestAcquireRights url=" << url << endl;
|
||||
cout << "WVDrmPluginTest::TestRegister" << endl;
|
||||
|
||||
String8 mimeType("video/wvm");
|
||||
DrmInfoRequest registrationInfo(DrmInfoRequest::TYPE_REGISTRATION_INFO, mimeType);
|
||||
registrationInfo.put(String8("WVPortalKey"), String8("YouTube"));
|
||||
|
||||
DrmInfo *info = plugin->acquireDrmInfo(0, ®istrationInfo);
|
||||
if (info == NULL) {
|
||||
fprintf(stderr, "acquireDrmInfo failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
delete info;
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestAcquireRights(IDrmEngine *plugin, String8 &url, int playbackMode)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestAcquireRights url=" << url << " mode=" << playbackMode << endl;
|
||||
|
||||
String8 mimeType("video/wvm");
|
||||
DrmInfoRequest rightsAcquisitionInfo(DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, mimeType);
|
||||
@@ -111,6 +134,12 @@ void WVMDrmPluginTest::TestAcquireRights(IDrmEngine *plugin, String8 &url)
|
||||
rightsAcquisitionInfo.put(String8("WVAssetURIKey"), url);
|
||||
rightsAcquisitionInfo.put(String8("WVDeviceIDKey"), String8("device1234"));
|
||||
rightsAcquisitionInfo.put(String8("WVPortalKey"), String8("YouTube"));
|
||||
if (playbackMode) {
|
||||
char num[4];
|
||||
sprintf(num, "%d", playbackMode);
|
||||
rightsAcquisitionInfo.put(String8("WVLicenseTypeKey"), String8(num));
|
||||
cout << "WVLicenseTypeKey = " << num << endl;
|
||||
}
|
||||
|
||||
DrmInfo *info = plugin->acquireDrmInfo(0, &rightsAcquisitionInfo);
|
||||
if (info == NULL) {
|
||||
@@ -158,7 +187,7 @@ void WVMDrmPluginTest::TestCheckValidRights(IDrmEngine *plugin, String8 &url)
|
||||
}
|
||||
}
|
||||
|
||||
void WVMDrmPluginTest::TestGetConstraints(IDrmEngine *plugin, String8 &url)
|
||||
void WVMDrmPluginTest::TestGetConstraints(IDrmEngine *plugin, String8 &url, int playbackMode)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestGetConstraints url=" << url << endl;
|
||||
|
||||
@@ -169,23 +198,45 @@ void WVMDrmPluginTest::TestGetConstraints(IDrmEngine *plugin, String8 &url)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->getCount() != 3) {
|
||||
if (constraints->getCount() != 6) {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(DrmConstraints::LICENSE_START_TIME) == "") {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
fprintf(stderr, "getConstraints missing start time!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(DrmConstraints::LICENSE_AVAILABLE_TIME) == "") {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
fprintf(stderr, "getConstraints missing available time!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(DrmConstraints::LICENSE_EXPIRY_TIME) == "") {
|
||||
fprintf(stderr, "getConstraints returned unexpected count!\n");
|
||||
fprintf(stderr, "getConstraints missing expiry time!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(String8("WVLicenseTypeKey")) == "") {
|
||||
fprintf(stderr, "getConstraints missing license type key!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(String8("WVLicensedResolutionKey")) == "") {
|
||||
fprintf(stderr, "getConstraints missing resolution key!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (constraints->get(String8("WVLastErrorKey")) == "") {
|
||||
fprintf(stderr, "getConstraints missing last error key!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
String8 licenseTypeStr = constraints->get(String8("WVLicenseTypeKey"));
|
||||
int licenseType = atol(licenseTypeStr.string());
|
||||
if (licenseType != playbackMode) {
|
||||
fprintf(stderr, "license type mismatch, expected %d, found %d\n", playbackMode, licenseType);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -218,13 +269,32 @@ void WVMDrmPluginTest::TestAsset(IDrmEngine *plugin, String8 &url)
|
||||
{
|
||||
cout << "WVDrmPluginTest::TestAsset url=" << url << endl;
|
||||
|
||||
TestAcquireRights(plugin, url);
|
||||
TestRegister(plugin);
|
||||
TestRemoveAllRights(plugin);
|
||||
TestCheckRightsNotAcquired(plugin, url);
|
||||
|
||||
TestAcquireRights(plugin, url, PlaybackMode_Default);
|
||||
TestCheckValidRights(plugin, url);
|
||||
TestGetConstraints(plugin, url);
|
||||
TestGetConstraints(plugin, url, PlaybackMode_Any);
|
||||
TestRemoveRights(plugin, url);
|
||||
TestCheckRightsNotAcquired(plugin, url);
|
||||
TestAcquireRights(plugin, url);
|
||||
TestRemoveAllRights(plugin);
|
||||
|
||||
TestAcquireRights(plugin, url, PlaybackMode_Offline);
|
||||
TestCheckValidRights(plugin, url);
|
||||
TestGetConstraints(plugin, url, PlaybackMode_Offline);
|
||||
TestRemoveRights(plugin, url);
|
||||
TestCheckRightsNotAcquired(plugin, url);
|
||||
|
||||
TestAcquireRights(plugin, url, PlaybackMode_Streaming);
|
||||
TestCheckValidRights(plugin, url);
|
||||
TestGetConstraints(plugin, url, PlaybackMode_Streaming);
|
||||
TestRemoveRights(plugin, url);
|
||||
TestCheckRightsNotAcquired(plugin, url);
|
||||
|
||||
TestAcquireRights(plugin, url, PlaybackMode_Any);
|
||||
TestCheckValidRights(plugin, url);
|
||||
TestGetConstraints(plugin, url, PlaybackMode_Any);
|
||||
TestRemoveRights(plugin, url);
|
||||
TestCheckRightsNotAcquired(plugin, url);
|
||||
}
|
||||
|
||||
@@ -232,6 +302,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
// turn off some noisy printing in WVStreamControl
|
||||
setenv("WV_SILENT", "true", 1);
|
||||
|
||||
WVMDrmPluginTest test;
|
||||
test.Run();
|
||||
}
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
* Copyright 2011 Widevine Technologies, Inc., All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
* Declarations for Widevine Adaptive Streaming API
|
||||
*/
|
||||
|
||||
#ifndef __WV_STREAM_CONTROL_API_H__
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -315,7 +315,7 @@ int main( int argc, char *argv[] )
|
||||
Terminate();
|
||||
}
|
||||
|
||||
if (!sDrmPlugin->ProcessDrmInfo(url)) {
|
||||
if (!sDrmPlugin->ProcessDrmInfo(url, WVDRMPluginAPI::PlaybackMode_Any)) {
|
||||
fprintf(stderr, "ERROR: ProcessDrmInfo failed\n");
|
||||
Terminate();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user