blob: b5639a71a267d7092b93c559c97b8c51067338b0 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.
*/
package android.security.cts;
import android.media.MediaCrypto;
import android.media.MediaCryptoException;
import android.media.MediaDrm;
import android.media.MediaDrmException;
import android.media.NotProvisionedException;
import android.media.ResourceBusyException;
import android.test.AndroidTestCase;
import android.util.Log;
import java.util.UUID;
public class MediaCryptoTest extends AndroidTestCase {
private static final String TAG = "MediaCryptoTest";
private static final UUID CLEARKEY_SCHEME_UUID =
new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
private static final UUID WIDEVINE_SCHEME_UUID =
new UUID(0xedef8ba979d64aceL, 0xa3c827dcd51d21edL);
static {
System.loadLibrary("ctssecurity_jni");
}
private native boolean validateCryptoNative(MediaCrypto crypto);
public void testMediaCryptoClearKey() throws Exception {
MediaCrypto crypto = null;
if (!MediaDrm.isCryptoSchemeSupported(CLEARKEY_SCHEME_UUID)) {
Log.i(TAG, "No ClearKey plugin, skipping test");
return;
}
try {
byte[] initData = new byte[0];
crypto = new MediaCrypto(CLEARKEY_SCHEME_UUID, initData);
} catch (MediaCryptoException e) {
throw new Error("Failed to create MediaCrypto using ClearKey plugin");
}
assertTrue("MediaCrypto validation failed", validateCryptoNative(crypto));
}
public void testMediaCryptoWidevine() throws Exception {
if (!MediaDrm.isCryptoSchemeSupported(WIDEVINE_SCHEME_UUID)) {
Log.i(TAG, "No Widevine plugin, skipping test");
return;
}
MediaDrm drm = null;
byte[] sessionId = null;
try {
drm = new MediaDrm(WIDEVINE_SCHEME_UUID);
sessionId = openSession(drm);
getWidevineKeys(drm, sessionId);
MediaCrypto crypto = new MediaCrypto(WIDEVINE_SCHEME_UUID, sessionId);
assertTrue("MediaCrypto validation failed", validateCryptoNative(crypto));
} catch (MediaCryptoException | MediaDrmException e) {
if (drm != null && sessionId != null) {
drm.closeSession(sessionId);
}
throw e;
}
}
private byte[] openSession(MediaDrm drm) throws Exception {
byte[] sessionId = null;
int retryCount = 3;
while (retryCount-- > 0) {
try {
return drm.openSession();
} catch (NotProvisionedException e) {
Log.i(TAG, "Missing certificate, provisioning");
ProvisionRequester provisionRequester = new ProvisionRequester();
provisionRequester.doTransact(drm);
} catch (ResourceBusyException e) {
Log.w(TAG, "Resource busy in openSession, retrying...");
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
// ignore
}
}
}
throw new Error("Failed to open session");
}
private void getWidevineKeys(MediaDrm drm, byte[] sessionId) throws Exception {
final String kKeyServerUrl = "https://jmt17.google.com/video/license/GetCencLicense";
final byte[] kPssh = hex2ba("08011210e02562e04cd55351b14b3d748d36ed8e");
final String kClientAuth = "?source=YOUTUBE&video_id=EGHC6OHNbOo&oauth=ya.gtsqawidevine";
final String kPort = "80";
KeyRequester keyRequester = new KeyRequester(kPssh, kKeyServerUrl + ":" + kPort + kClientAuth);
if (keyRequester.doTransact(drm, sessionId, MediaDrm.KEY_TYPE_STREAMING) == null) {
throw new Error("Failed to get keys from license server!");
}
}
private static byte[] hex2ba(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}