Add additional error conditions to MediaDrm

New codes are being added to handle resource
contention, lost session state, frame size too
large and insufficient security level for
decryption. Also cleans up inconsistent use of
tamper detected error where invalid state error
should have been used.

bug:111504510
bug:111505796
test: cts and gts media test cases

Change-Id: Ifa652d31ea151fbdc9faa0dd15b19f885d82b916
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index be71dad5..8336459 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -110,6 +110,7 @@
     jint kWhatDrmEvent;
     jint kWhatExpirationUpdate;
     jint kWhatKeyStatusChange;
+    jint kWhatSessionLostState;
 } gEventWhat;
 
 struct KeyTypes {
@@ -141,6 +142,16 @@
     jclass classId;
 };
 
+struct SessionExceptionFields {
+    jmethodID init;
+    jclass classId;
+    jfieldID errorCode;
+};
+
+struct SessionExceptionErrorCodes {
+    jint kResourceContention;
+} gSessionExceptionErrorCodes;
+
 struct HDCPLevels {
     jint kHdcpLevelUnknown;
     jint kHdcpNone;
@@ -180,6 +191,7 @@
     EntryFields entry;
     CertificateFields certificate;
     StateExceptionFields stateException;
+    SessionExceptionFields sessionException;
     jclass certificateClassId;
     jclass hashmapClassId;
     jclass arraylistClassId;
@@ -310,6 +322,9 @@
          case DrmPlugin::kDrmPluginEventKeysChange:
             jwhat = gEventWhat.kWhatKeyStatusChange;
             break;
+         case DrmPlugin::kDrmPluginEventSessionLostState:
+            jwhat = gEventWhat.kWhatSessionLostState;
+            break;
         default:
             ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
             return;
@@ -343,6 +358,30 @@
     env->Throw(static_cast<jthrowable>(exception));
 }
 
+static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
+    ALOGE("Session exception: %s (%d)", msg, err);
+
+    jint jErrorCode = 0;
+    switch(err) {
+        case ERROR_DRM_RESOURCE_CONTENTION:
+            jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
+            break;
+        default:
+            break;
+    }
+
+    jobject exception = env->NewObject(gFields.sessionException.classId,
+            gFields.sessionException.init, static_cast<int>(err),
+            env->NewStringUTF(msg));
+
+    env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
+    env->Throw(static_cast<jthrowable>(exception));
+}
+
+static bool isSessionException(status_t err) {
+    return err == ERROR_DRM_RESOURCE_CONTENTION;
+}
+
 static bool throwExceptionAsNecessary(
         JNIEnv *env, status_t err, const char *msg = NULL) {
 
@@ -370,7 +409,7 @@
     case ERROR_DRM_CANNOT_HANDLE:
         drmMessage = "Invalid parameter or data format";
         break;
-    case ERROR_DRM_TAMPER_DETECTED:
+    case ERROR_DRM_INVALID_STATE:
         drmMessage = "Invalid state";
         break;
     default:
@@ -399,6 +438,9 @@
         jniThrowException(env, "android/media/MediaDrmResetException",
                 "mediaserver died");
         return true;
+    } else if (isSessionException(err)) {
+        throwSessionException(env, msg, err);
+        return true;
     } else if (err != OK) {
         String8 errbuf;
         if (drmMessage != NULL) {
@@ -705,6 +747,8 @@
     gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
     GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
     gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
+    gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
 
     GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
     gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
@@ -831,6 +875,14 @@
     FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
     GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
     gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+    FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
+    GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
+    gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+    GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
+
+    GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
+    gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
 }
 
 static void android_media_MediaDrm_native_setup(