Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ed38266 authored by Jeff Tinker's avatar Jeff Tinker
Browse files

Define error codes for MediaCodec.CryptoException

Define specific failure cases so apps have the information they
need to deal with these conditions.

Also adds a new ResourceBusyException to MediaDrm

Change-Id: Iaecf269d58108f28179974b05671bf29b9fe4b7d
related-to-bug: 10157154
related-to-bug: 9695816
parent d8501485
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -12029,6 +12029,9 @@ package android.media {
  public static final class MediaCodec.CryptoException extends java.lang.RuntimeException {
    ctor public MediaCodec.CryptoException(int, java.lang.String);
    method public int getErrorCode();
    field public static final int ERROR_KEY_EXPIRED = 2; // 0x2
    field public static final int ERROR_NO_KEY = 1; // 0x1
    field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
  }
  public static final class MediaCodec.CryptoInfo {
+18 −0
Original line number Diff line number Diff line
@@ -300,6 +300,24 @@ final public class MediaCodec {
            mErrorCode = errorCode;
        }

        /**
         * This indicates that no key has been set to perform the requested
         * decrypt operation.
         */
        public static final int ERROR_NO_KEY = 1;

        /**
         * This indicates that the key used for decryption is no longer
         * valid due to license term expiration.
         */
        public static final int ERROR_KEY_EXPIRED = 2;

        /**
         * This indicates that a required crypto resource was not able to be
         * allocated while attempting the requested operation.
         */
        public static final int ERROR_RESOURCE_BUSY = 3;

        public int getErrorCode() {
            return mErrorCode;
        }
+2 −0
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ public final class MediaDrm {
     * Open a new session with the MediaDrm object.  A session ID is returned.
     *
     * @throws NotProvisionedException if provisioning is needed
     * @throws ResourceBusyException if required resources are in use
     */
    public native byte[] openSession() throws NotProvisionedException;

@@ -379,6 +380,7 @@ public final class MediaDrm {
     * reprovisioning is required
     * @throws DeniedByServerException if the response indicates that the
     * server rejected the request
     * @throws ResourceBusyException if required resources are in use
     */
    public native byte[] provideKeyResponse(byte[] scope, byte[] response)
        throws NotProvisionedException, DeniedByServerException;
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 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.media;

/**
 * Exception thrown when an operation on a MediaDrm object is attempted
 * and hardware resources are not available, due to being in use.
 */
public final class ResourceBusyException extends MediaDrmException {
    public ResourceBusyException(String detailMessage) {
        super(detailMessage);
    }
}
+44 −3
Original line number Diff line number Diff line
@@ -49,9 +49,14 @@ enum {
    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
};

struct CryptoErrorCodes {
    jint cryptoErrorNoKey;
    jint cryptoErrorKeyExpired;
    jint cryptoErrorResourceBusy;
} gCryptoErrorCodes;

struct fields_t {
    jfieldID context;

    jfieldID cryptoInfoNumSubSamplesID;
    jfieldID cryptoInfoNumBytesOfClearDataID;
    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
@@ -342,6 +347,21 @@ static void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {

    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");

    /* translate OS errors to Java API CryptoException errorCodes */
    switch (err) {
        case ERROR_DRM_NO_LICENSE:
            err = gCryptoErrorCodes.cryptoErrorNoKey;
            break;
        case ERROR_DRM_LICENSE_EXPIRED:
            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
            break;
        case ERROR_DRM_RESOURCE_BUSY:
            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
            break;
        default:
            break;
    }

    jthrowable exception =
        (jthrowable)env->NewObject(clazz, constructID, err, msgObj);

@@ -350,9 +370,8 @@ static void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {

static jint throwExceptionAsNecessary(
        JNIEnv *env, status_t err, const char *msg = NULL) {
    if (err >= ERROR_DRM_WV_VENDOR_MIN && err <= ERROR_DRM_WV_VENDOR_MAX) {
    if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
        // We'll throw our custom MediaCodec.CryptoException

        throwCryptoException(env, err, msg);
        return 0;
    }
@@ -370,6 +389,12 @@ static jint throwExceptionAsNecessary(
        case INFO_OUTPUT_BUFFERS_CHANGED:
            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;

        case ERROR_DRM_NO_LICENSE:
        case ERROR_DRM_LICENSE_EXPIRED:
        case ERROR_DRM_RESOURCE_BUSY:
            throwCryptoException(env, err, msg);
            break;

        default:
        {
            jniThrowException(env, "java/lang/IllegalStateException", msg);
@@ -852,6 +877,22 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) {

    gFields.cryptoInfoModeID = env->GetFieldID(clazz, "mode", "I");
    CHECK(gFields.cryptoInfoModeID != NULL);

    clazz = env->FindClass("android/media/MediaCodec$CryptoException");
    CHECK(clazz != NULL);

    jfieldID field;
    field = env->GetStaticFieldID(clazz, "ERROR_NO_KEY", "I");
    CHECK(field != NULL);
    gCryptoErrorCodes.cryptoErrorNoKey = env->GetStaticIntField(clazz, field);

    field = env->GetStaticFieldID(clazz, "ERROR_KEY_EXPIRED", "I");
    CHECK(field != NULL);
    gCryptoErrorCodes.cryptoErrorKeyExpired = env->GetStaticIntField(clazz, field);

    field = env->GetStaticFieldID(clazz, "ERROR_RESOURCE_BUSY", "I");
    CHECK(field != NULL);
    gCryptoErrorCodes.cryptoErrorResourceBusy = env->GetStaticIntField(clazz, field);
}

static void android_media_MediaCodec_native_setup(
Loading