• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.media.metrics;
18 
19 import android.annotation.IntDef;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SuppressLint;
24 import android.os.Bundle;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import java.lang.annotation.Retention;
29 import java.util.Objects;
30 
31 /**
32  * Playback error event.
33  */
34 public final class PlaybackErrorEvent extends Event implements Parcelable {
35     /** Unknown error code. */
36     public static final int ERROR_UNKNOWN = 0;
37     /** Error code for other errors */
38     public static final int ERROR_OTHER = 1;
39     /** Error code for runtime errors */
40     public static final int ERROR_RUNTIME = 2;
41 
42     /** Error code for lack of network connectivity while trying to access a network resource */
43     public static final int ERROR_IO_NETWORK_UNAVAILABLE = 3;
44     /** Error code for a failure while establishing a network connection */
45     public static final int ERROR_IO_NETWORK_CONNECTION_FAILED = 4;
46     /** Error code for an HTTP server returning an unexpected HTTP response status code */
47     public static final int ERROR_IO_BAD_HTTP_STATUS = 5;
48     /** Error code for failing to resolve a hostname */
49     public static final int ERROR_IO_DNS_FAILED = 6;
50     /**
51      * Error code for a network timeout, meaning the server is taking too long to fulfill
52      * a request
53      */
54     public static final int ERROR_IO_CONNECTION_TIMEOUT = 7;
55     /** Error code for an existing network connection being unexpectedly closed */
56     public static final int ERROR_IO_CONNECTION_CLOSED = 8;
57     /** Error code for other Input/Output errors */
58     public static final int ERROR_IO_OTHER = 9;
59 
60     /** Error code for a parsing error associated to a media manifest */
61     public static final int ERROR_PARSING_MANIFEST_MALFORMED = 10;
62     /** Error code for a parsing error associated to a media container format bitstream */
63     public static final int ERROR_PARSING_CONTAINER_MALFORMED = 11;
64     /** Error code for other media parsing errors */
65     public static final int ERROR_PARSING_OTHER = 12;
66 
67     /** Error code for a decoder initialization failure */
68     public static final int ERROR_DECODER_INIT_FAILED = 13;
69     /** Error code for a failure while trying to decode media samples */
70     public static final int ERROR_DECODING_FAILED = 14;
71     /**
72      * Error code for trying to decode content whose format exceeds the capabilities of the device.
73      */
74     public static final int ERROR_DECODING_FORMAT_EXCEEDS_CAPABILITIES = 15;
75     /** Error code for other decoding errors */
76     public static final int ERROR_DECODING_OTHER = 16;
77 
78     /** Error code for an AudioTrack initialization failure */
79     public static final int ERROR_AUDIO_TRACK_INIT_FAILED = 17;
80     /** Error code for an AudioTrack write operation failure */
81     public static final int ERROR_AUDIO_TRACK_WRITE_FAILED = 18;
82     /** Error code for other AudioTrack errors */
83     public static final int ERROR_AUDIO_TRACK_OTHER = 19;
84 
85     /** Error code for an unidentified error in a remote controller or player */
86     public static final int ERROR_PLAYER_REMOTE = 20;
87     /**
88      * Error code for the loading position falling behind the sliding window of available live
89      * content.
90      */
91     public static final int ERROR_PLAYER_BEHIND_LIVE_WINDOW = 21;
92     /** Error code for other player errors */
93     public static final int ERROR_PLAYER_OTHER = 22;
94 
95     /** Error code for a chosen DRM protection scheme not being supported by the device */
96     public static final int ERROR_DRM_SCHEME_UNSUPPORTED = 23;
97     /** Error code for a failure while provisioning the device */
98     public static final int ERROR_DRM_PROVISIONING_FAILED = 24;
99     /** Error code for a failure while trying to obtain a license */
100     public static final int ERROR_DRM_LICENSE_ACQUISITION_FAILED = 25;
101     /** Error code an operation being disallowed by a license policy */
102     public static final int ERROR_DRM_DISALLOWED_OPERATION = 26;
103     /** Error code for an error in the DRM system */
104     public static final int ERROR_DRM_SYSTEM_ERROR = 27;
105     /** Error code for attempting to play incompatible DRM-protected content */
106     public static final int ERROR_DRM_CONTENT_ERROR = 28;
107     /** Error code for the device having revoked DRM privileges */
108     public static final int ERROR_DRM_DEVICE_REVOKED = 29;
109     /** Error code for other DRM errors */
110     public static final int ERROR_DRM_OTHER = 30;
111 
112     /** Error code for a non-existent file */
113     public static final int ERROR_IO_FILE_NOT_FOUND = 31;
114     /**
115      * Error code for lack of permission to perform an IO operation, for example, lack of permission
116      * to access internet or external storage.
117      */
118     public static final int ERROR_IO_NO_PERMISSION = 32;
119 
120     /** Error code for an unsupported feature in a media manifest */
121     public static final int ERROR_PARSING_MANIFEST_UNSUPPORTED = 33;
122     /**
123      * Error code for attempting to extract a file with an unsupported media container format, or an
124      * unsupported media container feature
125      */
126     public static final int ERROR_PARSING_CONTAINER_UNSUPPORTED = 34;
127 
128     /** Error code for trying to decode content whose format is not supported */
129     public static final int ERROR_DECODING_FORMAT_UNSUPPORTED = 35;
130 
131 
132     private final @Nullable String mExceptionStack;
133     private final int mErrorCode;
134     private final int mSubErrorCode;
135     private final long mTimeSinceCreatedMillis;
136 
137 
138     /** @hide */
139     @IntDef(prefix = "ERROR_", value = {
140         ERROR_UNKNOWN,
141         ERROR_OTHER,
142         ERROR_RUNTIME,
143         ERROR_IO_NETWORK_UNAVAILABLE,
144         ERROR_IO_NETWORK_CONNECTION_FAILED,
145         ERROR_IO_BAD_HTTP_STATUS,
146         ERROR_IO_DNS_FAILED,
147         ERROR_IO_CONNECTION_TIMEOUT,
148         ERROR_IO_CONNECTION_CLOSED,
149         ERROR_IO_OTHER,
150         ERROR_PARSING_MANIFEST_MALFORMED,
151         ERROR_PARSING_CONTAINER_MALFORMED,
152         ERROR_PARSING_OTHER,
153         ERROR_DECODER_INIT_FAILED,
154         ERROR_DECODING_FAILED,
155         ERROR_DECODING_FORMAT_EXCEEDS_CAPABILITIES,
156         ERROR_DECODING_OTHER,
157         ERROR_AUDIO_TRACK_INIT_FAILED,
158         ERROR_AUDIO_TRACK_WRITE_FAILED,
159         ERROR_AUDIO_TRACK_OTHER,
160         ERROR_PLAYER_REMOTE,
161         ERROR_PLAYER_BEHIND_LIVE_WINDOW,
162         ERROR_PLAYER_OTHER,
163         ERROR_DRM_SCHEME_UNSUPPORTED,
164         ERROR_DRM_PROVISIONING_FAILED,
165         ERROR_DRM_LICENSE_ACQUISITION_FAILED,
166         ERROR_DRM_DISALLOWED_OPERATION,
167         ERROR_DRM_SYSTEM_ERROR,
168         ERROR_DRM_CONTENT_ERROR,
169         ERROR_DRM_DEVICE_REVOKED,
170         ERROR_DRM_OTHER,
171         ERROR_IO_FILE_NOT_FOUND,
172         ERROR_IO_NO_PERMISSION,
173         ERROR_PARSING_MANIFEST_UNSUPPORTED,
174         ERROR_PARSING_CONTAINER_UNSUPPORTED,
175         ERROR_DECODING_FORMAT_UNSUPPORTED,
176     })
177     @Retention(java.lang.annotation.RetentionPolicy.SOURCE)
178     public @interface ErrorCode {}
179 
180     /**
181      * Creates a new PlaybackErrorEvent.
182      */
PlaybackErrorEvent( @ullable String exceptionStack, int errorCode, int subErrorCode, long timeSinceCreatedMillis, @NonNull Bundle extras)183     private PlaybackErrorEvent(
184             @Nullable String exceptionStack,
185             int errorCode,
186             int subErrorCode,
187             long timeSinceCreatedMillis,
188             @NonNull Bundle extras) {
189         this.mExceptionStack = exceptionStack;
190         this.mErrorCode = errorCode;
191         this.mSubErrorCode = subErrorCode;
192         this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
193         this.mMetricsBundle = extras.deepCopy();
194     }
195 
196     /** @hide */
197     @Nullable
getExceptionStack()198     public String getExceptionStack() {
199         return mExceptionStack;
200     }
201 
202 
203     /**
204      * Gets error code.
205      */
206     @ErrorCode
getErrorCode()207     public int getErrorCode() {
208         return mErrorCode;
209     }
210 
211 
212     /**
213      * Gets sub error code.
214      */
215     @IntRange(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE)
getSubErrorCode()216     public int getSubErrorCode() {
217         return mSubErrorCode;
218     }
219 
220     /**
221      * Gets the timestamp since creation of the playback session in milliseconds.
222      * @return the timestamp since the playback is created, or -1 if unknown.
223      * @see LogSessionId
224      * @see PlaybackSession
225      */
226     @Override
227     @IntRange(from = -1)
getTimeSinceCreatedMillis()228     public long getTimeSinceCreatedMillis() {
229         return mTimeSinceCreatedMillis;
230     }
231 
232     /**
233      * Gets metrics-related information that is not supported by dedicated methods.
234      * <p>It is intended to be used for backwards compatibility by the metrics infrastructure.
235      */
236     @Override
237     @NonNull
getMetricsBundle()238     public Bundle getMetricsBundle() {
239         return mMetricsBundle;
240     }
241 
242     @Override
toString()243     public String toString() {
244         return "PlaybackErrorEvent { "
245                 + "exceptionStack = " + mExceptionStack + ", "
246                 + "errorCode = " + mErrorCode + ", "
247                 + "subErrorCode = " + mSubErrorCode + ", "
248                 + "timeSinceCreatedMillis = " + mTimeSinceCreatedMillis
249                 + " }";
250     }
251 
252     @Override
equals(@ullable Object o)253     public boolean equals(@Nullable Object o) {
254         if (this == o) return true;
255         if (o == null || getClass() != o.getClass()) return false;
256         PlaybackErrorEvent that = (PlaybackErrorEvent) o;
257         return Objects.equals(mExceptionStack, that.mExceptionStack)
258                 && mErrorCode == that.mErrorCode
259                 && mSubErrorCode == that.mSubErrorCode
260                 && mTimeSinceCreatedMillis == that.mTimeSinceCreatedMillis;
261     }
262 
263     @Override
hashCode()264     public int hashCode() {
265         return Objects.hash(mExceptionStack, mErrorCode, mSubErrorCode,
266             mTimeSinceCreatedMillis);
267     }
268 
269     @Override
writeToParcel(@onNull Parcel dest, int flags)270     public void writeToParcel(@NonNull Parcel dest, int flags) {
271         byte flg = 0;
272         if (mExceptionStack != null) flg |= 0x1;
273         dest.writeByte(flg);
274         if (mExceptionStack != null) dest.writeString(mExceptionStack);
275         dest.writeInt(mErrorCode);
276         dest.writeInt(mSubErrorCode);
277         dest.writeLong(mTimeSinceCreatedMillis);
278         dest.writeBundle(mMetricsBundle);
279     }
280 
281     @Override
describeContents()282     public int describeContents() {
283         return 0;
284     }
285 
PlaybackErrorEvent(@onNull Parcel in)286     private PlaybackErrorEvent(@NonNull Parcel in) {
287         byte flg = in.readByte();
288         String exceptionStack = (flg & 0x1) == 0 ? null : in.readString();
289         int errorCode = in.readInt();
290         int subErrorCode = in.readInt();
291         long timeSinceCreatedMillis = in.readLong();
292         Bundle extras = in.readBundle();
293 
294         this.mExceptionStack = exceptionStack;
295         this.mErrorCode = errorCode;
296         this.mSubErrorCode = subErrorCode;
297         this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
298         this.mMetricsBundle = extras;
299     }
300 
301 
302     public static final @NonNull Parcelable.Creator<PlaybackErrorEvent> CREATOR =
303             new Parcelable.Creator<PlaybackErrorEvent>() {
304         @Override
305         public PlaybackErrorEvent[] newArray(int size) {
306             return new PlaybackErrorEvent[size];
307         }
308 
309         @Override
310         public PlaybackErrorEvent createFromParcel(@NonNull Parcel in) {
311             return new PlaybackErrorEvent(in);
312         }
313     };
314 
315     /**
316      * A builder for {@link PlaybackErrorEvent}
317      */
318     public static final class Builder {
319         private @Nullable Exception mException;
320         private int mErrorCode = ERROR_UNKNOWN;
321         private int mSubErrorCode;
322         private long mTimeSinceCreatedMillis = -1;
323         private Bundle mMetricsBundle = new Bundle();
324 
325         /**
326          * Creates a new Builder.
327          */
Builder()328         public Builder() {
329         }
330 
331         /**
332          * Sets the {@link Exception} object.
333          */
334         @SuppressLint("MissingGetterMatchingBuilder") // Exception is not parcelable.
setException(@onNull Exception value)335         public @NonNull Builder setException(@NonNull Exception value) {
336             mException = value;
337             return this;
338         }
339 
340         /**
341          * Sets error code.
342          */
setErrorCode(@rrorCode int value)343         public @NonNull Builder setErrorCode(@ErrorCode int value) {
344             mErrorCode = value;
345             return this;
346         }
347 
348         /**
349          * Sets sub error code.
350          */
setSubErrorCode( @ntRangefrom = Integer.MIN_VALUE, to = Integer.MAX_VALUE) int value)351         public @NonNull Builder setSubErrorCode(
352                 @IntRange(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE) int value) {
353             mSubErrorCode = value;
354             return this;
355         }
356 
357         /**
358          * Set the timestamp since creation in milliseconds.
359          * @param value the timestamp since the creation in milliseconds.
360          *              -1 indicates the value is unknown.
361          * @see #getTimeSinceCreatedMillis()
362          */
setTimeSinceCreatedMillis(@ntRangefrom = -1) long value)363         public @NonNull Builder setTimeSinceCreatedMillis(@IntRange(from = -1) long value) {
364             mTimeSinceCreatedMillis = value;
365             return this;
366         }
367 
368         /**
369          * Sets metrics-related information that is not supported by dedicated
370          * methods.
371          * <p>It is intended to be used for backwards compatibility by the
372          * metrics infrastructure.
373          */
setMetricsBundle(@onNull Bundle metricsBundle)374         public @NonNull Builder setMetricsBundle(@NonNull Bundle metricsBundle) {
375             mMetricsBundle = metricsBundle;
376             return this;
377         }
378 
379         /** Builds the instance. */
build()380         public @NonNull PlaybackErrorEvent build() {
381 
382             String stack;
383             if (mException.getStackTrace() != null && mException.getStackTrace().length > 0) {
384                 // TODO: a better definition of the stack trace
385                 stack = mException.getStackTrace()[0].toString();
386             } else {
387                 stack = null;
388             }
389 
390             PlaybackErrorEvent o = new PlaybackErrorEvent(
391                     stack,
392                     mErrorCode,
393                     mSubErrorCode,
394                     mTimeSinceCreatedMillis,
395                     mMetricsBundle);
396             return o;
397         }
398     }
399 }
400