Allow DRM client to pass the FD of an open file to the DRM server.

This allows a DRM client to open a locally-cached file on behalf of the
DRM server so the DRM server no longer requires the sdcard_r permission
to access the file's metadata.  Specifically, this adds an optional
attribute FileDescriptorKey to the DrmInfoRequest.

This change is dependent on this Widevine CL:
https://widevine-internal-review.googlesource.com/#/c/1330/

Relevant bug reports:
bug: 6426185

Change-Id: Ia7bcb2455c7a55fa4c7c7061de4d672957c7ac0a
This commit is contained in:
Gene Morgan
2012-09-04 15:52:32 -07:00
committed by Jeff Tinker
parent b092b158d2
commit 8cd5d09119
5 changed files with 114 additions and 20 deletions

View File

@@ -51,7 +51,7 @@ class WVDRMPluginAPI {
virtual bool RegisterDrmInfo(std::string &portal, std::string &dsPath) = 0;
virtual bool RegisterDrmInfo(std::string &portal, std::string &dsPath, uint32_t *status) = 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, int assetOpenFd, WVCredentials &credentials,
std::string &dsPath, const std::string &systemIdStr,
const std::string &assetIdStr,
const std::string &keyIdStr,
@@ -61,10 +61,10 @@ class WVDRMPluginAPI {
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,
virtual bool GetConstraints(std::string &path, uint32_t *timeSincePlayback,
uint32_t *timeRemaining,
uint32_t *licenseDuration, std::string &lastError,
bool &allowOffline, bool &allowStreaming,
bool &allowOffline, bool &allowStreaming,
bool &denyHD) = 0;
virtual bool SetPlaybackStatus(int playbackStatus, off64_t position) = 0;

View File

@@ -247,6 +247,9 @@ DrmInfo* WVMDrmPlugin::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmI
return NULL;
}
// for local files, app may provide the FD of the open file.
int assetOpenFd = atol(drmInfoRequest->get(String8("FileDescriptorKey")).string());
std::string assetDbPath = drmInfoRequest->get(String8("WVAssetDBPathKey")).string();
//ALOGV("onAcquireDrmInfo: portal=%s, dsPath=%s", credentials.portal.c_str(), assetDbPath.c_str());
@@ -262,7 +265,7 @@ DrmInfo* WVMDrmPlugin::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmI
uint32_t systemId, assetId, keyId;
if (!mDrmPluginImpl->AcquireDrmInfo(assetPath, credentials, assetDbPath,
if (!mDrmPluginImpl->AcquireDrmInfo(assetPath, assetOpenFd, credentials, assetDbPath,
systemIdStr, assetIdStr, keyIdStr,
&systemId, &assetId, &keyId))
return NULL;
@@ -277,6 +280,7 @@ DrmInfo* WVMDrmPlugin::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmI
DrmBuffer(data, length), drmInfoRequest->getMimeType());
// Sets additional drmInfo attributes
// Do not propagate FileDescriptorKey into the newDrmInfo object
drmInfo->put(String8("WVAssetURIKey"), String8(assetPath.c_str()));
drmInfo->put(String8("WVDRMServerKey"), String8(credentials.drmServerURL.c_str()));
drmInfo->put(String8("WVAssetDbPathKey"), String8(assetDbPath.c_str()));

View File

@@ -2,6 +2,11 @@
* Copyright (C) 2011 Google, Inc. All Rights Reserved
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <iostream>
@@ -21,10 +26,11 @@ public:
WVMDrmPluginTest() {}
~WVMDrmPluginTest() {}
void TestAsset(IDrmEngine *plugin, String8 &url);
void TestAsset(IDrmEngine *plugin, String8 &url, bool useOpenFd = false);
void TestRegister(IDrmEngine *plugin);
void TestAcquireRights(IDrmEngine *plugin, String8 &url, int playbackMode);
void TestAcquireRights(IDrmEngine *plugin, String8 &url, int playbackMode,
bool useOpenFd = false);
void TestCheckRightsNotAcquired(IDrmEngine *plugin, String8 &url);
void TestCheckValidRights(IDrmEngine *plugin, String8 &url);
void TestGetConstraints(IDrmEngine *plugin, String8 &url, int playbackMode);
@@ -83,10 +89,18 @@ void WVMDrmPluginTest::Run()
url = String8("widevine://seawwws001.cdn.shibboleth.tv/videos/content/bbb_ffmpeg_hc_single_480p.wvm");
TestAsset(plugin, url);
// Local asset
// Local asset using URL syntax
url = String8("file:///sdcard/Widevine/inception_base_360p_single.wvm");
TestAsset(plugin, url);
// Local asset using normal file path
url = String8("/sdcard/Widevine/inception_base_360p_single.wvm");
TestAsset(plugin, url);
// Local asset, but also supply open file descriptor
url = String8("/sdcard/Widevine/inception_base_360p_single.wvm");
TestAsset(plugin, url, true);
// Remote asset with query parameters
url = String8("http://seawwws001.cdn.shibboleth.tv/videos/content/bbb_ffmpeg_hc_single_480p.wvm?a=b");
TestAsset(plugin, url);
@@ -118,15 +132,32 @@ void WVMDrmPluginTest::TestRegister(IDrmEngine *plugin)
delete info;
}
void WVMDrmPluginTest::TestAcquireRights(IDrmEngine *plugin, String8 &url, int playbackMode)
void WVMDrmPluginTest::TestAcquireRights(IDrmEngine *plugin, String8 &url,
int playbackMode, bool useOpenFd)
{
cout << "WVDrmPluginTest::TestAcquireRights url=" << url << " mode=" << playbackMode << endl;
cout << "WVDrmPluginTest::TestAcquireRights url=" << url << " mode=" <<
playbackMode << " useOpenFd=" << useOpenFd << endl;
int openFd = -1;
String8 mimeType("video/wvm");
DrmInfoRequest rightsAcquisitionInfo(DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, mimeType);
rightsAcquisitionInfo.put(String8("WVDRMServerKey"), String8(
"https://staging.shibboleth.tv/widevine/cypherpc/cgi-bin/GetEMMs.cgi"));
rightsAcquisitionInfo.put(String8("WVAssetURIKey"), url);
if (useOpenFd) {
char openFdStr[16];
openFd = open(url.string(), O_RDONLY);
if (openFd == -1) {
cout << "error opening " << url << ":" << endl;
fprintf(stderr, "Couldn't open local asset file\n");
exit(-1);
}
sprintf(openFdStr, "%lu", (unsigned long)openFd);
rightsAcquisitionInfo.put(String8("FileDescriptorKey"), String8(openFdStr));
}
rightsAcquisitionInfo.put(String8("WVDeviceIDKey"), String8("device1234"));
rightsAcquisitionInfo.put(String8("WVPortalKey"), String8("OEM"));
if (playbackMode) {
@@ -142,6 +173,10 @@ void WVMDrmPluginTest::TestAcquireRights(IDrmEngine *plugin, String8 &url, int p
exit(-1);
}
if (useOpenFd && (openFd != -1)) {
close(openFd);
}
DrmInfoStatus *status = plugin->processDrmInfo(0, info);
if (status == NULL || status->statusCode != DrmInfoStatus::STATUS_OK) {
fprintf(stderr, "processDrmInfo failed!\n");
@@ -260,33 +295,35 @@ void WVMDrmPluginTest::TestRemoveAllRights(IDrmEngine *plugin)
}
}
void WVMDrmPluginTest::TestAsset(IDrmEngine *plugin, String8 &url)
void WVMDrmPluginTest::TestAsset(IDrmEngine *plugin, String8 &url,
bool useOpenFd)
{
cout << "WVDrmPluginTest::TestAsset url=" << url << endl;
cout << "WVDrmPluginTest::TestAsset url=" << url <<
" useOpenFd=" << useOpenFd << endl;
TestRegister(plugin);
TestRemoveAllRights(plugin);
TestCheckRightsNotAcquired(plugin, url);
TestAcquireRights(plugin, url, PlaybackMode_Default);
TestAcquireRights(plugin, url, PlaybackMode_Default, useOpenFd);
TestCheckValidRights(plugin, url);
TestGetConstraints(plugin, url, PlaybackMode_Any);
TestRemoveRights(plugin, url);
TestCheckRightsNotAcquired(plugin, url);
TestAcquireRights(plugin, url, PlaybackMode_Offline);
TestAcquireRights(plugin, url, PlaybackMode_Offline, useOpenFd);
TestCheckValidRights(plugin, url);
TestGetConstraints(plugin, url, PlaybackMode_Offline);
TestRemoveRights(plugin, url);
TestCheckRightsNotAcquired(plugin, url);
TestAcquireRights(plugin, url, PlaybackMode_Streaming);
TestAcquireRights(plugin, url, PlaybackMode_Streaming, useOpenFd);
TestCheckValidRights(plugin, url);
TestGetConstraints(plugin, url, PlaybackMode_Streaming);
TestRemoveRights(plugin, url);
TestCheckRightsNotAcquired(plugin, url);
TestAcquireRights(plugin, url, PlaybackMode_Any);
TestAcquireRights(plugin, url, PlaybackMode_Any, useOpenFd);
TestCheckValidRights(plugin, url);
TestGetConstraints(plugin, url, PlaybackMode_Any);
TestRemoveRights(plugin, url);

View File

@@ -5,7 +5,7 @@
package com.widevine.demo;
import java.util.EventListener;
import java.io.FileInputStream;
//import java.util.HashMap;
import java.util.Set;
@@ -122,6 +122,15 @@ public class WidevineDrm {
rightsAcquisitionInfo = new DrmInfoRequest(DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO,
Settings.WIDEVINE_MIME_TYPE);
if (assetUri.startsWith("/sdcard")) {
try {
FileInputStream fis = new FileInputStream(assetUri);
rightsAcquisitionInfo.put("FileDescriptorKey", fis.getFD().toString());
}
catch (java.io.IOException e) {
logMessage("Unable to get fd for '" + assetUri + "'\n");
}
}
rightsAcquisitionInfo.put("WVDRMServerKey", Settings.DRM_SERVER_URI);
rightsAcquisitionInfo.put("WVAssetURIKey", assetUri);
rightsAcquisitionInfo.put("WVDeviceIDKey", Settings.DEVICE_ID);

View File

@@ -8,6 +8,9 @@
#include <stdio.h>
#include <stdint.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <iostream>
@@ -45,12 +48,14 @@ static void Terminate();
void PrintUsage(char *prog)
{
printf("Usage: %s <options> url\n", prog);
printf(" %s <options> -L filename\n", prog);
printf(" -o output_file\n");
printf(" -b block_size (default: %d)\n", DEFAULT_BLOCK_SIZE);
printf(" -p playback_buffer_size (default: %d)\n", (int)DEFAULT_PLAYBACK_BUFFER_SIZE);
printf(" -m print PTS -> media time\n");
printf(" -s start_time (default: %s)\n", DEFAULT_START_TIME);
printf(" -d drm_url\n");
printf(" -L open filname on local file system\n");
exit(-1);
}
@@ -222,33 +227,64 @@ static void CloseDrmPlugin()
}
}
static void AcquireRights(IDrmEngine *plugin, string url, string drmUrl)
static void AcquireRights(IDrmEngine *plugin, string url, string drmUrl,
bool isLocal)
{
String8 mimeType("video/wvm");
DrmInfoRequest rightsAcquisitionInfo(DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, mimeType);
int fdNum = -1;
rightsAcquisitionInfo.put(String8("WVDRMServerKey"), String8(drmUrl.c_str()));
rightsAcquisitionInfo.put(String8("WVAssetURIKey"), String8(url.c_str()));
if (isLocal) {
char fdStr[16];
fdNum = open(url.c_str(), O_RDONLY);
if (fdNum == -1) {
fprintf(stderr, "unable to open local movie file %s for reading.\n",
url.c_str());
close(fdNum);
Terminate();
}
sprintf(fdStr, "%lu", (unsigned long)fdNum);
rightsAcquisitionInfo.put(String8("FileDescriptorKey"), String8(fdStr));
}
rightsAcquisitionInfo.put(String8("WVDeviceIDKey"), String8("device1234"));
rightsAcquisitionInfo.put(String8("WVPortalKey"), String8("OEM"));
rightsAcquisitionInfo.put(String8("WVLicenseTypeKey"), String8("1"));
// Get asset rights from DRM. If it is necessary to
// read file metadata to get the asset ID, this can take several seconds.
DrmInfo *info = plugin->acquireDrmInfo(0, &rightsAcquisitionInfo);
if (info == NULL) {
fprintf(stderr, "acquireDrmInfo failed!\n");
if (isLocal) {
close(fdNum);
}
Terminate();
}
DrmInfoStatus *status = plugin->processDrmInfo(0, info);
if (status == NULL || status->statusCode != DrmInfoStatus::STATUS_OK) {
fprintf(stderr, "processDrmInfo failed!\n");
if (isLocal) {
close(fdNum);
}
Terminate();
}
if (plugin->checkRightsStatus(0, String8(url.c_str()), Action::DEFAULT) != RightsStatus::RIGHTS_VALID) {
fprintf(stderr, "checkValidRights default action failed!\n");
if (isLocal) {
close(fdNum);
}
Terminate();
}
if (isLocal) {
close(fdNum);
}
delete status;
delete info;
}
@@ -281,10 +317,11 @@ int main( int argc, char *argv[] )
unsigned long playbackBufferSize = DEFAULT_PLAYBACK_BUFFER_SIZE;
bool ptsToMediaTime = false;
string drmUrl = DEFAULT_DRM_URL;
bool isLocal = false;
_ah006(PrintMessage);
while ((option = getopt(argc, argv, "o:b:p:s:mD:d:")) != -1) {
while ((option = getopt(argc, argv, "o:b:p:s:mD:d:L")) != -1) {
switch (option) {
case 'o':
outputFile = optarg;
@@ -312,6 +349,10 @@ int main( int argc, char *argv[] )
drmUrl = optarg;
break;
case 'L':
isLocal = true;
break;
default:
printf("unknown option: '%c'\n", option);
PrintUsage(argv[0]);
@@ -327,7 +368,8 @@ int main( int argc, char *argv[] )
if (outputFile.size()) {
output = fopen(outputFile.c_str(), "wb");
if (!output) {
fprintf(stderr, "unable to open output file %s for writing\n", argv[2]);
fprintf(stderr, "unable to open output file %s for writing\n",
argv[2]);
Terminate();
}
}
@@ -347,7 +389,9 @@ int main( int argc, char *argv[] )
WV_SetLogging(WV_Logging_HTTP);
OpenDrmPlugin();
AcquireRights(sDrmPlugin, url, drmUrl);
// if isLocal is true, the url param holds a local filesystem filename
AcquireRights(sDrmPlugin, url, drmUrl, isLocal);
_ah002(_cb1);