diff --git a/libwvdrmengine/test/java/src/com/widevine/test/KeyRequester.java b/libwvdrmengine/test/java/src/com/widevine/test/KeyRequester.java index 56e99367..cbab3833 100644 --- a/libwvdrmengine/test/java/src/com/widevine/test/KeyRequester.java +++ b/libwvdrmengine/test/java/src/com/widevine/test/KeyRequester.java @@ -1,6 +1,8 @@ package com.widevine.test; import android.media.MediaDrm; +import android.media.NotProvisionedException; +import android.media.DeniedByServerException; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.HttpClient; import org.apache.http.client.ClientProtocolException; @@ -26,27 +28,69 @@ public class KeyRequester { } public void doTransact(MediaDrm drm, byte[] sessionId) { - MediaDrm.KeyRequest drmRequest; - drmRequest = drm.getKeyRequest(sessionId, mPssh, "video/avc", - MediaDrm.KEY_TYPE_STREAMING, null); - PostRequestTask postTask = new PostRequestTask(drmRequest.getData()); - postTask.execute(mServerUrl); - - // wait for post task to complete - byte[] responseBody; - long startTime = System.currentTimeMillis(); + boolean retryTransaction; do { - responseBody = postTask.getResponseBody(); - } while (responseBody == null && System.currentTimeMillis() - startTime < 5000); + retryTransaction = false; - if (responseBody == null) { - Log.d(TAG, "No response from license server!"); - } else { - byte[] drmResponse = parseResponseBody(responseBody); + MediaDrm.KeyRequest drmRequest = null; + boolean retryRequest; + do { + retryRequest = false; - drm.provideKeyResponse(sessionId, drmResponse); - } + try { + drmRequest = drm.getKeyRequest(sessionId, mPssh, "video/avc", + 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()); + postTask.execute(mServerUrl); + + // wait for post task to complete + byte[] responseBody; + long startTime = System.currentTimeMillis(); + + do { + responseBody = postTask.getResponseBody(); + if (responseBody == null) { + sleep(100); + } else { + break; + } + } while (System.currentTimeMillis() - startTime < 5000); + + if (responseBody == null) { + Log.e(TAG, "No response from license server!"); + } else { + byte[] drmResponse = parseResponseBody(responseBody); + if (drmResponse == null) { + Log.e(TAG, "No response body in response"); + } else { + try { + 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 { @@ -133,5 +177,12 @@ public class KeyRequester { return Arrays.copyOfRange(responseBody, drmMessageOffset + 4, responseBody.length); } + private void sleep(int msec) { + try { + Thread.sleep(msec); + } catch (InterruptedException e) { + } + } + } diff --git a/libwvdrmengine/test/java/src/com/widevine/test/MediaDrmAPITest.java b/libwvdrmengine/test/java/src/com/widevine/test/MediaDrmAPITest.java index 9d2cd339..bf8b0369 100644 --- a/libwvdrmengine/test/java/src/com/widevine/test/MediaDrmAPITest.java +++ b/libwvdrmengine/test/java/src/com/widevine/test/MediaDrmAPITest.java @@ -6,8 +6,10 @@ package com.widevine.test; import android.app.TabActivity; import android.os.Bundle; +import android.os.Looper; import android.media.MediaDrm; import android.media.MediaDrmException; +import android.media.NotProvisionedException; import android.media.MediaCrypto; import android.media.MediaCodec; import android.media.MediaCryptoException; @@ -53,7 +55,6 @@ public class MediaDrmAPITest extends TabActivity { mTestFailed = false; testWidevineSchemeSupported(); - testProvisioning(); testProperties(); testQueryKeyStatus(); 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() { if (!MediaDrm.isCryptoSchemeSupported(kWidevineScheme)) { Log.e(TAG, "testWidevineSchemeSupported failed"); @@ -74,15 +162,7 @@ public class MediaDrmAPITest extends TabActivity { } private void testProperties() { - MediaDrm drm = null; - try { - drm = new MediaDrm(kWidevineScheme); - } catch (MediaDrmException e) { - Log.e(TAG, "test failed due to exception: " + e.getMessage()); - e.printStackTrace(); - finish(); - } - + MediaDrm drm = startDrm(); Log.i(TAG, "vendor: " + drm.getPropertyString(MediaDrm.PROPERTY_VENDOR)); Log.i(TAG, "version: " + drm.getPropertyString(MediaDrm.PROPERTY_VERSION)); Log.i(TAG, "description: " + drm.getPropertyString(MediaDrm.PROPERTY_DESCRIPTION)); @@ -92,35 +172,13 @@ public class MediaDrmAPITest extends TabActivity { // widevine-specific properties Log.i(TAG, "security level: " + drm.getPropertyString("securityLevel")); Log.i(TAG, "system ID: " + drm.getPropertyString("systemId")); - } - - 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); + stopDrm(drm); } private void testQueryKeyStatus() { - MediaDrm drm = null; - try { - drm = new MediaDrm(kWidevineScheme); - } 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); + MediaDrm drm = startDrm(); + byte[] sessionId = openSession(drm); + getKeys(drm, sessionId); Log.i(TAG, "Query Key Status:"); HashMap keyStatus = drm.queryKeyStatus(sessionId); @@ -131,37 +189,29 @@ public class MediaDrmAPITest extends TabActivity { } 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() { - MediaDrm drm = null; - try { - drm = new MediaDrm(kWidevineScheme); - } 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); + MediaDrm drm = startDrm(); + byte[] sessionId = openSession(drm); + getKeys(drm, sessionId); testDecrypt(sessionId); drm.closeSession(sessionId); + stopDrm(drm); } private void testClearContentNoKeys() { - MediaDrm drm = null; - try { - drm = new MediaDrm(kWidevineScheme); - } catch (MediaDrmException e) { - Log.e(TAG, "test failed due to exception: " + e.getMessage()); - e.printStackTrace(); - finish(); - } - byte[] sessionId = drm.openSession(); + MediaDrm drm = startDrm(); + byte[] sessionId = openSession(drm); testClear(sessionId); drm.closeSession(sessionId); + stopDrm(drm); } private byte[] getTestModeSessionId(byte[] sessionId) { @@ -178,7 +228,7 @@ public class MediaDrmAPITest extends TabActivity { private void sleep(int msec) { try { - Thread.sleep(10); + Thread.sleep(msec); } catch (InterruptedException e) { } } diff --git a/libwvdrmengine/test/java/src/com/widevine/test/ProvisionRequester.java b/libwvdrmengine/test/java/src/com/widevine/test/ProvisionRequester.java index 97428a86..cb2a69ef 100644 --- a/libwvdrmengine/test/java/src/com/widevine/test/ProvisionRequester.java +++ b/libwvdrmengine/test/java/src/com/widevine/test/ProvisionRequester.java @@ -1,6 +1,7 @@ package com.widevine.test; import android.media.MediaDrm; +import android.media.DeniedByServerException; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.HttpClient; import org.apache.http.client.ClientProtocolException; @@ -33,12 +34,21 @@ public class ProvisionRequester { long startTime = System.currentTimeMillis(); do { 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) { - Log.d(TAG, "No response from provisioning server!"); + Log.e(TAG, "No response from provisioning server!"); } else { - drm.provideProvisionResponse(responseBody); + try { + drm.provideProvisionResponse(responseBody); + } catch (DeniedByServerException e) { + Log.e(TAG, "Server denied provisioning request"); + } } } @@ -95,5 +105,12 @@ public class ProvisionRequester { return null; } } + + private void sleep(int msec) { + try { + Thread.sleep(msec); + } catch (InterruptedException e) { + } + } }