Hook up events and new exceptions in the MediaDrm API test

Bug: 8725707

Merge of https://widevine-internal-review.googlesource.com/#/c/5302/
from the Widevine CDM repository

Change-Id: If142e558585e5cc7ba0cecf45693413943b2b64f
This commit is contained in:
Jeff Tinker
2013-04-30 17:35:29 -07:00
parent d291efc823
commit cb5541b740
3 changed files with 196 additions and 78 deletions

View File

@@ -1,6 +1,8 @@
package com.widevine.test; package com.widevine.test;
import android.media.MediaDrm; import android.media.MediaDrm;
import android.media.NotProvisionedException;
import android.media.DeniedByServerException;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
@@ -26,9 +28,31 @@ public class KeyRequester {
} }
public void doTransact(MediaDrm drm, byte[] sessionId) { public void doTransact(MediaDrm drm, byte[] sessionId) {
MediaDrm.KeyRequest drmRequest;
boolean retryTransaction;
do {
retryTransaction = false;
MediaDrm.KeyRequest drmRequest = null;
boolean retryRequest;
do {
retryRequest = false;
try {
drmRequest = drm.getKeyRequest(sessionId, mPssh, "video/avc", drmRequest = drm.getKeyRequest(sessionId, mPssh, "video/avc",
MediaDrm.KEY_TYPE_STREAMING, null); MediaDrm.KEY_TYPE_STREAMING, null);
} catch (NotProvisionedException e) {
Log.i(TAG, "Invalid certificate, reprovisioning");
ProvisionRequester provisionRequester = new ProvisionRequester();
provisionRequester.doTransact(drm);
retryRequest = true;
}
} while (retryRequest);
if (drmRequest == null) {
Log.e(TAG, "Failed to get key request");
return;
}
PostRequestTask postTask = new PostRequestTask(drmRequest.getData()); PostRequestTask postTask = new PostRequestTask(drmRequest.getData());
postTask.execute(mServerUrl); postTask.execute(mServerUrl);
@@ -36,18 +60,38 @@ public class KeyRequester {
// wait for post task to complete // wait for post task to complete
byte[] responseBody; byte[] responseBody;
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
do { do {
responseBody = postTask.getResponseBody(); responseBody = postTask.getResponseBody();
} while (responseBody == null && System.currentTimeMillis() - startTime < 5000); if (responseBody == null) {
sleep(100);
} else {
break;
}
} while (System.currentTimeMillis() - startTime < 5000);
if (responseBody == null) { if (responseBody == null) {
Log.d(TAG, "No response from license server!"); Log.e(TAG, "No response from license server!");
} else { } else {
byte[] drmResponse = parseResponseBody(responseBody); byte[] drmResponse = parseResponseBody(responseBody);
if (drmResponse == null) {
Log.e(TAG, "No response body in response");
} else {
try {
drm.provideKeyResponse(sessionId, drmResponse); drm.provideKeyResponse(sessionId, drmResponse);
} catch (NotProvisionedException e) {
Log.i(TAG, "Key response invalidated the certificate, reprovisioning");
ProvisionRequester provisionRequester = new ProvisionRequester();
provisionRequester.doTransact(drm);
retryTransaction = true;
} catch (DeniedByServerException e) {
// informational, the event handler will take care of provisioning
Log.e(TAG, "Server rejected the key request");
} }
} }
}
} while (retryTransaction);
}
private class PostRequestTask extends AsyncTask<String, Void, Void> { private class PostRequestTask extends AsyncTask<String, Void, Void> {
private final String TAG = "PostRequestTask"; private final String TAG = "PostRequestTask";
@@ -133,5 +177,12 @@ public class KeyRequester {
return Arrays.copyOfRange(responseBody, drmMessageOffset + 4, responseBody.length); return Arrays.copyOfRange(responseBody, drmMessageOffset + 4, responseBody.length);
} }
private void sleep(int msec) {
try {
Thread.sleep(msec);
} catch (InterruptedException e) {
}
}
} }

View File

@@ -6,8 +6,10 @@ package com.widevine.test;
import android.app.TabActivity; import android.app.TabActivity;
import android.os.Bundle; import android.os.Bundle;
import android.os.Looper;
import android.media.MediaDrm; import android.media.MediaDrm;
import android.media.MediaDrmException; import android.media.MediaDrmException;
import android.media.NotProvisionedException;
import android.media.MediaCrypto; import android.media.MediaCrypto;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCryptoException; import android.media.MediaCryptoException;
@@ -53,7 +55,6 @@ public class MediaDrmAPITest extends TabActivity {
mTestFailed = false; mTestFailed = false;
testWidevineSchemeSupported(); testWidevineSchemeSupported();
testProvisioning();
testProperties(); testProperties();
testQueryKeyStatus(); testQueryKeyStatus();
testClearContentNoKeys(); testClearContentNoKeys();
@@ -66,6 +67,93 @@ public class MediaDrmAPITest extends TabActivity {
} }
} }
private MediaDrm mDrm;
private Looper mLooper;
private Object mLock = new Object();
private MediaDrm startDrm() {
new Thread() {
@Override
public void run() {
// Set up a looper to handle events
Looper.prepare();
// Save the looper so that we can terminate this thread
// after we are done with it.
mLooper = Looper.myLooper();
try {
mDrm = new MediaDrm(kWidevineScheme);
} catch (MediaDrmException e) {
Log.e(TAG, "Failed to create MediaDrm: " + e.getMessage());
e.printStackTrace();
return;
}
synchronized(mLock) {
mDrm.setOnEventListener(new MediaDrm.OnEventListener() {
@Override
public void onEvent(MediaDrm md, byte[] sessionId, int event,
int extra, byte[] data) {
if (event == MediaDrm.EVENT_PROVISION_REQUIRED) {
Log.i(TAG, "Provisioning is required");
} else if (event == MediaDrm.EVENT_KEY_REQUIRED) {
Log.i(TAG, "MediaDrm event: Key required");
} else if (event == MediaDrm.EVENT_KEY_EXPIRED) {
Log.i(TAG, "MediaDrm event: Key expired");
} else if (event == MediaDrm.EVENT_VENDOR_DEFINED) {
Log.i(TAG, "MediaDrm event: Vendor defined: " + event);
}
}
});
mLock.notify();
}
Looper.loop(); // Blocks forever until Looper.quit() is called.
}
}.start();
// wait for mDrm to be created
synchronized(mLock) {
try {
mLock.wait(1000);
} catch (Exception e) {
}
}
if (mDrm == null) {
Log.e(TAG, "Failed to create drm");
}
return mDrm;
}
private void stopDrm(MediaDrm drm) {
if (drm != mDrm) {
Log.e(TAG, "invalid drm specified in stopDrm");
}
mLooper.quit();
}
private byte[] openSession(MediaDrm drm) {
byte[] sessionId = null;
boolean retryOpen;
do {
try {
retryOpen = false;
sessionId = drm.openSession();
} catch (NotProvisionedException e) {
Log.i(TAG, "Missing certificate, provisioning");
ProvisionRequester provisionRequester = new ProvisionRequester();
provisionRequester.doTransact(drm);
retryOpen = true;
}
} while (retryOpen);
return sessionId;
}
private void testWidevineSchemeSupported() { private void testWidevineSchemeSupported() {
if (!MediaDrm.isCryptoSchemeSupported(kWidevineScheme)) { if (!MediaDrm.isCryptoSchemeSupported(kWidevineScheme)) {
Log.e(TAG, "testWidevineSchemeSupported failed"); Log.e(TAG, "testWidevineSchemeSupported failed");
@@ -74,15 +162,7 @@ public class MediaDrmAPITest extends TabActivity {
} }
private void testProperties() { private void testProperties() {
MediaDrm drm = null; MediaDrm drm = startDrm();
try {
drm = new MediaDrm(kWidevineScheme);
} catch (MediaDrmException e) {
Log.e(TAG, "test failed due to exception: " + e.getMessage());
e.printStackTrace();
finish();
}
Log.i(TAG, "vendor: " + drm.getPropertyString(MediaDrm.PROPERTY_VENDOR)); Log.i(TAG, "vendor: " + drm.getPropertyString(MediaDrm.PROPERTY_VENDOR));
Log.i(TAG, "version: " + drm.getPropertyString(MediaDrm.PROPERTY_VERSION)); Log.i(TAG, "version: " + drm.getPropertyString(MediaDrm.PROPERTY_VERSION));
Log.i(TAG, "description: " + drm.getPropertyString(MediaDrm.PROPERTY_DESCRIPTION)); Log.i(TAG, "description: " + drm.getPropertyString(MediaDrm.PROPERTY_DESCRIPTION));
@@ -92,35 +172,13 @@ public class MediaDrmAPITest extends TabActivity {
// widevine-specific properties // widevine-specific properties
Log.i(TAG, "security level: " + drm.getPropertyString("securityLevel")); Log.i(TAG, "security level: " + drm.getPropertyString("securityLevel"));
Log.i(TAG, "system ID: " + drm.getPropertyString("systemId")); Log.i(TAG, "system ID: " + drm.getPropertyString("systemId"));
} stopDrm(drm);
private void testProvisioning() {
MediaDrm drm = null;
try {
drm = new MediaDrm(kWidevineScheme);
} catch (MediaDrmException e) {
Log.e(TAG, "test failed due to exception: " + e.getMessage());
e.printStackTrace();
finish();
}
ProvisionRequester provisionRequester = new ProvisionRequester();
provisionRequester.doTransact(drm);
} }
private void testQueryKeyStatus() { private void testQueryKeyStatus() {
MediaDrm drm = null; MediaDrm drm = startDrm();
try { byte[] sessionId = openSession(drm);
drm = new MediaDrm(kWidevineScheme); getKeys(drm, sessionId);
} catch (MediaDrmException e) {
Log.e(TAG, "test failed due to exception: " + e.getMessage());
e.printStackTrace();
finish();
}
byte[] sessionId = drm.openSession();
KeyRequester keyRequester = new KeyRequester(kPssh, kKeyServerUrl + ":" + kPort + kClientAuth);
keyRequester.doTransact(drm, sessionId);
Log.i(TAG, "Query Key Status:"); Log.i(TAG, "Query Key Status:");
HashMap<String, String> keyStatus = drm.queryKeyStatus(sessionId); HashMap<String, String> keyStatus = drm.queryKeyStatus(sessionId);
@@ -131,37 +189,29 @@ public class MediaDrmAPITest extends TabActivity {
} }
drm.closeSession(sessionId); drm.closeSession(sessionId);
stopDrm(drm);
}
private void getKeys(MediaDrm drm, byte[] sessionId) {
KeyRequester keyRequester = new KeyRequester(kPssh, kKeyServerUrl + ":" + kPort + kClientAuth);
keyRequester.doTransact(drm, sessionId);
} }
private void testEncryptedContent() { private void testEncryptedContent() {
MediaDrm drm = null; MediaDrm drm = startDrm();
try { byte[] sessionId = openSession(drm);
drm = new MediaDrm(kWidevineScheme); getKeys(drm, sessionId);
} catch (MediaDrmException e) {
Log.e(TAG, "test failed due to exception: " + e.getMessage());
e.printStackTrace();
finish();
}
byte[] sessionId = drm.openSession();
KeyRequester keyRequester = new KeyRequester(kPssh, kKeyServerUrl + ":" + kPort + kClientAuth);
keyRequester.doTransact(drm, sessionId);
testDecrypt(sessionId); testDecrypt(sessionId);
drm.closeSession(sessionId); drm.closeSession(sessionId);
stopDrm(drm);
} }
private void testClearContentNoKeys() { private void testClearContentNoKeys() {
MediaDrm drm = null; MediaDrm drm = startDrm();
try { byte[] sessionId = openSession(drm);
drm = new MediaDrm(kWidevineScheme);
} catch (MediaDrmException e) {
Log.e(TAG, "test failed due to exception: " + e.getMessage());
e.printStackTrace();
finish();
}
byte[] sessionId = drm.openSession();
testClear(sessionId); testClear(sessionId);
drm.closeSession(sessionId); drm.closeSession(sessionId);
stopDrm(drm);
} }
private byte[] getTestModeSessionId(byte[] sessionId) { private byte[] getTestModeSessionId(byte[] sessionId) {
@@ -178,7 +228,7 @@ public class MediaDrmAPITest extends TabActivity {
private void sleep(int msec) { private void sleep(int msec) {
try { try {
Thread.sleep(10); Thread.sleep(msec);
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
} }

View File

@@ -1,6 +1,7 @@
package com.widevine.test; package com.widevine.test;
import android.media.MediaDrm; import android.media.MediaDrm;
import android.media.DeniedByServerException;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
@@ -33,12 +34,21 @@ public class ProvisionRequester {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
do { do {
responseBody = postTask.getResponseBody(); responseBody = postTask.getResponseBody();
} while (responseBody == null && System.currentTimeMillis() - startTime < 5000); if (responseBody == null) {
sleep(100);
} else {
break;
}
} while (System.currentTimeMillis() - startTime < 5000);
if (responseBody == null) { if (responseBody == null) {
Log.d(TAG, "No response from provisioning server!"); Log.e(TAG, "No response from provisioning server!");
} else { } else {
try {
drm.provideProvisionResponse(responseBody); drm.provideProvisionResponse(responseBody);
} catch (DeniedByServerException e) {
Log.e(TAG, "Server denied provisioning request");
}
} }
} }
@@ -95,5 +105,12 @@ public class ProvisionRequester {
return null; return null;
} }
} }
private void sleep(int msec) {
try {
Thread.sleep(msec);
} catch (InterruptedException e) {
}
}
} }