MediaDrm: comprehensive exception messages

Bug: 162255728
Test: gts MediaDrmTest#testExceptionMessage
Change-Id: I15578a08a0b0a85e2f64eb90e6957c1941149cd6
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 6f1b6d3..73e1f7d 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -422,43 +422,11 @@
 }
 
 static bool throwExceptionAsNecessary(
-        JNIEnv *env, status_t err, const char *msg = NULL) {
-
-    const char *drmMessage = NULL;
-
-    switch (err) {
-    case ERROR_DRM_UNKNOWN:
-        drmMessage = "General DRM error";
-        break;
-    case ERROR_DRM_NO_LICENSE:
-        drmMessage = "No license";
-        break;
-    case ERROR_DRM_LICENSE_EXPIRED:
-        drmMessage = "License expired";
-        break;
-    case ERROR_DRM_SESSION_NOT_OPENED:
-        drmMessage = "Session not opened";
-        break;
-    case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
-        drmMessage = "Not initialized";
-        break;
-    case ERROR_DRM_DECRYPT:
-        drmMessage = "Decrypt error";
-        break;
-    case ERROR_DRM_CANNOT_HANDLE:
-        drmMessage = "Invalid parameter or data format";
-        break;
-    case ERROR_DRM_INVALID_STATE:
-        drmMessage = "Invalid state";
-        break;
-    default:
-        break;
-    }
-
-    String8 vendorMessage;
-    if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
-        vendorMessage = String8::format("DRM vendor-defined error: %d", err);
-        drmMessage = vendorMessage.string();
+        JNIEnv *env, const sp<IDrm> &drm, status_t err, const char *msg = NULL) {
+    std::string msgStr;
+    if (drm != NULL) {
+        msgStr = DrmUtils::GetExceptionMessage(err, msg, drm);
+        msg = msgStr.c_str();
     }
 
     if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
@@ -484,15 +452,6 @@
         throwSessionException(env, msg, err);
         return true;
     } else if (err != OK) {
-        String8 errbuf;
-        if (drmMessage != NULL) {
-            if (msg == NULL) {
-                msg = drmMessage;
-            } else {
-                errbuf = String8::format("%s: %s", msg, drmMessage);
-                msg = errbuf.string();
-            }
-        }
         throwStateException(env, msg, err);
         return true;
     }
@@ -1090,7 +1049,7 @@
     status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
             securityLevel, &isSupported);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
+    if (throwExceptionAsNecessary(env, NULL, err, "Failed to query crypto scheme support")) {
         return false;
     }
     return isSupported;
@@ -1113,7 +1072,7 @@
 
     status_t err = drm->openSession(level, sessionId);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to open session")) {
         return NULL;
     }
 
@@ -1132,7 +1091,7 @@
 
     status_t err = drm->closeSession(sessionId);
 
-    throwExceptionAsNecessary(env, err, "Failed to close session");
+    throwExceptionAsNecessary(env, drm, err, "Failed to close session");
 }
 
 static jobject android_media_MediaDrm_getKeyRequest(
@@ -1185,7 +1144,7 @@
     status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
             keyType, optParams, request, defaultUrl, &keyRequestType);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get key request")) {
         return NULL;
     }
 
@@ -1255,7 +1214,7 @@
 
     status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to handle key response")) {
         return NULL;
     }
     return VectorToJByteArray(env, keySetId);
@@ -1279,7 +1238,7 @@
 
     status_t err = drm->removeKeys(keySetId);
 
-    throwExceptionAsNecessary(env, err, "Failed to remove keys");
+    throwExceptionAsNecessary(env, drm, err, "Failed to remove keys");
 }
 
 static void android_media_MediaDrm_restoreKeys(
@@ -1302,7 +1261,7 @@
 
     status_t err = drm->restoreKeys(sessionId, keySetId);
 
-    throwExceptionAsNecessary(env, err, "Failed to restore keys");
+    throwExceptionAsNecessary(env, drm, err, "Failed to restore keys");
 }
 
 static jobject android_media_MediaDrm_queryKeyStatus(
@@ -1318,7 +1277,7 @@
 
     status_t err = drm->queryKeyStatus(sessionId, infoMap);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to query key status")) {
         return NULL;
     }
 
@@ -1348,7 +1307,7 @@
     String8 certAuthority = JStringToString8(env, jcertAuthority);
     status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get provision request")) {
         return NULL;
     }
 
@@ -1403,7 +1362,7 @@
         env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
     }
 
-    throwExceptionAsNecessary(env, err, "Failed to handle provision response");
+    throwExceptionAsNecessary(env, drm, err, "Failed to handle provision response");
     return certificateObj;
 }
 
@@ -1419,7 +1378,7 @@
 
     status_t err = drm->getSecureStops(secureStops);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stops")) {
         return NULL;
     }
 
@@ -1438,7 +1397,7 @@
 
     status_t err = drm->getSecureStopIds(secureStopIds);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop Ids")) {
         return NULL;
     }
 
@@ -1457,7 +1416,7 @@
 
     status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop")) {
         return NULL;
     }
 
@@ -1476,7 +1435,7 @@
 
     status_t err = drm->releaseSecureStops(ssRelease);
 
-    throwExceptionAsNecessary(env, err, "Failed to release secure stops");
+    throwExceptionAsNecessary(env, drm, err, "Failed to release secure stops");
 }
 
 static void android_media_MediaDrm_removeSecureStop(
@@ -1489,7 +1448,7 @@
 
     status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
 
-    throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
+    throwExceptionAsNecessary(env, drm, err, "Failed to remove secure stop");
 }
 
 static void android_media_MediaDrm_removeAllSecureStops(
@@ -1502,7 +1461,7 @@
 
     status_t err = drm->removeAllSecureStops();
 
-    throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
+    throwExceptionAsNecessary(env, drm, err, "Failed to remove all secure stops");
 }
 
 
@@ -1541,7 +1500,7 @@
 
     status_t err = drm->getHdcpLevels(&connected, &max);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
         return gHdcpLevels.kHdcpLevelUnknown;
     }
     return HdcpLevelTojint(connected);
@@ -1560,7 +1519,7 @@
 
     status_t err = drm->getHdcpLevels(&connected, &max);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
         return gHdcpLevels.kHdcpLevelUnknown;
     }
     return HdcpLevelTojint(max);
@@ -1577,7 +1536,7 @@
     uint32_t open = 0, max = 0;
     status_t err = drm->getNumberOfSessions(&open, &max);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
         return 0;
     }
     return open;
@@ -1594,7 +1553,7 @@
     uint32_t open = 0, max = 0;
     status_t err = drm->getNumberOfSessions(&open, &max);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
         return 0;
     }
     return max;
@@ -1614,7 +1573,7 @@
 
     status_t err = drm->getSecurityLevel(sessionId, &level);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get security level")) {
         return gSecurityLevels.kSecurityLevelUnknown;
     }
 
@@ -1646,7 +1605,7 @@
 
     status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline key set Ids")) {
         return NULL;
     }
 
@@ -1663,7 +1622,7 @@
 
     status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
 
-    throwExceptionAsNecessary(env, err, "Failed to remove offline license");
+    throwExceptionAsNecessary(env, drm, err, "Failed to remove offline license");
 }
 
 static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
@@ -1680,7 +1639,7 @@
 
     status_t err = drm->getOfflineLicenseState(keySetId, &state);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline license state")) {
         return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
     }
 
@@ -1713,7 +1672,7 @@
 
     status_t err = drm->getPropertyString(name, value);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
         return NULL;
     }
 
@@ -1739,7 +1698,7 @@
 
     status_t err = drm->getPropertyByteArray(name, value);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
         return NULL;
     }
 
@@ -1771,7 +1730,7 @@
 
     status_t err = drm->setPropertyString(name, value);
 
-    throwExceptionAsNecessary(env, err, "Failed to set property");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set property");
 }
 
 static void android_media_MediaDrm_setPropertyByteArray(
@@ -1799,7 +1758,7 @@
 
     status_t err = drm->setPropertyByteArray(name, value);
 
-    throwExceptionAsNecessary(env, err, "Failed to set property");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set property");
 }
 
 static void android_media_MediaDrm_setCipherAlgorithmNative(
@@ -1823,7 +1782,7 @@
 
     status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
 
-    throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set cipher algorithm");
 }
 
 static void android_media_MediaDrm_setMacAlgorithmNative(
@@ -1847,7 +1806,7 @@
 
     status_t err = drm->setMacAlgorithm(sessionId, algorithm);
 
-    throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set mac algorithm");
 }
 
 
@@ -1875,7 +1834,7 @@
 
     status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to encrypt")) {
         return NULL;
     }
 
@@ -1905,7 +1864,7 @@
     Vector<uint8_t> output;
 
     status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
-    if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to decrypt")) {
         return NULL;
     }
 
@@ -1935,7 +1894,7 @@
 
     status_t err = drm->sign(sessionId, keyId, message, signature);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
         return NULL;
     }
 
@@ -1966,7 +1925,7 @@
 
     status_t err = drm->verify(sessionId, keyId, message, signature, match);
 
-    throwExceptionAsNecessary(env, err, "Failed to verify");
+    throwExceptionAsNecessary(env, drm, err, "Failed to verify");
     return match;
 }
 
@@ -2015,7 +1974,7 @@
 
     status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
 
-    if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
         return NULL;
     }
 
@@ -2062,7 +2021,7 @@
         playbackId = JStringToString8(env, jplaybackId);
     }
     status_t err = drm->setPlaybackId(sessionId, playbackId.c_str());
-    throwExceptionAsNecessary(env, err, "Failed to set playbackId");
+    throwExceptionAsNecessary(env, drm, err, "Failed to set playbackId");
 }
 
 static jobject android_media_MediaDrm_getLogMessages(
@@ -2075,7 +2034,7 @@
     Vector<drm::V1_4::LogMessage> logs;
     status_t err = drm->getLogMessages(logs);
     ALOGI("drm->getLogMessages %zu logs", logs.size());
-    if (throwExceptionAsNecessary(env, err, "Failed to get log messages")) {
+    if (throwExceptionAsNecessary(env, drm, err, "Failed to get log messages")) {
         return NULL;
     }
     return hidlLogMessagesToJavaList(env, logs);