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.os.Bundle; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import com.android.internal.util.AnnotationValidations; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.List; 34 import java.util.Objects; 35 36 /** 37 * This class is used to store playback data. 38 */ 39 public final class PlaybackMetrics implements Parcelable { 40 /** Unknown stream source. */ 41 public static final int STREAM_SOURCE_UNKNOWN = 0; 42 /** Stream from network. */ 43 public static final int STREAM_SOURCE_NETWORK = 1; 44 /** Stream from device. */ 45 public static final int STREAM_SOURCE_DEVICE = 2; 46 /** Stream from more than one sources. */ 47 public static final int STREAM_SOURCE_MIXED = 3; 48 49 /** Unknown stream type. */ 50 public static final int STREAM_TYPE_UNKNOWN = 0; 51 /** Other stream type. */ 52 public static final int STREAM_TYPE_OTHER = 1; 53 /** Progressive stream type. */ 54 public static final int STREAM_TYPE_PROGRESSIVE = 2; 55 /** DASH (Dynamic Adaptive Streaming over HTTP) stream type. */ 56 public static final int STREAM_TYPE_DASH = 3; 57 /** HLS (HTTP Live Streaming) stream type. */ 58 public static final int STREAM_TYPE_HLS = 4; 59 /** SS (HTTP Smooth Streaming) stream type. */ 60 public static final int STREAM_TYPE_SS = 5; 61 62 /** Unknown playback type. */ 63 public static final int PLAYBACK_TYPE_UNKNOWN = 0; 64 /** VOD (Video on Demand) playback type. */ 65 public static final int PLAYBACK_TYPE_VOD = 1; 66 /** Live playback type. */ 67 public static final int PLAYBACK_TYPE_LIVE = 2; 68 /** Other playback type. */ 69 public static final int PLAYBACK_TYPE_OTHER = 3; 70 71 /** DRM is not used. */ 72 public static final int DRM_TYPE_NONE = 0; 73 /** Other DRM type. */ 74 public static final int DRM_TYPE_OTHER = 1; 75 /** Play ready DRM type. */ 76 public static final int DRM_TYPE_PLAY_READY = 2; 77 /** Widevine L1 DRM type. */ 78 public static final int DRM_TYPE_WIDEVINE_L1 = 3; 79 /** Widevine L3 DRM type. */ 80 public static final int DRM_TYPE_WIDEVINE_L3 = 4; 81 /** Widevine L3 fallback DRM type. */ 82 public static final int DRM_TYPE_WV_L3_FALLBACK = 5; 83 /** Clear key DRM type. */ 84 public static final int DRM_TYPE_CLEARKEY = 6; 85 86 /** Unknown content type. */ 87 public static final int CONTENT_TYPE_UNKNOWN = 0; 88 /** Main contents. */ 89 public static final int CONTENT_TYPE_MAIN = 1; 90 /** Advertisement contents. */ 91 public static final int CONTENT_TYPE_AD = 2; 92 /** Other contents. */ 93 public static final int CONTENT_TYPE_OTHER = 3; 94 95 96 /** @hide */ 97 @IntDef(prefix = "STREAM_SOURCE_", value = { 98 STREAM_SOURCE_UNKNOWN, 99 STREAM_SOURCE_NETWORK, 100 STREAM_SOURCE_DEVICE, 101 STREAM_SOURCE_MIXED 102 }) 103 @Retention(RetentionPolicy.SOURCE) 104 public @interface StreamSource {} 105 106 /** @hide */ 107 @IntDef(prefix = "STREAM_TYPE_", value = { 108 STREAM_TYPE_UNKNOWN, 109 STREAM_TYPE_OTHER, 110 STREAM_TYPE_PROGRESSIVE, 111 STREAM_TYPE_DASH, 112 STREAM_TYPE_HLS, 113 STREAM_TYPE_SS 114 }) 115 @Retention(RetentionPolicy.SOURCE) 116 public @interface StreamType {} 117 118 /** @hide */ 119 @IntDef(prefix = "PLAYBACK_TYPE_", value = { 120 PLAYBACK_TYPE_UNKNOWN, 121 PLAYBACK_TYPE_VOD, 122 PLAYBACK_TYPE_LIVE, 123 PLAYBACK_TYPE_OTHER 124 }) 125 @Retention(RetentionPolicy.SOURCE) 126 public @interface PlaybackType {} 127 128 /** @hide */ 129 @IntDef(prefix = "DRM_TYPE_", value = { 130 DRM_TYPE_NONE, 131 DRM_TYPE_OTHER, 132 DRM_TYPE_PLAY_READY, 133 DRM_TYPE_WIDEVINE_L1, 134 DRM_TYPE_WIDEVINE_L3, 135 DRM_TYPE_WV_L3_FALLBACK, 136 DRM_TYPE_CLEARKEY 137 }) 138 @Retention(RetentionPolicy.SOURCE) 139 public @interface DrmType {} 140 141 /** @hide */ 142 @IntDef(prefix = "CONTENT_TYPE_", value = { 143 CONTENT_TYPE_UNKNOWN, 144 CONTENT_TYPE_MAIN, 145 CONTENT_TYPE_AD, 146 CONTENT_TYPE_OTHER 147 }) 148 @Retention(RetentionPolicy.SOURCE) 149 public @interface ContentType {} 150 151 152 153 private final long mMediaDurationMillis; 154 private final int mStreamSource; 155 private final int mStreamType; 156 private final int mPlaybackType; 157 private final int mDrmType; 158 private final int mContentType; 159 private final @Nullable String mPlayerName; 160 private final @Nullable String mPlayerVersion; 161 private final @NonNull long[] mExperimentIds; 162 private final int mVideoFramesPlayed; 163 private final int mVideoFramesDropped; 164 private final int mAudioUnderrunCount; 165 private final long mNetworkBytesRead; 166 private final long mLocalBytesRead; 167 private final long mNetworkTransferDurationMillis; 168 private final byte[] mDrmSessionId; 169 private final @NonNull Bundle mMetricsBundle; 170 171 /** 172 * Creates a new PlaybackMetrics. 173 * 174 * @hide 175 */ PlaybackMetrics( long mediaDurationMillis, int streamSource, int streamType, int playbackType, int drmType, int contentType, @Nullable String playerName, @Nullable String playerVersion, @NonNull long[] experimentIds, int videoFramesPlayed, int videoFramesDropped, int audioUnderrunCount, long networkBytesRead, long localBytesRead, long networkTransferDurationMillis, byte[] drmSessionId, @NonNull Bundle extras)176 public PlaybackMetrics( 177 long mediaDurationMillis, 178 int streamSource, 179 int streamType, 180 int playbackType, 181 int drmType, 182 int contentType, 183 @Nullable String playerName, 184 @Nullable String playerVersion, 185 @NonNull long[] experimentIds, 186 int videoFramesPlayed, 187 int videoFramesDropped, 188 int audioUnderrunCount, 189 long networkBytesRead, 190 long localBytesRead, 191 long networkTransferDurationMillis, 192 byte[] drmSessionId, 193 @NonNull Bundle extras) { 194 this.mMediaDurationMillis = mediaDurationMillis; 195 this.mStreamSource = streamSource; 196 this.mStreamType = streamType; 197 this.mPlaybackType = playbackType; 198 this.mDrmType = drmType; 199 this.mContentType = contentType; 200 this.mPlayerName = playerName; 201 this.mPlayerVersion = playerVersion; 202 this.mExperimentIds = experimentIds; 203 AnnotationValidations.validate(NonNull.class, null, mExperimentIds); 204 this.mVideoFramesPlayed = videoFramesPlayed; 205 this.mVideoFramesDropped = videoFramesDropped; 206 this.mAudioUnderrunCount = audioUnderrunCount; 207 this.mNetworkBytesRead = networkBytesRead; 208 this.mLocalBytesRead = localBytesRead; 209 this.mNetworkTransferDurationMillis = networkTransferDurationMillis; 210 this.mDrmSessionId = drmSessionId; 211 this.mMetricsBundle = extras.deepCopy(); 212 } 213 214 /** 215 * Gets the media duration in milliseconds. 216 * <p>Media duration is the length of the media. 217 * @return the media duration in milliseconds, or -1 if unknown. 218 */ 219 @IntRange(from = -1) getMediaDurationMillis()220 public long getMediaDurationMillis() { 221 return mMediaDurationMillis; 222 } 223 224 /** 225 * Gets stream source type. 226 */ 227 @StreamSource getStreamSource()228 public int getStreamSource() { 229 return mStreamSource; 230 } 231 232 /** 233 * Gets stream type. 234 */ 235 @StreamType getStreamType()236 public int getStreamType() { 237 return mStreamType; 238 } 239 240 241 /** 242 * Gets playback type. 243 */ 244 @PlaybackType getPlaybackType()245 public int getPlaybackType() { 246 return mPlaybackType; 247 } 248 249 /** 250 * Gets DRM type. 251 */ 252 @DrmType getDrmType()253 public int getDrmType() { 254 return mDrmType; 255 } 256 257 /** 258 * Gets content type. 259 */ 260 @ContentType getContentType()261 public int getContentType() { 262 return mContentType; 263 } 264 265 /** 266 * Gets player name. 267 */ getPlayerName()268 public @Nullable String getPlayerName() { 269 return mPlayerName; 270 } 271 272 /** 273 * Gets player version. 274 */ getPlayerVersion()275 public @Nullable String getPlayerVersion() { 276 return mPlayerVersion; 277 } 278 279 /** 280 * Gets experiment IDs. 281 */ getExperimentIds()282 public @NonNull long[] getExperimentIds() { 283 return Arrays.copyOf(mExperimentIds, mExperimentIds.length); 284 } 285 286 /** 287 * Gets video frames played. 288 * @return the video frames played, or -1 if unknown. 289 */ 290 @IntRange(from = -1, to = Integer.MAX_VALUE) getVideoFramesPlayed()291 public int getVideoFramesPlayed() { 292 return mVideoFramesPlayed; 293 } 294 295 /** 296 * Gets video frames dropped. 297 * @return the video frames dropped, or -1 if unknown. 298 */ 299 @IntRange(from = -1, to = Integer.MAX_VALUE) getVideoFramesDropped()300 public int getVideoFramesDropped() { 301 return mVideoFramesDropped; 302 } 303 304 /** 305 * Gets audio underrun count. 306 * @return the audio underrun count, or -1 if unknown. 307 */ 308 @IntRange(from = -1, to = Integer.MAX_VALUE) getAudioUnderrunCount()309 public int getAudioUnderrunCount() { 310 return mAudioUnderrunCount; 311 } 312 313 /** 314 * Gets number of network bytes read. 315 * @return the number of network bytes read, or -1 if unknown. 316 */ 317 @IntRange(from = -1) getNetworkBytesRead()318 public long getNetworkBytesRead() { 319 return mNetworkBytesRead; 320 } 321 322 /** 323 * Gets number of local bytes read. 324 */ 325 @IntRange(from = -1) getLocalBytesRead()326 public long getLocalBytesRead() { 327 return mLocalBytesRead; 328 } 329 330 /** 331 * Gets network transfer duration in milliseconds. 332 * <p>Total transfer time spent reading from the network in ms. For parallel requests, the 333 * overlapping time intervals are counted only once. 334 */ 335 @IntRange(from = -1) getNetworkTransferDurationMillis()336 public long getNetworkTransferDurationMillis() { 337 return mNetworkTransferDurationMillis; 338 } 339 340 /** 341 * Gets DRM session ID. 342 */ 343 @NonNull getDrmSessionId()344 public byte[] getDrmSessionId() { 345 return mDrmSessionId; 346 } 347 348 /** 349 * Gets metrics-related information that is not supported by dedicated methods. 350 * <p>It is intended to be used for backwards compatibility by the metrics infrastructure. 351 */ 352 @NonNull getMetricsBundle()353 public Bundle getMetricsBundle() { 354 return mMetricsBundle; 355 } 356 357 @Override toString()358 public String toString() { 359 return "PlaybackMetrics { " 360 + "mediaDurationMillis = " + mMediaDurationMillis + ", " 361 + "streamSource = " + mStreamSource + ", " 362 + "streamType = " + mStreamType + ", " 363 + "playbackType = " + mPlaybackType + ", " 364 + "drmType = " + mDrmType + ", " 365 + "contentType = " + mContentType + ", " 366 + "playerName = " + mPlayerName + ", " 367 + "playerVersion = " + mPlayerVersion + ", " 368 + "experimentIds = " + Arrays.toString(mExperimentIds) + ", " 369 + "videoFramesPlayed = " + mVideoFramesPlayed + ", " 370 + "videoFramesDropped = " + mVideoFramesDropped + ", " 371 + "audioUnderrunCount = " + mAudioUnderrunCount + ", " 372 + "networkBytesRead = " + mNetworkBytesRead + ", " 373 + "localBytesRead = " + mLocalBytesRead + ", " 374 + "networkTransferDurationMillis = " + mNetworkTransferDurationMillis 375 + "drmSessionId = " + Arrays.toString(mDrmSessionId) 376 + " }"; 377 } 378 379 @Override equals(@ullable Object o)380 public boolean equals(@Nullable Object o) { 381 if (this == o) return true; 382 if (o == null || getClass() != o.getClass()) return false; 383 PlaybackMetrics that = (PlaybackMetrics) o; 384 return mMediaDurationMillis == that.mMediaDurationMillis 385 && mStreamSource == that.mStreamSource 386 && mStreamType == that.mStreamType 387 && mPlaybackType == that.mPlaybackType 388 && mDrmType == that.mDrmType 389 && mContentType == that.mContentType 390 && Objects.equals(mPlayerName, that.mPlayerName) 391 && Objects.equals(mPlayerVersion, that.mPlayerVersion) 392 && Arrays.equals(mExperimentIds, that.mExperimentIds) 393 && mVideoFramesPlayed == that.mVideoFramesPlayed 394 && mVideoFramesDropped == that.mVideoFramesDropped 395 && mAudioUnderrunCount == that.mAudioUnderrunCount 396 && mNetworkBytesRead == that.mNetworkBytesRead 397 && mLocalBytesRead == that.mLocalBytesRead 398 && mNetworkTransferDurationMillis == that.mNetworkTransferDurationMillis 399 && Arrays.equals(mDrmSessionId, that.mDrmSessionId); 400 } 401 402 @Override hashCode()403 public int hashCode() { 404 return Objects.hash(mMediaDurationMillis, mStreamSource, mStreamType, mPlaybackType, 405 mDrmType, mContentType, mPlayerName, mPlayerVersion, mExperimentIds, 406 mVideoFramesPlayed, mVideoFramesDropped, mAudioUnderrunCount, mNetworkBytesRead, 407 mLocalBytesRead, mNetworkTransferDurationMillis, mDrmSessionId); 408 } 409 410 @Override writeToParcel(@onNull Parcel dest, int flags)411 public void writeToParcel(@NonNull Parcel dest, int flags) { 412 long flg = 0; 413 if (mPlayerName != null) flg |= 0x80; 414 if (mPlayerVersion != null) flg |= 0x100; 415 dest.writeLong(flg); 416 dest.writeLong(mMediaDurationMillis); 417 dest.writeInt(mStreamSource); 418 dest.writeInt(mStreamType); 419 dest.writeInt(mPlaybackType); 420 dest.writeInt(mDrmType); 421 dest.writeInt(mContentType); 422 if (mPlayerName != null) dest.writeString(mPlayerName); 423 if (mPlayerVersion != null) dest.writeString(mPlayerVersion); 424 dest.writeLongArray(mExperimentIds); 425 dest.writeInt(mVideoFramesPlayed); 426 dest.writeInt(mVideoFramesDropped); 427 dest.writeInt(mAudioUnderrunCount); 428 dest.writeLong(mNetworkBytesRead); 429 dest.writeLong(mLocalBytesRead); 430 dest.writeLong(mNetworkTransferDurationMillis); 431 dest.writeInt(mDrmSessionId.length); 432 dest.writeByteArray(mDrmSessionId); 433 dest.writeBundle(mMetricsBundle); 434 } 435 436 @Override describeContents()437 public int describeContents() { 438 return 0; 439 } 440 441 /** @hide */ PlaybackMetrics(@onNull Parcel in)442 /* package-private */ PlaybackMetrics(@NonNull Parcel in) { 443 long flg = in.readLong(); 444 long mediaDurationMillis = in.readLong(); 445 int streamSource = in.readInt(); 446 int streamType = in.readInt(); 447 int playbackType = in.readInt(); 448 int drmType = in.readInt(); 449 int contentType = in.readInt(); 450 String playerName = (flg & 0x80) == 0 ? null : in.readString(); 451 String playerVersion = (flg & 0x100) == 0 ? null : in.readString(); 452 long[] experimentIds = in.createLongArray(); 453 int videoFramesPlayed = in.readInt(); 454 int videoFramesDropped = in.readInt(); 455 int audioUnderrunCount = in.readInt(); 456 long networkBytesRead = in.readLong(); 457 long localBytesRead = in.readLong(); 458 long networkTransferDurationMillis = in.readLong(); 459 int drmSessionIdLen = in.readInt(); 460 byte[] drmSessionId = new byte[drmSessionIdLen]; 461 in.readByteArray(drmSessionId); 462 Bundle extras = in.readBundle(); 463 464 this.mMediaDurationMillis = mediaDurationMillis; 465 this.mStreamSource = streamSource; 466 this.mStreamType = streamType; 467 this.mPlaybackType = playbackType; 468 this.mDrmType = drmType; 469 this.mContentType = contentType; 470 this.mPlayerName = playerName; 471 this.mPlayerVersion = playerVersion; 472 this.mExperimentIds = experimentIds; 473 AnnotationValidations.validate(NonNull.class, null, mExperimentIds); 474 this.mVideoFramesPlayed = videoFramesPlayed; 475 this.mVideoFramesDropped = videoFramesDropped; 476 this.mAudioUnderrunCount = audioUnderrunCount; 477 this.mNetworkBytesRead = networkBytesRead; 478 this.mLocalBytesRead = localBytesRead; 479 this.mNetworkTransferDurationMillis = networkTransferDurationMillis; 480 this.mDrmSessionId = drmSessionId; 481 this.mMetricsBundle = extras; 482 } 483 484 public static final @NonNull Parcelable.Creator<PlaybackMetrics> CREATOR = 485 new Parcelable.Creator<PlaybackMetrics>() { 486 @Override 487 public PlaybackMetrics[] newArray(int size) { 488 return new PlaybackMetrics[size]; 489 } 490 491 @Override 492 public PlaybackMetrics createFromParcel(@NonNull Parcel in) { 493 return new PlaybackMetrics(in); 494 } 495 }; 496 497 /** 498 * A builder for {@link PlaybackMetrics} 499 */ 500 public static final class Builder { 501 502 private long mMediaDurationMillis = -1; 503 private int mStreamSource = STREAM_SOURCE_UNKNOWN; 504 private int mStreamType = STREAM_TYPE_UNKNOWN; 505 private int mPlaybackType = PLAYBACK_TYPE_UNKNOWN; 506 private int mDrmType = DRM_TYPE_NONE; 507 private int mContentType = CONTENT_TYPE_UNKNOWN; 508 private @Nullable String mPlayerName; 509 private @Nullable String mPlayerVersion; 510 private @NonNull List<Long> mExperimentIds = new ArrayList<>(); 511 private int mVideoFramesPlayed = -1; 512 private int mVideoFramesDropped = -1; 513 private int mAudioUnderrunCount = -1; 514 private long mNetworkBytesRead = -1; 515 private long mLocalBytesRead = -1; 516 private long mNetworkTransferDurationMillis = -1; 517 private byte[] mDrmSessionId = new byte[0]; 518 private Bundle mMetricsBundle = new Bundle(); 519 520 /** 521 * Creates a new Builder. 522 */ Builder()523 public Builder() { 524 } 525 526 /** 527 * Sets the media duration in milliseconds. 528 * @param value the media duration in milliseconds. -1 indicates the value is unknown. 529 * @see #getMediaDurationMillis() 530 */ setMediaDurationMillis(@ntRangefrom = -1) long value)531 public @NonNull Builder setMediaDurationMillis(@IntRange(from = -1) long value) { 532 mMediaDurationMillis = value; 533 return this; 534 } 535 536 /** 537 * Sets the stream source type. 538 */ setStreamSource(@treamSource int value)539 public @NonNull Builder setStreamSource(@StreamSource int value) { 540 mStreamSource = value; 541 return this; 542 } 543 544 /** 545 * Sets the stream type. 546 */ setStreamType(@treamType int value)547 public @NonNull Builder setStreamType(@StreamType int value) { 548 mStreamType = value; 549 return this; 550 } 551 552 /** 553 * Sets the playback type. 554 */ setPlaybackType(@laybackType int value)555 public @NonNull Builder setPlaybackType(@PlaybackType int value) { 556 mPlaybackType = value; 557 return this; 558 } 559 560 /** 561 * Sets the DRM type. 562 */ setDrmType(@rmType int value)563 public @NonNull Builder setDrmType(@DrmType int value) { 564 mDrmType = value; 565 return this; 566 } 567 568 /** 569 * Sets the content type. 570 */ setContentType(@ontentType int value)571 public @NonNull Builder setContentType(@ContentType int value) { 572 mContentType = value; 573 return this; 574 } 575 576 /** 577 * Sets the player name. 578 */ setPlayerName(@onNull String value)579 public @NonNull Builder setPlayerName(@NonNull String value) { 580 mPlayerName = value; 581 return this; 582 } 583 584 /** 585 * Sets the player version. 586 */ setPlayerVersion(@onNull String value)587 public @NonNull Builder setPlayerVersion(@NonNull String value) { 588 mPlayerVersion = value; 589 return this; 590 } 591 592 /** 593 * Adds the experiment ID. 594 */ addExperimentId(long value)595 public @NonNull Builder addExperimentId(long value) { 596 mExperimentIds.add(value); 597 return this; 598 } 599 600 /** 601 * Sets the video frames played. 602 * @param value the video frames played. -1 indicates the value is unknown. 603 */ setVideoFramesPlayed( @ntRangefrom = -1, to = Integer.MAX_VALUE) int value)604 public @NonNull Builder setVideoFramesPlayed( 605 @IntRange(from = -1, to = Integer.MAX_VALUE) int value) { 606 mVideoFramesPlayed = value; 607 return this; 608 } 609 610 /** 611 * Sets the video frames dropped. 612 * @param value the video frames dropped. -1 indicates the value is unknown. 613 */ setVideoFramesDropped( @ntRangefrom = -1, to = Integer.MAX_VALUE) int value)614 public @NonNull Builder setVideoFramesDropped( 615 @IntRange(from = -1, to = Integer.MAX_VALUE) int value) { 616 mVideoFramesDropped = value; 617 return this; 618 } 619 620 /** 621 * Sets the audio underrun count. 622 * @param value the audio underrun count. -1 indicates the value is unknown. 623 */ setAudioUnderrunCount( @ntRangefrom = -1, to = Integer.MAX_VALUE) int value)624 public @NonNull Builder setAudioUnderrunCount( 625 @IntRange(from = -1, to = Integer.MAX_VALUE) int value) { 626 mAudioUnderrunCount = value; 627 return this; 628 } 629 630 /** 631 * Sets the number of network bytes read. 632 * @param value the number of network bytes read. -1 indicates the value is unknown. 633 */ setNetworkBytesRead(@ntRangefrom = -1) long value)634 public @NonNull Builder setNetworkBytesRead(@IntRange(from = -1) long value) { 635 mNetworkBytesRead = value; 636 return this; 637 } 638 639 /** 640 * Sets the number of local bytes read. 641 * @param value the number of local bytes read. -1 indicates the value is unknown. 642 */ setLocalBytesRead(@ntRangefrom = -1) long value)643 public @NonNull Builder setLocalBytesRead(@IntRange(from = -1) long value) { 644 mLocalBytesRead = value; 645 return this; 646 } 647 648 /** 649 * Sets the network transfer duration in milliseconds. 650 * @param value the network transfer duration in milliseconds. 651 * -1 indicates the value is unknown. 652 * @see #getNetworkTransferDurationMillis() 653 */ setNetworkTransferDurationMillis(@ntRangefrom = -1) long value)654 public @NonNull Builder setNetworkTransferDurationMillis(@IntRange(from = -1) long value) { 655 mNetworkTransferDurationMillis = value; 656 return this; 657 } 658 659 /** 660 * Sets DRM session ID. 661 */ setDrmSessionId(@onNull byte[] drmSessionId)662 public @NonNull Builder setDrmSessionId(@NonNull byte[] drmSessionId) { 663 mDrmSessionId = drmSessionId; 664 return this; 665 } 666 667 /** 668 * Sets metrics-related information that is not supported by dedicated 669 * methods. 670 * <p>It is intended to be used for backwards compatibility by the 671 * metrics infrastructure. 672 */ setMetricsBundle(@onNull Bundle metricsBundle)673 public @NonNull Builder setMetricsBundle(@NonNull Bundle metricsBundle) { 674 mMetricsBundle = metricsBundle; 675 return this; 676 } 677 678 /** Builds the instance. This builder should not be touched after calling this! */ build()679 public @NonNull PlaybackMetrics build() { 680 681 PlaybackMetrics o = new PlaybackMetrics( 682 mMediaDurationMillis, 683 mStreamSource, 684 mStreamType, 685 mPlaybackType, 686 mDrmType, 687 mContentType, 688 mPlayerName, 689 mPlayerVersion, 690 idsToLongArray(), 691 mVideoFramesPlayed, 692 mVideoFramesDropped, 693 mAudioUnderrunCount, 694 mNetworkBytesRead, 695 mLocalBytesRead, 696 mNetworkTransferDurationMillis, 697 mDrmSessionId, 698 mMetricsBundle); 699 return o; 700 } 701 idsToLongArray()702 private long[] idsToLongArray() { 703 long[] ids = new long[mExperimentIds.size()]; 704 for (int i = 0; i < mExperimentIds.size(); i++) { 705 ids[i] = mExperimentIds.get(i); 706 } 707 return ids; 708 } 709 } 710 } 711