diff options
| -rw-r--r-- | core/api/current.txt | 63 | ||||
| -rw-r--r-- | media/java/android/media/MediaCodec.java | 61 | ||||
| -rw-r--r-- | media/java/android/media/MediaDrm.java | 404 |
3 files changed, 492 insertions, 36 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 52f2335127a4..742004b24541 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -21118,15 +21118,15 @@ package android.media { public static final class MediaCodec.CryptoException extends java.lang.RuntimeException { ctor public MediaCodec.CryptoException(int, @Nullable String); method public int getErrorCode(); - field public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8 - field public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4 - field public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7 - field public static final int ERROR_KEY_EXPIRED = 2; // 0x2 - field public static final int ERROR_LOST_STATE = 9; // 0x9 - field public static final int ERROR_NO_KEY = 1; // 0x1 - field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3 - field public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5 - field public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6 + field @Deprecated public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8 + field @Deprecated public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4 + field @Deprecated public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7 + field @Deprecated public static final int ERROR_KEY_EXPIRED = 2; // 0x2 + field @Deprecated public static final int ERROR_LOST_STATE = 9; // 0x9 + field @Deprecated public static final int ERROR_NO_KEY = 1; // 0x1 + field @Deprecated public static final int ERROR_RESOURCE_BUSY = 3; // 0x3 + field @Deprecated public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5 + field @Deprecated public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6 } public static final class MediaCodec.CryptoInfo { @@ -21745,6 +21745,42 @@ package android.media { method public boolean verify(@NonNull byte[], @NonNull byte[], @NonNull byte[]); } + public static final class MediaDrm.ErrorCodes { + field public static final int ERROR_CERTIFICATE_MALFORMED = 10; // 0xa + field public static final int ERROR_CERTIFICATE_MISSING = 11; // 0xb + field public static final int ERROR_CRYPTO_LIBRARY = 12; // 0xc + field public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8 + field public static final int ERROR_GENERIC_OEM = 13; // 0xd + field public static final int ERROR_GENERIC_PLUGIN = 14; // 0xe + field public static final int ERROR_INIT_DATA = 15; // 0xf + field public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4 + field public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7 + field public static final int ERROR_KEY_EXPIRED = 2; // 0x2 + field public static final int ERROR_KEY_NOT_LOADED = 16; // 0x10 + field public static final int ERROR_LICENSE_PARSE = 17; // 0x11 + field public static final int ERROR_LICENSE_POLICY = 18; // 0x12 + field public static final int ERROR_LICENSE_RELEASE = 19; // 0x13 + field public static final int ERROR_LICENSE_REQUEST_REJECTED = 20; // 0x14 + field public static final int ERROR_LICENSE_RESTORE = 21; // 0x15 + field public static final int ERROR_LICENSE_STATE = 22; // 0x16 + field public static final int ERROR_LOST_STATE = 9; // 0x9 + field public static final int ERROR_MEDIA_FRAMEWORK = 23; // 0x17 + field public static final int ERROR_NO_KEY = 1; // 0x1 + field public static final int ERROR_PROVISIONING_CERTIFICATE = 24; // 0x18 + field public static final int ERROR_PROVISIONING_CONFIG = 25; // 0x19 + field public static final int ERROR_PROVISIONING_PARSE = 26; // 0x1a + field public static final int ERROR_PROVISIONING_RETRY = 27; // 0x1b + field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3 + field public static final int ERROR_RESOURCE_CONTENTION = 28; // 0x1c + field public static final int ERROR_SECURE_STOP_RELEASE = 29; // 0x1d + field public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5 + field public static final int ERROR_STORAGE_READ = 30; // 0x1e + field public static final int ERROR_STORAGE_WRITE = 31; // 0x1f + field public static final int ERROR_UNKNOWN = 0; // 0x0 + field public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6 + field public static final int ERROR_ZERO_SUBSAMPLES = 32; // 0x20 + } + @Deprecated @IntDef({android.media.MediaDrm.HDCP_LEVEL_UNKNOWN, android.media.MediaDrm.HDCP_NONE, android.media.MediaDrm.HDCP_V1, android.media.MediaDrm.HDCP_V2, android.media.MediaDrm.HDCP_V2_1, android.media.MediaDrm.HDCP_V2_2, android.media.MediaDrm.HDCP_V2_3, android.media.MediaDrm.HDCP_NO_DIGITAL_OUTPUT}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MediaDrm.HdcpLevel { } @@ -21778,6 +21814,8 @@ package android.media { public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException { method @NonNull public String getDiagnosticInfo(); + method public int getErrorCode(); + method public boolean isTransient(); } public static final class MediaDrm.MetricsConstants { @@ -21844,9 +21882,10 @@ package android.media { public static final class MediaDrm.SessionException extends java.lang.RuntimeException { ctor public MediaDrm.SessionException(int, @Nullable String); - method public int getErrorCode(); - field public static final int ERROR_RESOURCE_CONTENTION = 1; // 0x1 - field public static final int ERROR_UNKNOWN = 0; // 0x0 + method @Deprecated public int getErrorCode(); + method public boolean isTransient(); + field @Deprecated public static final int ERROR_RESOURCE_CONTENTION = 1; // 0x1 + field @Deprecated public static final int ERROR_UNKNOWN = 0; // 0x0 } public class MediaDrmException extends java.lang.Exception { diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 607c8f11e01a..cf31e4141a6d 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -2414,37 +2414,44 @@ final public class MediaCodec implements PlaybackComponent { * This indicates that the requested key was not found when trying to * perform a decrypt operation. The operation can be retried after adding * the correct decryption key. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_NO_KEY}. */ - public static final int ERROR_NO_KEY = 1; + public static final int ERROR_NO_KEY = MediaDrm.ErrorCodes.ERROR_NO_KEY; /** * This indicates that the key used for decryption is no longer * valid due to license term expiration. The operation can be retried * after updating the expired keys. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_KEY_EXPIRED}. */ - public static final int ERROR_KEY_EXPIRED = 2; + public static final int ERROR_KEY_EXPIRED = MediaDrm.ErrorCodes.ERROR_KEY_EXPIRED; /** * This indicates that a required crypto resource was not able to be * allocated while attempting the requested operation. The operation * can be retried if the app is able to release resources. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_RESOURCE_BUSY} */ - public static final int ERROR_RESOURCE_BUSY = 3; + public static final int ERROR_RESOURCE_BUSY = MediaDrm.ErrorCodes.ERROR_RESOURCE_BUSY; /** * This indicates that the output protection levels supported by the * device are not sufficient to meet the requirements set by the * content owner in the license policy. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_INSUFFICIENT_OUTPUT_PROTECTION} */ - public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; + public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = + MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION; /** * This indicates that decryption was attempted on a session that is * not opened, which could be due to a failure to open the session, * closing the session prematurely, or the session being reclaimed * by the resource manager. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_SESSION_NOT_OPENED} */ - public static final int ERROR_SESSION_NOT_OPENED = 5; + public static final int ERROR_SESSION_NOT_OPENED = + MediaDrm.ErrorCodes.ERROR_SESSION_NOT_OPENED; /** * This indicates that an operation was attempted that could not be @@ -2453,23 +2460,28 @@ final public class MediaCodec implements PlaybackComponent { * device security features that aren't supported by the device, * or due to an internal error in the crypto system that prevents * the specified security policy from being met. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_UNSUPPORTED_OPERATION} */ - public static final int ERROR_UNSUPPORTED_OPERATION = 6; + public static final int ERROR_UNSUPPORTED_OPERATION = + MediaDrm.ErrorCodes.ERROR_UNSUPPORTED_OPERATION; /** * This indicates that the security level of the device is not * sufficient to meet the requirements set by the content owner * in the license policy. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_INSUFFICIENT_SECURITY} */ - public static final int ERROR_INSUFFICIENT_SECURITY = 7; + public static final int ERROR_INSUFFICIENT_SECURITY = + MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_SECURITY; /** * This indicates that the video frame being decrypted exceeds * the size of the device's protected output buffers. When * encountering this error the app should try playing content * of a lower resolution. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_FRAME_TOO_LARGE} */ - public static final int ERROR_FRAME_TOO_LARGE = 8; + public static final int ERROR_FRAME_TOO_LARGE = MediaDrm.ErrorCodes.ERROR_FRAME_TOO_LARGE; /** * This error indicates that session state has been @@ -2477,26 +2489,37 @@ final public class MediaCodec implements PlaybackComponent { * of retaining crypto session state across device * suspend/resume. The session must be closed and a new * session opened to resume operation. + * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_LOST_STATE} */ - public static final int ERROR_LOST_STATE = 9; + public static final int ERROR_LOST_STATE = MediaDrm.ErrorCodes.ERROR_LOST_STATE; /** @hide */ @IntDef({ - ERROR_NO_KEY, - ERROR_KEY_EXPIRED, - ERROR_RESOURCE_BUSY, - ERROR_INSUFFICIENT_OUTPUT_PROTECTION, - ERROR_SESSION_NOT_OPENED, - ERROR_UNSUPPORTED_OPERATION, - ERROR_INSUFFICIENT_SECURITY, - ERROR_FRAME_TOO_LARGE, - ERROR_LOST_STATE + MediaDrm.ErrorCodes.ERROR_NO_KEY, + MediaDrm.ErrorCodes.ERROR_KEY_EXPIRED, + MediaDrm.ErrorCodes.ERROR_RESOURCE_BUSY, + MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION, + MediaDrm.ErrorCodes.ERROR_SESSION_NOT_OPENED, + MediaDrm.ErrorCodes.ERROR_UNSUPPORTED_OPERATION, + MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_SECURITY, + MediaDrm.ErrorCodes.ERROR_FRAME_TOO_LARGE, + MediaDrm.ErrorCodes.ERROR_LOST_STATE, + MediaDrm.ErrorCodes.ERROR_GENERIC_OEM, + MediaDrm.ErrorCodes.ERROR_GENERIC_PLUGIN, + MediaDrm.ErrorCodes.ERROR_LICENSE_PARSE, + MediaDrm.ErrorCodes.ERROR_MEDIA_FRAMEWORK, + MediaDrm.ErrorCodes.ERROR_ZERO_SUBSAMPLES }) @Retention(RetentionPolicy.SOURCE) public @interface CryptoErrorCode {} /** - * Retrieve the error code associated with a CryptoException + * Returns error code associated with this {@link CryptoException}. + * <p> + * Please refer to {@link MediaDrm.ErrorCodes} for the general error + * handling strategy and details about each possible return value. + * + * @return an error code defined in {@link MediaDrm.ErrorCodes}. */ @CryptoErrorCode public int getErrorCode() { diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java index ea5fe39ccc08..f7467a636024 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -297,9 +297,363 @@ public final class MediaDrm implements AutoCloseable { } /** - * Thrown when an unrecoverable failure occurs during a MediaDrm operation. - * Extends java.lang.IllegalStateException with the addition of an error + * Error codes that may be returned from {@link + * MediaDrmStateException#getErrorCode()} and {@link + * MediaCodec.CryptoException#getErrorCode()} + * <p> + * The description of each error code includes steps that may be taken to + * resolve the error condition. For some errors however, a recovery action + * cannot be predetermined. The description of those codes refers to a + * general strategy for handling the error condition programmatically, which + * is to try the following in listed order until successful: + * <ol> + * <li> retry the operation </li> + * <li> if the operation is related to a session, {@link + * #closeSession(byte[]) close} the session, {@link #openSession() open} a + * new session, and retry the operation </li> + * <li> {@link #close() close} the {@link MediaDrm} instance and any other + * related components such as the {@link MediaCodec codec} and retry + * playback, or </li> + * <li> try using a different configuration of the {@link MediaDrm} plugin, + * such as a different {@link #openSession(int) security level}. </li> + * </ol> + * <p> + * If the problem still persists after all the aforementioned steps, please + * report the failure to the {@link MediaDrm} plugin vendor along with the + * {@link LogMessage log messages} returned by {@link + * MediaDrm#getLogMessages()}, and a bugreport if possible. + */ + public final static class ErrorCodes { + private ErrorCodes() {} + + /** + * ERROR_UNKNOWN is used where no other defined error code is applicable + * to the current failure. + * <p> + * Please see the general error handling strategy for unexpected errors + * described in {@link ErrorCodes}. + */ + public static final int ERROR_UNKNOWN = 0; + + /** + * The requested key was not found when trying to perform a decrypt + * operation. + * <p> + * The operation can be retried after adding the correct decryption key. + */ + public static final int ERROR_NO_KEY = 1; + + /** + * The key used for decryption is no longer valid due to license term + * expiration. + * <p> + * The operation can be retried after updating the expired keys. + */ + public static final int ERROR_KEY_EXPIRED = 2; + + /** + * A required crypto resource was not able to be allocated while + * attempting the requested operation. + * <p> + * The operation can be retried if the app is able to release resources. + */ + public static final int ERROR_RESOURCE_BUSY = 3; + + /** + * The output protection levels supported by the device are not + * sufficient to meet the requirements set by the content owner in the + * license policy. + */ + public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; + + /** + * Decryption was attempted on a session that is not opened, which could + * be due to a failure to open the session, closing the session + * prematurely, the session being reclaimed by the resource manager, or + * a non-existent session id. + */ + public static final int ERROR_SESSION_NOT_OPENED = 5; + + /** + * An operation was attempted that could not be supported by the crypto + * system of the device in its current configuration. + * <p> + * This may occur when the license policy requires device security + * features that aren't supported by the device, or due to an internal + * error in the crypto system that prevents the specified security + * policy from being met. + */ + public static final int ERROR_UNSUPPORTED_OPERATION = 6; + + /** + * The security level of the device is not sufficient to meet the + * requirements set by the content owner in the license policy. + */ + public static final int ERROR_INSUFFICIENT_SECURITY = 7; + + /** + * The video frame being decrypted exceeds the size of the device's + * protected output buffers. + * <p> + * When encountering this error the app should try playing content + * of a lower resolution or skipping the problematic frame. + */ + public static final int ERROR_FRAME_TOO_LARGE = 8; + + /** + * The session state has been invalidated. This can occur on devices + * that are not capable of retaining crypto session state across device + * suspend/resume. + * <p> + * The session must be closed and a new session opened to resume + * operation. + */ + public static final int ERROR_LOST_STATE = 9; + + /** + * Certificate is malformed or is of the wrong type. + * <p> + * Ensure the certificate provided by the app or returned from the + * license server is valid. Check with the {@link MediaDrm} plugin + * vendor for the expected certificate format. + */ + public static final int ERROR_CERTIFICATE_MALFORMED = 10; + + /** + * Certificate has not been set. + * <p> + * Ensure the certificate has been provided by the app. Check with the + * {@link MediaDrm} plugin vendor for the expected method to provide + * {@link MediaDrm} a certificate. + */ + public static final int ERROR_CERTIFICATE_MISSING = 11; + + /** + * An error happened within the crypto library used by the drm plugin. + */ + public static final int ERROR_CRYPTO_LIBRARY = 12; + + /** + * Unexpected error reported by the device OEM subsystem. + * <p> + * Please see the general error handling strategy for unexpected errors + * described in {@link ErrorCodes}. + */ + public static final int ERROR_GENERIC_OEM = 13; + + /** + * Unexpected internal failure in {@link MediaDrm}/{@link MediaCrypto}. + * <p> + * Please see the general error handling strategy for unexpected errors + * described in {@link ErrorCodes}. + */ + public static final int ERROR_GENERIC_PLUGIN = 14; + + /** + * The init data parameter passed to {@link MediaDrm#getKeyRequest} is + * empty or invalid. + * <p> + * Init data is typically obtained from {@link + * MediaExtractor#getPsshInfo()} or {@link + * MediaExtractor#getDrmInitData()}. Check with the {@link MediaDrm} + * plugin vendor for the expected init data format. + */ + public static final int ERROR_INIT_DATA = 15; + + /** + * Either the key was not loaded from the license before attempting the + * operation, or the key ID parameter provided by the app is incorrect. + * <p> + * Ensure the proper keys are in the license, and check the key ID + * parameter provided by the app is correct. Check with the {@link + * MediaDrm} plugin vendor for the expected license format. + */ + public static final int ERROR_KEY_NOT_LOADED = 16; + + /** + * The license response was empty, fields are missing or otherwise + * unable to be parsed or decrypted. + * <p> + * Check for mistakes such as empty or overwritten buffers. Otherwise, + * check with the {@link MediaDrm} plugin vendor for the expected + * license format. + */ + public static final int ERROR_LICENSE_PARSE = 17; + + /** + * The operation (e.g. to renew or persist a license) is prohibited by + * the license policy. + * <p> + * Check the license policy configuration on the license server. + */ + public static final int ERROR_LICENSE_POLICY = 18; + + /** + * Failed to generate a release request because a field in the offline + * license is empty or malformed. + * <p> + * The license can't be released on the server, but the app may remove + * the offline license explicitly using {@link + * MediaDrm#removeOfflineLicense}. + */ + public static final int ERROR_LICENSE_RELEASE = 19; + + /** + * The license server detected an error in the license request. + * <p> + * Check for errors on the license server. + */ + public static final int ERROR_LICENSE_REQUEST_REJECTED = 20; + + /** + * Failed to restore an offline license because a field in the offline + * license is empty or malformed. + * <p> + * Try requesting the license again if the device is online. + */ + public static final int ERROR_LICENSE_RESTORE = 21; + + /** + * Offline license is in an invalid state for the attempted operation. + * <p> + * Check the sequence of API calls made that can affect offline license + * state. For example, this could happen when the app attempts to + * restore a license after it has been released. + */ + public static final int ERROR_LICENSE_STATE = 22; + + /** + * Failure in the media framework. + * <p> + * Try releasing media resources (e.g. {@link MediaCodec}, {@link + * MediaDrm}), and restarting playback. + */ + public static final int ERROR_MEDIA_FRAMEWORK = 23; + + /** + * Error loading the provisioned certificate. + * <p> + * Re-provisioning may resolve the problem; check with the {@link + * MediaDrm} plugin vendor for re-provisioning instructions. Otherwise, + * using a different security level may resolve the issue. + */ + public static final int ERROR_PROVISIONING_CERTIFICATE = 24; + + /** + * Required steps were not performed before provisioning was attempted. + * <p> + * Ask the {@link MediaDrm} plugin vendor for situations where this + * error may occur. + */ + public static final int ERROR_PROVISIONING_CONFIG = 25; + + /** + * The provisioning response was empty, fields are missing or otherwise + * unable to be parsed. + * <p> + * Check for mistakes such as empty or overwritten buffers. Otherwise, + * check with the {@link MediaDrm} plugin vendor for the expected + * provisioning response format. + */ + public static final int ERROR_PROVISIONING_PARSE = 26; + + /** + * Provisioning failed in a way that is likely to succeed on a + * subsequent attempt. + * <p> + * The app should retry the operation. + */ + public static final int ERROR_PROVISIONING_RETRY = 27; + + /** + * This indicates that apps using MediaDrm sessions are + * temporarily exceeding the capacity of available crypto + * resources. + * <p> + * The app should retry the operation later. + */ + public static final int ERROR_RESOURCE_CONTENTION = 28; + + /** + * Failed to generate a secure stop request because a field in the + * stored license is empty or malformed. + * <p> + * The secure stop can't be released on the server, but the app may + * remove it explicitly using {@link MediaDrm#removeSecureStop}. + */ + public static final int ERROR_SECURE_STOP_RELEASE = 29; + + /** + * The plugin was unable to read data from the filesystem. + * <p> + * Please see the general error handling strategy for unexpected errors + * described in {@link ErrorCodes}. + */ + public static final int ERROR_STORAGE_READ = 30; + + /** + * The plugin was unable to write data to the filesystem. + * <p> + * Please see the general error handling strategy for unexpected errors + * described in {@link ErrorCodes}. + */ + public static final int ERROR_STORAGE_WRITE = 31; + + /** + * {@link MediaCodec#queueSecureInputBuffer} called with 0 subsamples. + * <p> + * Check the {@link MediaCodec.CryptoInfo} object passed to {@link + * MediaCodec#queueSecureInputBuffer}. + */ + public static final int ERROR_ZERO_SUBSAMPLES = 32; + + } + + /** @hide */ + @IntDef({ + ErrorCodes.ERROR_NO_KEY, + ErrorCodes.ERROR_KEY_EXPIRED, + ErrorCodes.ERROR_RESOURCE_BUSY, + ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION, + ErrorCodes.ERROR_SESSION_NOT_OPENED, + ErrorCodes.ERROR_UNSUPPORTED_OPERATION, + ErrorCodes.ERROR_INSUFFICIENT_SECURITY, + ErrorCodes.ERROR_FRAME_TOO_LARGE, + ErrorCodes.ERROR_LOST_STATE, + ErrorCodes.ERROR_CERTIFICATE_MALFORMED, + ErrorCodes.ERROR_CERTIFICATE_MISSING, + ErrorCodes.ERROR_CRYPTO_LIBRARY, + ErrorCodes.ERROR_GENERIC_OEM, + ErrorCodes.ERROR_GENERIC_PLUGIN, + ErrorCodes.ERROR_INIT_DATA, + ErrorCodes.ERROR_KEY_NOT_LOADED, + ErrorCodes.ERROR_LICENSE_PARSE, + ErrorCodes.ERROR_LICENSE_POLICY, + ErrorCodes.ERROR_LICENSE_RELEASE, + ErrorCodes.ERROR_LICENSE_REQUEST_REJECTED, + ErrorCodes.ERROR_LICENSE_RESTORE, + ErrorCodes.ERROR_LICENSE_STATE, + ErrorCodes.ERROR_MEDIA_FRAMEWORK, + ErrorCodes.ERROR_PROVISIONING_CERTIFICATE, + ErrorCodes.ERROR_PROVISIONING_CONFIG, + ErrorCodes.ERROR_PROVISIONING_PARSE, + ErrorCodes.ERROR_PROVISIONING_RETRY, + ErrorCodes.ERROR_SECURE_STOP_RELEASE, + ErrorCodes.ERROR_STORAGE_READ, + ErrorCodes.ERROR_STORAGE_WRITE, + ErrorCodes.ERROR_ZERO_SUBSAMPLES + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MediaDrmErrorCode {} + + /** + * Thrown when a general failure occurs during a MediaDrm operation. + * Extends {@link IllegalStateException} with the addition of an error * code that may be useful in diagnosing the failure. + * <p> + * Please refer to {@link ErrorCodes} for the general error handling + * strategy and details about each possible return value from {@link + * MediaDrmStateException#getErrorCode()}. */ public static final class MediaDrmStateException extends java.lang.IllegalStateException { private final int mErrorCode; @@ -320,15 +674,30 @@ public final class MediaDrm implements AutoCloseable { } /** - * Retrieve the associated error code + * Returns error code associated with this {@link + * MediaDrmStateException}. + * <p> + * Please refer to {@link ErrorCodes} for the general error handling + * strategy and details about each possible return value. * - * @hide + * @return an error code defined in {@link MediaDrm.ErrorCodes}. */ + @MediaDrmErrorCode public int getErrorCode() { return mErrorCode; } /** + * Returns true if the {@link MediaDrmStateException} is a transient + * issue, perhaps due to resource constraints, and that the operation + * (e.g. provisioning) may succeed on a subsequent attempt. + */ + public boolean isTransient() { + return mErrorCode == ErrorCodes.ERROR_PROVISIONING_RETRY + || mErrorCode == ErrorCodes.ERROR_RESOURCE_CONTENTION; + } + + /** * Retrieve a developer-readable diagnostic information string * associated with the exception. Do not show this to end-users, * since this string will not be localized or generally comprehensible @@ -341,7 +710,13 @@ public final class MediaDrm implements AutoCloseable { } /** - * Thrown when an error occurs in any method that has a session context. + * {@link SessionException} is a misnomer because it may occur in methods + * <b>without</b> a session context. + * <p> + * A {@link SessionException} is most likely to be thrown when an operation + * failed in a way that is likely to succeed on a subsequent attempt; call + * {@link #isTransient()} to determine whether the app should retry the + * failing operation. */ public static final class SessionException extends RuntimeException { public SessionException(int errorCode, @Nullable String detailMessage) { @@ -351,6 +726,7 @@ public final class MediaDrm implements AutoCloseable { /** * The SessionException has an unknown error code. + * @deprecated Unused. */ public static final int ERROR_UNKNOWN = 0; @@ -358,6 +734,10 @@ public final class MediaDrm implements AutoCloseable { * This indicates that apps using MediaDrm sessions are * temporarily exceeding the capacity of available crypto * resources. The app should retry the operation later. + * + * @deprecated Please use {@link #isTransient()} instead of comparing + * the return value of {@link #getErrorCode()} against + * {@link SessionException#ERROR_RESOURCE_CONTENTION}. */ public static final int ERROR_RESOURCE_CONTENTION = 1; @@ -370,12 +750,26 @@ public final class MediaDrm implements AutoCloseable { /** * Retrieve the error code associated with the SessionException + * + * @deprecated Please use {@link #isTransient()} instead of comparing + * the return value of {@link #getErrorCode()} against + * {@link SessionException#ERROR_RESOURCE_CONTENTION}. */ @SessionErrorCode public int getErrorCode() { return mErrorCode; } + /** + * Returns true if the {@link SessionException} is a transient + * issue, perhaps due to resource constraints, and that the operation + * (e.g. provisioning, generating requests) may succeed on a subsequent + * attempt. + */ + public boolean isTransient() { + return mErrorCode == ERROR_RESOURCE_CONTENTION; + } + private final int mErrorCode; } |