/* * Copyright (C) 2020 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.metrics; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.util.Objects; /** * Playback error event. */ public final class PlaybackErrorEvent extends Event implements Parcelable { /** Unknown error code. */ public static final int ERROR_UNKNOWN = 0; /** Error code for other errors */ public static final int ERROR_OTHER = 1; /** Error code for runtime errors */ public static final int ERROR_RUNTIME = 2; /** Error code for lack of network connectivity while trying to access a network resource */ public static final int ERROR_IO_NETWORK_UNAVAILABLE = 3; /** Error code for a failure while establishing a network connection */ public static final int ERROR_IO_NETWORK_CONNECTION_FAILED = 4; /** Error code for an HTTP server returning an unexpected HTTP response status code */ public static final int ERROR_IO_BAD_HTTP_STATUS = 5; /** Error code for failing to resolve a hostname */ public static final int ERROR_IO_DNS_FAILED = 6; /** * Error code for a network timeout, meaning the server is taking too long to fulfill * a request */ public static final int ERROR_IO_CONNECTION_TIMEOUT = 7; /** Error code for an existing network connection being unexpectedly closed */ public static final int ERROR_IO_CONNECTION_CLOSED = 8; /** Error code for other Input/Output errors */ public static final int ERROR_IO_OTHER = 9; /** Error code for a parsing error associated to a media manifest */ public static final int ERROR_PARSING_MANIFEST_MALFORMED = 10; /** Error code for a parsing error associated to a media container format bitstream */ public static final int ERROR_PARSING_CONTAINER_MALFORMED = 11; /** Error code for other media parsing errors */ public static final int ERROR_PARSING_OTHER = 12; /** Error code for a decoder initialization failure */ public static final int ERROR_DECODER_INIT_FAILED = 13; /** Error code for a failure while trying to decode media samples */ public static final int ERROR_DECODING_FAILED = 14; /** * Error code for trying to decode content whose format exceeds the capabilities of the device. */ public static final int ERROR_DECODING_FORMAT_EXCEEDS_CAPABILITIES = 15; /** Error code for other decoding errors */ public static final int ERROR_DECODING_OTHER = 16; /** Error code for an AudioTrack initialization failure */ public static final int ERROR_AUDIO_TRACK_INIT_FAILED = 17; /** Error code for an AudioTrack write operation failure */ public static final int ERROR_AUDIO_TRACK_WRITE_FAILED = 18; /** Error code for other AudioTrack errors */ public static final int ERROR_AUDIO_TRACK_OTHER = 19; /** Error code for an unidentified error in a remote controller or player */ public static final int ERROR_PLAYER_REMOTE = 20; /** * Error code for the loading position falling behind the sliding window of available live * content. */ public static final int ERROR_PLAYER_BEHIND_LIVE_WINDOW = 21; /** Error code for other player errors */ public static final int ERROR_PLAYER_OTHER = 22; /** Error code for a chosen DRM protection scheme not being supported by the device */ public static final int ERROR_DRM_SCHEME_UNSUPPORTED = 23; /** Error code for a failure while provisioning the device */ public static final int ERROR_DRM_PROVISIONING_FAILED = 24; /** Error code for a failure while trying to obtain a license */ public static final int ERROR_DRM_LICENSE_ACQUISITION_FAILED = 25; /** Error code an operation being disallowed by a license policy */ public static final int ERROR_DRM_DISALLOWED_OPERATION = 26; /** Error code for an error in the DRM system */ public static final int ERROR_DRM_SYSTEM_ERROR = 27; /** Error code for attempting to play incompatible DRM-protected content */ public static final int ERROR_DRM_CONTENT_ERROR = 28; /** Error code for the device having revoked DRM privileges */ public static final int ERROR_DRM_DEVICE_REVOKED = 29; /** Error code for other DRM errors */ public static final int ERROR_DRM_OTHER = 30; /** Error code for a non-existent file */ public static final int ERROR_IO_FILE_NOT_FOUND = 31; /** * Error code for lack of permission to perform an IO operation, for example, lack of permission * to access internet or external storage. */ public static final int ERROR_IO_NO_PERMISSION = 32; /** Error code for an unsupported feature in a media manifest */ public static final int ERROR_PARSING_MANIFEST_UNSUPPORTED = 33; /** * Error code for attempting to extract a file with an unsupported media container format, or an * unsupported media container feature */ public static final int ERROR_PARSING_CONTAINER_UNSUPPORTED = 34; /** Error code for trying to decode content whose format is not supported */ public static final int ERROR_DECODING_FORMAT_UNSUPPORTED = 35; private final @Nullable String mExceptionStack; private final int mErrorCode; private final int mSubErrorCode; private final long mTimeSinceCreatedMillis; /** @hide */ @IntDef(prefix = "ERROR_", value = { ERROR_UNKNOWN, ERROR_OTHER, ERROR_RUNTIME, ERROR_IO_NETWORK_UNAVAILABLE, ERROR_IO_NETWORK_CONNECTION_FAILED, ERROR_IO_BAD_HTTP_STATUS, ERROR_IO_DNS_FAILED, ERROR_IO_CONNECTION_TIMEOUT, ERROR_IO_CONNECTION_CLOSED, ERROR_IO_OTHER, ERROR_PARSING_MANIFEST_MALFORMED, ERROR_PARSING_CONTAINER_MALFORMED, ERROR_PARSING_OTHER, ERROR_DECODER_INIT_FAILED, ERROR_DECODING_FAILED, ERROR_DECODING_FORMAT_EXCEEDS_CAPABILITIES, ERROR_DECODING_OTHER, ERROR_AUDIO_TRACK_INIT_FAILED, ERROR_AUDIO_TRACK_WRITE_FAILED, ERROR_AUDIO_TRACK_OTHER, ERROR_PLAYER_REMOTE, ERROR_PLAYER_BEHIND_LIVE_WINDOW, ERROR_PLAYER_OTHER, ERROR_DRM_SCHEME_UNSUPPORTED, ERROR_DRM_PROVISIONING_FAILED, ERROR_DRM_LICENSE_ACQUISITION_FAILED, ERROR_DRM_DISALLOWED_OPERATION, ERROR_DRM_SYSTEM_ERROR, ERROR_DRM_CONTENT_ERROR, ERROR_DRM_DEVICE_REVOKED, ERROR_DRM_OTHER, ERROR_IO_FILE_NOT_FOUND, ERROR_IO_NO_PERMISSION, ERROR_PARSING_MANIFEST_UNSUPPORTED, ERROR_PARSING_CONTAINER_UNSUPPORTED, ERROR_DECODING_FORMAT_UNSUPPORTED, }) @Retention(java.lang.annotation.RetentionPolicy.SOURCE) public @interface ErrorCode {} /** * Creates a new PlaybackErrorEvent. */ private PlaybackErrorEvent( @Nullable String exceptionStack, int errorCode, int subErrorCode, long timeSinceCreatedMillis, @NonNull Bundle extras) { this.mExceptionStack = exceptionStack; this.mErrorCode = errorCode; this.mSubErrorCode = subErrorCode; this.mTimeSinceCreatedMillis = timeSinceCreatedMillis; this.mMetricsBundle = extras.deepCopy(); } /** @hide */ @Nullable public String getExceptionStack() { return mExceptionStack; } /** * Gets error code. */ @ErrorCode public int getErrorCode() { return mErrorCode; } /** * Gets sub error code. */ @IntRange(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE) public int getSubErrorCode() { return mSubErrorCode; } /** * Gets the timestamp since creation of the playback session in milliseconds. * @return the timestamp since the playback is created, or -1 if unknown. * @see LogSessionId * @see PlaybackSession */ @Override @IntRange(from = -1) public long getTimeSinceCreatedMillis() { return mTimeSinceCreatedMillis; } /** * Gets metrics-related information that is not supported by dedicated methods. *
It is intended to be used for backwards compatibility by the metrics infrastructure.
*/
@Override
@NonNull
public Bundle getMetricsBundle() {
return mMetricsBundle;
}
@Override
public String toString() {
return "PlaybackErrorEvent { "
+ "exceptionStack = " + mExceptionStack + ", "
+ "errorCode = " + mErrorCode + ", "
+ "subErrorCode = " + mSubErrorCode + ", "
+ "timeSinceCreatedMillis = " + mTimeSinceCreatedMillis
+ " }";
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlaybackErrorEvent that = (PlaybackErrorEvent) o;
return Objects.equals(mExceptionStack, that.mExceptionStack)
&& mErrorCode == that.mErrorCode
&& mSubErrorCode == that.mSubErrorCode
&& mTimeSinceCreatedMillis == that.mTimeSinceCreatedMillis;
}
@Override
public int hashCode() {
return Objects.hash(mExceptionStack, mErrorCode, mSubErrorCode,
mTimeSinceCreatedMillis);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
byte flg = 0;
if (mExceptionStack != null) flg |= 0x1;
dest.writeByte(flg);
if (mExceptionStack != null) dest.writeString(mExceptionStack);
dest.writeInt(mErrorCode);
dest.writeInt(mSubErrorCode);
dest.writeLong(mTimeSinceCreatedMillis);
dest.writeBundle(mMetricsBundle);
}
@Override
public int describeContents() {
return 0;
}
private PlaybackErrorEvent(@NonNull Parcel in) {
byte flg = in.readByte();
String exceptionStack = (flg & 0x1) == 0 ? null : in.readString();
int errorCode = in.readInt();
int subErrorCode = in.readInt();
long timeSinceCreatedMillis = in.readLong();
Bundle extras = in.readBundle();
this.mExceptionStack = exceptionStack;
this.mErrorCode = errorCode;
this.mSubErrorCode = subErrorCode;
this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
this.mMetricsBundle = extras;
}
public static final @NonNull Parcelable.Creator It is intended to be used for backwards compatibility by the
* metrics infrastructure.
*/
public @NonNull Builder setMetricsBundle(@NonNull Bundle metricsBundle) {
mMetricsBundle = metricsBundle;
return this;
}
/** Builds the instance. */
public @NonNull PlaybackErrorEvent build() {
String stack;
if (mException.getStackTrace() != null && mException.getStackTrace().length > 0) {
// TODO: a better definition of the stack trace
stack = mException.getStackTrace()[0].toString();
} else {
stack = null;
}
PlaybackErrorEvent o = new PlaybackErrorEvent(
stack,
mErrorCode,
mSubErrorCode,
mTimeSinceCreatedMillis,
mMetricsBundle);
return o;
}
}
}