Add testQueryKeyStatus tests to test Clearkey plugin implementation.
Add testQueryKeyStatus in ClearKeySystemTest and
NativeClearKeySystemTest.
Test: CTS - ClearSystemTests
ANDROID_BUILD_droid-cts/tools/cts-tradefed run cts -m
CtsMediaTestCases --test android.media.cts.ClearKeySystemTest
Test: CTS - NativeClearSystemTests
ANDROID_BUILD_droid-cts/tools/cts-tradefed run cts -m
CtsMediaTestCases --test android.media.cts.NativeClearKeySystemTest
bug: 64938501
Change-Id: I39df097afa0187818037dd0ce1bc38245e094821
diff --git a/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp b/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
index aa549b2..fa7025e 100644
--- a/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
@@ -493,6 +493,54 @@
}
}
+static void acquireLicense(
+ JNIEnv* env, const AMediaObjects& aMediaObjects, const AMediaDrmSessionId& sessionId,
+ AMediaDrmKeyType keyType) {
+ // Pointer to keyRequest memory, which remains until the next
+ // AMediaDrm_getKeyRequest call or until the drm object is released.
+ const uint8_t* keyRequest;
+ size_t keyRequestSize = 0;
+ std::string errorMessage;
+
+ // The server recognizes "video/mp4" but not "video/avc".
+ media_status_t status = AMediaDrm_getKeyRequest(aMediaObjects.getDrm(),
+ &sessionId, kClearkeyPssh, sizeof(kClearkeyPssh),
+ "video/mp4" /*mimeType*/, keyType,
+ NULL, 0, &keyRequest, &keyRequestSize);
+ if (status != AMEDIA_OK) {
+ errorMessage.assign("getKeyRequest failed, error = %d");
+ goto errorOut;
+ }
+
+ if (kKeyRequestSize != keyRequestSize) {
+ ALOGE("Invalid keyRequestSize %zd", kKeyRequestSize);
+ errorMessage.assign("Invalid key request size, error = %d");
+ status = AMEDIA_DRM_NEED_KEY;
+ goto errorOut;
+ }
+
+ if (memcmp(kKeyRequestData, keyRequest, kKeyRequestSize) != 0) {
+ errorMessage.assign("Invalid key request data is returned, error = %d");
+ status = AMEDIA_DRM_NEED_KEY;
+ goto errorOut;
+ }
+
+ AMediaDrmKeySetId keySetId;
+ gGotVendorDefinedEvent = false;
+ status = AMediaDrm_provideKeyResponse(aMediaObjects.getDrm(), &sessionId,
+ reinterpret_cast<const uint8_t*>(kResponse),
+ sizeof(kResponse), &keySetId);
+ if (status == AMEDIA_OK) {
+ return; // success
+ }
+
+ errorMessage.assign("provideKeyResponse failed, error = %d");
+
+errorOut:
+ AMediaDrm_closeSession(aMediaObjects.getDrm(), &sessionId);
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException", errorMessage.c_str(), status);
+}
+
extern "C" jboolean Java_android_media_cts_NativeClearKeySystemTest_testClearKeyPlaybackNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jobject playbackParams) {
if (NULL == uuid || NULL == playbackParams) {
@@ -562,44 +610,7 @@
return JNI_FALSE;
}
- // Pointer to keyRequest memory, which remains until the next
- // AMediaDrm_getKeyRequest call or until the drm object is released.
- const uint8_t* keyRequest;
- size_t keyRequestSize = 0;
-
- // The server recognizes "video/mp4" but not "video/avc".
- status = AMediaDrm_getKeyRequest(aMediaObjects.getDrm(), &sessionId,
- kClearkeyPssh, sizeof(kClearkeyPssh),
- "video/mp4" /*mimeType*/, KEY_TYPE_STREAMING,
- NULL, 0, &keyRequest, &keyRequestSize);
- if (status != AMEDIA_OK) {
- jniThrowExceptionFmt(env, "java/lang/RuntimeException",
- "getKeyRequest failed, error = %d", status);
- AMediaDrm_closeSession(aMediaObjects.getDrm(), &sessionId);
- return JNI_FALSE;
- }
-
- if (kKeyRequestSize != keyRequestSize) {
- ALOGE("Invalid keyRequestSize %zd", keyRequestSize);
- return JNI_FALSE;
- }
-
- if (memcmp(kKeyRequestData, keyRequest, kKeyRequestSize) != 0) {
- ALOGE("Invalid keyRequest data is returned");
- return JNI_FALSE;
- }
-
- AMediaDrmKeySetId keySetId;
- gGotVendorDefinedEvent = false;
- status = AMediaDrm_provideKeyResponse(aMediaObjects.getDrm(), &sessionId,
- reinterpret_cast<const uint8_t*>(kResponse),
- sizeof(kResponse), &keySetId);
- if (status != AMEDIA_OK) {
- jniThrowExceptionFmt(env, "java/lang/RuntimeException",
- "provideKeyResponse failed, error = %d", status);
- AMediaDrm_closeSession(aMediaObjects.getDrm(), &sessionId);
- return JNI_FALSE;
- }
+ acquireLicense(env, aMediaObjects, sessionId, KEY_TYPE_STREAMING);
// Check if the event listener has received the expected event sent by
// provideKeyResponse. This is for testing AMediaDrm_setOnEventListener().
@@ -635,6 +646,88 @@
return JNI_TRUE;
}
+extern "C" jboolean Java_android_media_cts_NativeClearKeySystemTest_testQueryKeyStatusNative(
+ JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
+
+ if (NULL == uuid) {
+ jniThrowException(env, "java/lang/NullPointerException", "null uuid");
+ return JNI_FALSE;
+ }
+
+ Uuid juuid = jbyteArrayToUuid(env, uuid);
+ if (!isUuidSizeValid(juuid)) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "invalid UUID size, expected %u bytes", kUuidSize);
+ return JNI_FALSE;
+ }
+
+ AMediaObjects aMediaObjects;
+ media_status_t status = AMEDIA_OK;
+ aMediaObjects.setDrm(AMediaDrm_createByUUID(&juuid[0]));
+ if (NULL == aMediaObjects.getDrm()) {
+ jniThrowException(env, "java/lang/RuntimeException", "failed to create drm");
+ return JNI_FALSE;
+ }
+
+ AMediaDrmSessionId sessionId;
+ status = AMediaDrm_openSession(aMediaObjects.getDrm(), &sessionId);
+ if (status != AMEDIA_OK) {
+ jniThrowException(env, "java/lang/RuntimeException",
+ "openSession failed");
+ return JNI_FALSE;
+ }
+
+ size_t numPairs = 3;
+ AMediaDrmKeyValue keyStatus[numPairs];
+
+ // Test for AMEDIA_DRM_SHORT_BUFFER
+ --numPairs;
+ status = AMediaDrm_queryKeyStatus(aMediaObjects.getDrm(), &sessionId, keyStatus, &numPairs);
+ if (status != AMEDIA_DRM_SHORT_BUFFER) {
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "AMediaDrm_queryKeyStatus should return AMEDIA_DRM_SHORT_BUFFER, error = %d",
+ status);
+ return JNI_FALSE;
+ }
+
+ // Test default key status
+ ++numPairs;
+ status = AMediaDrm_queryKeyStatus(aMediaObjects.getDrm(), &sessionId, keyStatus, &numPairs);
+ if (status != AMEDIA_OK) {
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "AMediaDrm_queryKeyStatus failed, error = %d", status);
+ return JNI_FALSE;
+ }
+
+ for (size_t i = 0; i < numPairs; ++i) {
+ ALOGI("AMediaDrm_queryKeyStatus: key=%s, value=%s", keyStatus[i].mKey, keyStatus[i].mValue);
+ }
+
+ acquireLicense(env, aMediaObjects, sessionId, KEY_TYPE_STREAMING);
+
+ // Test valid key status
+ numPairs = 3;
+ status = AMediaDrm_queryKeyStatus(aMediaObjects.getDrm(), &sessionId, keyStatus, &numPairs);
+ if (status != AMEDIA_OK) {
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "AMediaDrm_queryKeyStatus failed, error = %d", status);
+ return JNI_FALSE;
+ }
+
+ for (size_t i = 0; i < numPairs; ++i) {
+ ALOGI("AMediaDrm_queryKeyStatus: key=%s, value=%s", keyStatus[i].mKey, keyStatus[i].mValue);
+ }
+
+
+ status = AMediaDrm_closeSession(aMediaObjects.getDrm(), &sessionId);
+ if (status != AMEDIA_OK) {
+ jniThrowException(env, "java/lang/RuntimeException",
+ "closeSession failed");
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
static JNINativeMethod gMethods[] = {
{ "isCryptoSchemeSupportedNative", "([B)Z",
(void *)Java_android_media_cts_NativeClearKeySystemTest_isCryptoSchemeSupportedNative },
@@ -649,6 +742,9 @@
{ "testPsshNative", "([BLjava/lang/String;)Z",
(void *)Java_android_media_cts_NativeClearKeySystemTest__testPsshNative },
+
+ { "testQueryKeyStatusNative", "([B)Z",
+ (void *)Java_android_media_cts_NativeClearKeySystemTest_testQueryKeyStatusNative },
};
int register_android_media_cts_NativeClearKeySystemTest(JNIEnv* env) {
diff --git a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java b/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
index 94f8885..398bf1b 100644
--- a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
+++ b/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
@@ -31,6 +31,7 @@
import android.net.Uri;
import android.os.Environment;
import android.os.Looper;
+import android.support.annotation.NonNull;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Base64;
import android.util.Log;
@@ -42,8 +43,10 @@
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import java.util.Vector;
@@ -222,7 +225,7 @@
}
}
- private MediaDrm startDrm(final byte[][] clearKeys, final String initDataType, final UUID drmSchemeUuid) {
+ private @NonNull MediaDrm startDrm(final byte[][] clearKeys, final String initDataType, final UUID drmSchemeUuid) {
new Thread() {
@Override
public void run() {
@@ -279,7 +282,7 @@
mLooper.quit();
}
- private byte[] openSession(MediaDrm drm) {
+ private @NonNull byte[] openSession(MediaDrm drm) {
byte[] mSessionId = null;
boolean mRetryOpen;
do {
@@ -297,7 +300,7 @@
drm.closeSession(sessionId);
}
- public boolean isResolutionSupported(String mime, String[] features,
+ private boolean isResolutionSupported(String mime, String[] features,
int videoWidth, int videoHeight) {
if (ApiLevelUtil.isBefore(android.os.Build.VERSION_CODES.JELLY_BEAN)) {
if (videoHeight <= 144) {
@@ -343,10 +346,6 @@
mSessionId = null;
if (!scrambled) {
drm = startDrm(clearKeys, initDataType, drmSchemeUuid);
- if (null == drm) {
- throw new Error("Failed to create drm.");
- }
-
if (!drm.isCryptoSchemeSupported(drmSchemeUuid)) {
stopDrm(drm);
throw new Error("Crypto scheme is not supported.");
@@ -414,6 +413,64 @@
}
}
+ private boolean queryKeyStatus(@NonNull final MediaDrm drm, @NonNull final byte[] sessionId) {
+ final HashMap<String, String> keyStatus = drm.queryKeyStatus(sessionId);
+ if (keyStatus.isEmpty()) {
+ Log.e(TAG, "queryKeyStatus: empty key status");
+ return false;
+ }
+
+ final Set<String> keySet = keyStatus.keySet();
+ final int numKeys = keySet.size();
+ final String[] keys = keySet.toArray(new String[numKeys]);
+ for (int i = 0; i < numKeys; ++i) {
+ final String key = keys[i];
+ Log.i(TAG, "queryKeyStatus: key=" + key + ", value=" + keyStatus.get(key));
+ }
+
+ return true;
+ }
+
+ public void testQueryKeyStatus() throws Exception {
+ MediaDrm drm = startDrm(new byte[][] { CLEAR_KEY_CENC }, "cenc", COMMON_PSSH_SCHEME_UUID);
+ if (!drm.isCryptoSchemeSupported(COMMON_PSSH_SCHEME_UUID)) {
+ stopDrm(drm);
+ throw new Error("Crypto scheme is not supported.");
+ }
+
+ // Test default key status
+ mSessionId = openSession(drm);
+ if (!queryKeyStatus(drm, mSessionId)) {
+ closeSession(drm, mSessionId);
+ stopDrm(drm);
+ throw new Error("query default key status failed");
+ }
+
+ // Test valid key status
+ mMediaCodecPlayer = new MediaCodecClearKeyPlayer(
+ getActivity().getSurfaceHolder(),
+ mSessionId, false,
+ mContext.getResources());
+ mMediaCodecPlayer.setAudioDataSource(CENC_AUDIO_URL, null, false);
+ mMediaCodecPlayer.setVideoDataSource(CENC_VIDEO_URL, null, true);
+ mMediaCodecPlayer.start();
+ mMediaCodecPlayer.prepare();
+
+ mDrmInitData = mMediaCodecPlayer.getDrmInitData();
+ getKeys(drm, "cenc", mSessionId, mDrmInitData, new byte[][] { CLEAR_KEY_CENC });
+ boolean success = true;
+ if (!queryKeyStatus(drm, mSessionId)) {
+ success = false;
+ }
+
+ mMediaCodecPlayer.reset();
+ closeSession(drm, mSessionId);
+ stopDrm(drm);
+ if (!success) {
+ throw new Error("query key status failed");
+ }
+ }
+
public void testClearKeyPlaybackCenc() throws Exception {
testClearKeyPlayback(
COMMON_PSSH_SCHEME_UUID,
diff --git a/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java b/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java
index 2375d46..45b2b8b 100644
--- a/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java
@@ -127,6 +127,10 @@
CENC_CLEARKEY_VIDEO_URL.toString()));
}
+ public void testQueryKeyStatus() throws Exception {
+ assertTrue(testQueryKeyStatusNative(uuidByteArray(COMMON_PSSH_SCHEME_UUID)));
+ }
+
public void testGetPropertyString() throws Exception {
StringBuffer value = new StringBuffer();
testGetPropertyStringNative(uuidByteArray(COMMON_PSSH_SCHEME_UUID), "description", value);
@@ -230,6 +234,8 @@
private static native boolean testPsshNative(final byte[] uuid, final String videoUrl);
+ private static native boolean testQueryKeyStatusNative(final byte[] uuid);
+
public void testClearKeyPlaybackCenc() throws Exception {
testClearKeyPlayback(
COMMON_PSSH_SCHEME_UUID,