am 778b5ce2: 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 t

* commit '778b5ce26f691119f6c275538dc56a63179d93f2':
  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
This commit is contained in:
Jeffrey Tinker
2011-03-16 14:37:48 -07:00
committed by Android Git Automerger
9 changed files with 177 additions and 50 deletions

View File

@@ -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"); * Declarations for Widevine DRM Plugin API
* 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.
*/ */
#ifndef __WVMDRMPLUGIN_API_H__ #ifndef __WVMDRMPLUGIN_API_H__
@@ -38,6 +28,12 @@ class WVDRMPluginAPI {
PLAYBACK_INVALID 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 WVDRMPluginAPI *create();
static void destroy(WVDRMPluginAPI *plugin); static void destroy(WVDRMPluginAPI *plugin);
@@ -48,19 +44,35 @@ class WVDRMPluginAPI {
virtual bool RegisterDrmInfo(std::string &portal, std::string &dsPath) = 0; virtual bool RegisterDrmInfo(std::string &portal, std::string &dsPath) = 0;
virtual bool UnregisterDrmInfo(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, virtual bool AcquireDrmInfo(std::string &assetPath, WVCredentials &credentials,
std::string &dsPath, std::string &dsPath, const std::string &assetIdStr,
const std::string &assetIdStr, const std::string &systemIdStr, const std::string &systemIdStr,
const std::string &keyIdStr, const std::string &keyIdStr,
uint32_t *assetId, uint32_t *systemId, uint32_t *keyId) = 0; uint32_t *assetId, uint32_t *systemId,
virtual bool ProcessDrmInfo(std::string &assetPath) = 0; uint32_t *keyId) = 0;
virtual bool ProcessDrmInfo(std::string &assetPath, int playbackMode) = 0;
virtual int CheckRightsStatus(std::string &path) = 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 SetPlaybackStatus(int playbackStatus, off64_t position) = 0;
virtual bool RemoveRights(std::string &path) = 0; virtual bool RemoveRights(std::string &path) = 0;
virtual bool RemoveAllRights() = 0; virtual bool RemoveAllRights() = 0;
virtual bool Prepare(char *data, int len) = 0; virtual bool Prepare(char *data, int len) = 0;
virtual bool Operate(char *in, char *out, int len, char *iv) = 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: protected:
// use create factory method, don't construct directly // use create factory method, don't construct directly
WVDRMPluginAPI() {} WVDRMPluginAPI() {}

View File

@@ -101,7 +101,10 @@ protected:
void* buffer, ssize_t numBytes, off64_t offset); void* buffer, ssize_t numBytes, off64_t offset);
private: private:
const IDrmEngine::OnInfoListener *mOnInfoListener; static void SendEvent(WVDRMPluginAPI::EventType code, const std::string &path);
static IDrmEngine::OnInfoListener *sOnInfoListener;
static int sUniqueId;
WVDRMPluginAPI *mDrmPluginImpl; WVDRMPluginAPI *mDrmPluginImpl;
}; };

View File

@@ -21,6 +21,7 @@
#include <drm/DrmRights.h> #include <drm/DrmRights.h>
#include <drm/DrmConstraints.h> #include <drm/DrmConstraints.h>
#include <drm/DrmInfo.h> #include <drm/DrmInfo.h>
#include <drm/DrmInfoEvent.h>
#include <drm/DrmInfoStatus.h> #include <drm/DrmInfoStatus.h>
#include <drm/DrmConvertedStatus.h> #include <drm/DrmConvertedStatus.h>
#include <drm/DrmInfoRequest.h> #include <drm/DrmInfoRequest.h>
@@ -45,11 +46,15 @@ extern "C" void destroy(IDrmEngine* pPlugIn) {
delete pPlugIn; delete pPlugIn;
} }
// Needed for event callout from implementation object
IDrmEngine::OnInfoListener *WVMDrmPlugin::sOnInfoListener = NULL;
int WVMDrmPlugin::sUniqueId;
WVMDrmPlugin::WVMDrmPlugin() WVMDrmPlugin::WVMDrmPlugin()
: DrmEngineBase(), : DrmEngineBase(),
mOnInfoListener(NULL),
mDrmPluginImpl(WVDRMPluginAPI::create()) mDrmPluginImpl(WVDRMPluginAPI::create())
{ {
mDrmPluginImpl->SetEventHandler(&SendEvent);
} }
WVMDrmPlugin::~WVMDrmPlugin() { WVMDrmPlugin::~WVMDrmPlugin() {
@@ -96,10 +101,38 @@ status_t WVMDrmPlugin::onTerminate(int uniqueId) {
status_t WVMDrmPlugin::onSetOnInfoListener( status_t WVMDrmPlugin::onSetOnInfoListener(
int uniqueId, const IDrmEngine::OnInfoListener* infoListener) { int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
//LOGD("WVMDrmPlugin::onSetOnInfoListener : %d", uniqueId); //LOGD("WVMDrmPlugin::onSetOnInfoListener : %d", uniqueId);
mOnInfoListener = infoListener; sOnInfoListener = const_cast<IDrmEngine::OnInfoListener *>(infoListener);
sUniqueId = uniqueId;
return DRM_NO_ERROR; 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 * Retrieves necessary information for registration, unregistration or rights
* acquisition information. * acquisition information.
@@ -141,6 +174,7 @@ DrmInfo* WVMDrmPlugin::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmI
string systemIdStr = drmInfoRequest->get(String8("WVSystemIDKey")).string(); string systemIdStr = drmInfoRequest->get(String8("WVSystemIDKey")).string();
string assetIdStr = drmInfoRequest->get(String8("WVAssetIDKey")).string(); string assetIdStr = drmInfoRequest->get(String8("WVAssetIDKey")).string();
string keyIdStr = drmInfoRequest->get(String8("WVKeyIDKey")).string(); string keyIdStr = drmInfoRequest->get(String8("WVKeyIDKey")).string();
string licenseTypeStr = drmInfoRequest->get(String8("WVLicenseTypeKey")).string();
uint32_t systemId, assetId, keyId; 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("WVCAUserDataKey"), String8(credentials.userData.c_str()));
drmInfo->put(String8("WVDeviceIDKey"), String8(credentials.deviceID.c_str())); drmInfo->put(String8("WVDeviceIDKey"), String8(credentials.deviceID.c_str()));
drmInfo->put(String8("WVStreamIDKey"), String8(credentials.streamID.c_str())); drmInfo->put(String8("WVStreamIDKey"), String8(credentials.streamID.c_str()));
drmInfo->put(String8("WVLicenseTypeKey"), String8(licenseTypeStr.c_str()));
char buffer[16]; char buffer[16];
sprintf(buffer, "%lu", (unsigned long)systemId); sprintf(buffer, "%lu", (unsigned long)systemId);
@@ -239,8 +274,9 @@ DrmInfoStatus* WVMDrmPlugin::onProcessDrmInfo(int uniqueId, const DrmInfo* drmIn
if (NULL != drmInfo) { if (NULL != drmInfo) {
if (drmInfo->getInfoType() == DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO) { if (drmInfo->getInfoType() == DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO) {
std::string assetPath = drmInfo->get(String8("WVAssetURIKey")).string(); 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; status = DrmInfoStatus::STATUS_OK;
} else if ((drmInfo->getInfoType() == DrmInfoRequest::TYPE_REGISTRATION_INFO) || } else if ((drmInfo->getInfoType() == DrmInfoRequest::TYPE_REGISTRATION_INFO) ||
(drmInfo->getInfoType() == DrmInfoRequest::TYPE_UNREGISTRATION_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 licenseDuration = 0;
uint32_t timeSincePlayback = 0; uint32_t timeSincePlayback = 0;
uint32_t timeRemaining = 0; uint32_t timeRemaining = 0;
std::string lastError;
bool allowOffline;
bool allowStreaming;
bool denyHD;
std::string assetPath(path->string()); 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; return NULL;
DrmConstraints* drmConstraints = new DrmConstraints(); DrmConstraints* drmConstraints = new DrmConstraints();
@@ -308,6 +350,16 @@ DrmConstraints* WVMDrmPlugin::onGetConstraints(int uniqueId, const String8* path
sprintf(charValue, "%lu", (unsigned long)licenseDuration); sprintf(charValue, "%lu", (unsigned long)licenseDuration);
drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue); 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; return drmConstraints;
} }
@@ -755,4 +807,3 @@ DrmConvertedStatus* WVMDrmPlugin::onCloseConvertSession(int uniqueId, int conver
return NULL; return NULL;
} }

View File

@@ -35,15 +35,22 @@ public:
void TestAsset(IDrmEngine *plugin, String8 &url); void TestAsset(IDrmEngine *plugin, String8 &url);
void TestRemoveAllRights(IDrmEngine *plugin); void TestRegister(IDrmEngine *plugin);
void TestAcquireRights(IDrmEngine *plugin, String8 &url); void TestAcquireRights(IDrmEngine *plugin, String8 &url, int playbackMode);
void TestCheckRightsNotAcquired(IDrmEngine *plugin, String8 &url); void TestCheckRightsNotAcquired(IDrmEngine *plugin, String8 &url);
void TestCheckValidRights(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 TestRemoveRights(IDrmEngine *plugin, String8 &url);
void TestRemoveAllRights(IDrmEngine *plugin);
// Tests // Tests
void Run(); 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() void WVMDrmPluginTest::Run()
@@ -101,9 +108,25 @@ void WVMDrmPluginTest::Run()
exit(0); 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, &registrationInfo);
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"); String8 mimeType("video/wvm");
DrmInfoRequest rightsAcquisitionInfo(DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, mimeType); 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("WVAssetURIKey"), url);
rightsAcquisitionInfo.put(String8("WVDeviceIDKey"), String8("device1234")); rightsAcquisitionInfo.put(String8("WVDeviceIDKey"), String8("device1234"));
rightsAcquisitionInfo.put(String8("WVPortalKey"), String8("YouTube")); 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); DrmInfo *info = plugin->acquireDrmInfo(0, &rightsAcquisitionInfo);
if (info == NULL) { 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; cout << "WVDrmPluginTest::TestGetConstraints url=" << url << endl;
@@ -169,23 +198,45 @@ void WVMDrmPluginTest::TestGetConstraints(IDrmEngine *plugin, String8 &url)
exit(-1); exit(-1);
} }
if (constraints->getCount() != 3) { if (constraints->getCount() != 6) {
fprintf(stderr, "getConstraints returned unexpected count!\n"); fprintf(stderr, "getConstraints returned unexpected count!\n");
exit(-1); exit(-1);
} }
if (constraints->get(DrmConstraints::LICENSE_START_TIME) == "") { if (constraints->get(DrmConstraints::LICENSE_START_TIME) == "") {
fprintf(stderr, "getConstraints returned unexpected count!\n"); fprintf(stderr, "getConstraints missing start time!\n");
exit(-1); exit(-1);
} }
if (constraints->get(DrmConstraints::LICENSE_AVAILABLE_TIME) == "") { if (constraints->get(DrmConstraints::LICENSE_AVAILABLE_TIME) == "") {
fprintf(stderr, "getConstraints returned unexpected count!\n"); fprintf(stderr, "getConstraints missing available time!\n");
exit(-1); exit(-1);
} }
if (constraints->get(DrmConstraints::LICENSE_EXPIRY_TIME) == "") { 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); exit(-1);
} }
@@ -218,13 +269,32 @@ void WVMDrmPluginTest::TestAsset(IDrmEngine *plugin, String8 &url)
{ {
cout << "WVDrmPluginTest::TestAsset url=" << url << endl; cout << "WVDrmPluginTest::TestAsset url=" << url << endl;
TestAcquireRights(plugin, url); TestRegister(plugin);
TestRemoveAllRights(plugin);
TestCheckRightsNotAcquired(plugin, url);
TestAcquireRights(plugin, url, PlaybackMode_Default);
TestCheckValidRights(plugin, url); TestCheckValidRights(plugin, url);
TestGetConstraints(plugin, url); TestGetConstraints(plugin, url, PlaybackMode_Any);
TestRemoveRights(plugin, url); TestRemoveRights(plugin, url);
TestCheckRightsNotAcquired(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); TestCheckRightsNotAcquired(plugin, url);
} }
@@ -232,6 +302,7 @@ int main(int argc, char **argv)
{ {
// turn off some noisy printing in WVStreamControl // turn off some noisy printing in WVStreamControl
setenv("WV_SILENT", "true", 1); setenv("WV_SILENT", "true", 1);
WVMDrmPluginTest test; WVMDrmPluginTest test;
test.Run(); test.Run();
} }

View File

@@ -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"); * Declarations for Widevine Adaptive Streaming API
* 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.
*/ */
#ifndef __WV_STREAM_CONTROL_API_H__ #ifndef __WV_STREAM_CONTROL_API_H__

View File

@@ -315,7 +315,7 @@ int main( int argc, char *argv[] )
Terminate(); Terminate();
} }
if (!sDrmPlugin->ProcessDrmInfo(url)) { if (!sDrmPlugin->ProcessDrmInfo(url, WVDRMPluginAPI::PlaybackMode_Any)) {
fprintf(stderr, "ERROR: ProcessDrmInfo failed\n"); fprintf(stderr, "ERROR: ProcessDrmInfo failed\n");
Terminate(); Terminate();
} }