Add all fields to PlaybackMetrics

Bug: 167036690
Test: mmm
Change-Id: Ia52441bb1b40c684c72eab691ade293acb927a29
This commit is contained in:
shubang
2020-12-03 00:50:47 -08:00
parent 7721431149
commit d233f80a35
2 changed files with 547 additions and 21 deletions

View File

@@ -16,11 +16,19 @@
package android.media.metrics;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.AnnotationValidations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
@@ -28,38 +36,323 @@ import java.util.Objects;
* @hide
*/
public final class PlaybackMetrics implements Parcelable {
private int mStreamSourceType;
// TODO(b/177209128): JavaDoc for the constants.
public static final int STREAM_SOURCE_UNKNOWN = 0;
public static final int STREAM_SOURCE_NETWORK = 1;
public static final int STREAM_SOURCE_DEVICE = 2;
public static final int STREAM_SOURCE_MIXED = 3;
public static final int STREAM_TYPE_UNKNOWN = 0;
public static final int STREAM_TYPE_OTHER = 1;
public static final int STREAM_TYPE_PROGRESSIVE = 2;
public static final int STREAM_TYPE_DASH = 3;
public static final int STREAM_TYPE_HLS = 4;
public static final int STREAM_TYPE_SS = 5;
public static final int PLAYBACK_TYPE_VOD = 0;
public static final int PLAYBACK_TYPE_LIVE = 1;
public static final int PLAYBACK_TYPE_OTHER = 2;
public static final int DRM_TYPE_NONE = 0;
public static final int DRM_TYPE_OTHER = 1;
public static final int DRM_TYPE_PLAY_READY = 2;
public static final int DRM_TYPE_WIDEVINE_L1 = 3;
public static final int DRM_TYPE_WIDEVINE_L3 = 4;
// TODO: add DRM_TYPE_CLEARKEY
public static final int CONTENT_TYPE_MAIN = 0;
public static final int CONTENT_TYPE_AD = 1;
public static final int CONTENT_TYPE_OTHER = 2;
/** @hide */
@IntDef(prefix = "STREAM_SOURCE_", value = {
STREAM_SOURCE_UNKNOWN,
STREAM_SOURCE_NETWORK,
STREAM_SOURCE_DEVICE,
STREAM_SOURCE_MIXED
})
@Retention(RetentionPolicy.SOURCE)
public @interface StreamSource {}
/** @hide */
@IntDef(prefix = "STREAM_TYPE_", value = {
STREAM_TYPE_UNKNOWN,
STREAM_TYPE_OTHER,
STREAM_TYPE_PROGRESSIVE,
STREAM_TYPE_DASH,
STREAM_TYPE_HLS,
STREAM_TYPE_SS
})
@Retention(RetentionPolicy.SOURCE)
public @interface StreamType {}
/** @hide */
@IntDef(prefix = "PLAYBACK_TYPE_", value = {
PLAYBACK_TYPE_VOD,
PLAYBACK_TYPE_LIVE,
PLAYBACK_TYPE_OTHER
})
@Retention(RetentionPolicy.SOURCE)
public @interface PlaybackType {}
/** @hide */
@IntDef(prefix = "DRM_TYPE_", value = {
DRM_TYPE_NONE,
DRM_TYPE_OTHER,
DRM_TYPE_PLAY_READY,
DRM_TYPE_WIDEVINE_L1,
DRM_TYPE_WIDEVINE_L3
})
@Retention(RetentionPolicy.SOURCE)
public @interface DrmType {}
/** @hide */
@IntDef(prefix = "CONTENT_TYPE_", value = {
CONTENT_TYPE_MAIN,
CONTENT_TYPE_AD,
CONTENT_TYPE_OTHER
})
@Retention(RetentionPolicy.SOURCE)
public @interface ContentType {}
private final long mMediaDurationMillis;
private final int mStreamSource;
private final int mStreamType;
private final int mPlaybackType;
private final int mDrmType;
private final int mContentType;
private final @Nullable String mPlayerName;
private final @Nullable String mPlayerVersion;
private final @NonNull long[] mExperimentIds;
private final int mVideoFramesPlayed;
private final int mVideoFramesDropped;
private final int mAudioUnderrunCount;
private final long mNetworkBytesRead;
private final long mLocalBytesRead;
private final long mNetworkTransferDurationMillis;
/**
* Creates a new PlaybackMetrics.
*
* @hide
*/
public PlaybackMetrics(int streamSourceType) {
this.mStreamSourceType = streamSourceType;
public 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) {
this.mMediaDurationMillis = mediaDurationMillis;
this.mStreamSource = streamSource;
this.mStreamType = streamType;
this.mPlaybackType = playbackType;
this.mDrmType = drmType;
this.mContentType = contentType;
this.mPlayerName = playerName;
this.mPlayerVersion = playerVersion;
this.mExperimentIds = experimentIds;
AnnotationValidations.validate(NonNull.class, null, mExperimentIds);
this.mVideoFramesPlayed = videoFramesPlayed;
this.mVideoFramesDropped = videoFramesDropped;
this.mAudioUnderrunCount = audioUnderrunCount;
this.mNetworkBytesRead = networkBytesRead;
this.mLocalBytesRead = localBytesRead;
this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
}
public int getStreamSourceType() {
return mStreamSourceType;
public long getMediaDurationMillis() {
return mMediaDurationMillis;
}
/**
* Gets stream source type.
*/
@StreamSource
public int getStreamSource() {
return mStreamSource;
}
/**
* Gets stream type.
*/
@StreamType
public int getStreamType() {
return mStreamType;
}
/**
* Gets playback type.
*/
@PlaybackType
public int getPlaybackType() {
return mPlaybackType;
}
/**
* Gets DRM type.
*/
@DrmType
public int getDrmType() {
return mDrmType;
}
/**
* Gets content type.
*/
@ContentType
public int getContentType() {
return mContentType;
}
/**
* Gets player name.
*/
public @Nullable String getPlayerName() {
return mPlayerName;
}
/**
* Gets player version.
*/
public @Nullable String getPlayerVersion() {
return mPlayerVersion;
}
/**
* Gets experiment IDs.
*/
public @NonNull long[] getExperimentIds() {
return Arrays.copyOf(mExperimentIds, mExperimentIds.length);
}
/**
* Gets video frames played.
*/
public int getVideoFramesPlayed() {
return mVideoFramesPlayed;
}
/**
* Gets video frames dropped.
*/
public int getVideoFramesDropped() {
return mVideoFramesDropped;
}
/**
* Gets audio underrun count.
*/
public int getAudioUnderrunCount() {
return mAudioUnderrunCount;
}
/**
* Gets number of network bytes read.
*/
public long getNetworkBytesRead() {
return mNetworkBytesRead;
}
/**
* Gets number of local bytes read.
*/
public long getLocalBytesRead() {
return mLocalBytesRead;
}
/**
* Gets network transfer duration in milliseconds.
*/
public long getNetworkTransferDurationMillis() {
return mNetworkTransferDurationMillis;
}
@Override
public String toString() {
return "PlaybackMetrics { "
+ "mediaDurationMillis = " + mMediaDurationMillis + ", "
+ "streamSource = " + mStreamSource + ", "
+ "streamType = " + mStreamType + ", "
+ "playbackType = " + mPlaybackType + ", "
+ "drmType = " + mDrmType + ", "
+ "contentType = " + mContentType + ", "
+ "playerName = " + mPlayerName + ", "
+ "playerVersion = " + mPlayerVersion + ", "
+ "experimentIds = " + Arrays.toString(mExperimentIds) + ", "
+ "videoFramesPlayed = " + mVideoFramesPlayed + ", "
+ "videoFramesDropped = " + mVideoFramesDropped + ", "
+ "audioUnderrunCount = " + mAudioUnderrunCount + ", "
+ "networkBytesRead = " + mNetworkBytesRead + ", "
+ "localBytesRead = " + mLocalBytesRead + ", "
+ "networkTransferDurationMillis = " + mNetworkTransferDurationMillis
+ " }";
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlaybackMetrics that = (PlaybackMetrics) o;
return mStreamSourceType == that.mStreamSourceType;
return mMediaDurationMillis == that.mMediaDurationMillis
&& mStreamSource == that.mStreamSource
&& mStreamType == that.mStreamType
&& mPlaybackType == that.mPlaybackType
&& mDrmType == that.mDrmType
&& mContentType == that.mContentType
&& Objects.equals(mPlayerName, that.mPlayerName)
&& Objects.equals(mPlayerVersion, that.mPlayerVersion)
&& Arrays.equals(mExperimentIds, that.mExperimentIds)
&& mVideoFramesPlayed == that.mVideoFramesPlayed
&& mVideoFramesDropped == that.mVideoFramesDropped
&& mAudioUnderrunCount == that.mAudioUnderrunCount
&& mNetworkBytesRead == that.mNetworkBytesRead
&& mLocalBytesRead == that.mLocalBytesRead
&& mNetworkTransferDurationMillis == that.mNetworkTransferDurationMillis;
}
@Override
public int hashCode() {
return Objects.hash(mStreamSourceType);
return Objects.hash(mMediaDurationMillis, mStreamSource, mStreamType, mPlaybackType,
mDrmType, mContentType, mPlayerName, mPlayerVersion, mExperimentIds,
mVideoFramesPlayed, mVideoFramesDropped, mAudioUnderrunCount, mNetworkBytesRead,
mLocalBytesRead, mNetworkTransferDurationMillis);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mStreamSourceType);
long flg = 0;
if (mPlayerName != null) flg |= 0x80;
if (mPlayerVersion != null) flg |= 0x100;
dest.writeLong(flg);
dest.writeLong(mMediaDurationMillis);
dest.writeInt(mStreamSource);
dest.writeInt(mStreamType);
dest.writeInt(mPlaybackType);
dest.writeInt(mDrmType);
dest.writeInt(mContentType);
if (mPlayerName != null) dest.writeString(mPlayerName);
if (mPlayerVersion != null) dest.writeString(mPlayerVersion);
dest.writeLongArray(mExperimentIds);
dest.writeInt(mVideoFramesPlayed);
dest.writeInt(mVideoFramesDropped);
dest.writeInt(mAudioUnderrunCount);
dest.writeLong(mNetworkBytesRead);
dest.writeLong(mLocalBytesRead);
dest.writeLong(mNetworkTransferDurationMillis);
}
@Override
@@ -69,20 +362,231 @@ public final class PlaybackMetrics implements Parcelable {
/** @hide */
/* package-private */ PlaybackMetrics(@NonNull Parcel in) {
int streamSourceType = in.readInt();
this.mStreamSourceType = streamSourceType;
long flg = in.readLong();
long mediaDurationMillis = in.readLong();
int streamSource = in.readInt();
int streamType = in.readInt();
int playbackType = in.readInt();
int drmType = in.readInt();
int contentType = in.readInt();
String playerName = (flg & 0x80) == 0 ? null : in.readString();
String playerVersion = (flg & 0x100) == 0 ? null : in.readString();
long[] experimentIds = in.createLongArray();
int videoFramesPlayed = in.readInt();
int videoFramesDropped = in.readInt();
int audioUnderrunCount = in.readInt();
long networkBytesRead = in.readLong();
long localBytesRead = in.readLong();
long networkTransferDurationMillis = in.readLong();
this.mMediaDurationMillis = mediaDurationMillis;
this.mStreamSource = streamSource;
this.mStreamType = streamType;
this.mPlaybackType = playbackType;
this.mDrmType = drmType;
this.mContentType = contentType;
this.mPlayerName = playerName;
this.mPlayerVersion = playerVersion;
this.mExperimentIds = experimentIds;
AnnotationValidations.validate(NonNull.class, null, mExperimentIds);
this.mVideoFramesPlayed = videoFramesPlayed;
this.mVideoFramesDropped = videoFramesDropped;
this.mAudioUnderrunCount = audioUnderrunCount;
this.mNetworkBytesRead = networkBytesRead;
this.mLocalBytesRead = localBytesRead;
this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
}
public static final @NonNull Parcelable.Creator<PlaybackMetrics> CREATOR =
new Parcelable.Creator<PlaybackMetrics>() {
@Override
public PlaybackMetrics[] newArray(int size) {
return new PlaybackMetrics[size];
}
@Override
public PlaybackMetrics[] newArray(int size) {
return new PlaybackMetrics[size];
}
@Override
public PlaybackMetrics createFromParcel(@NonNull Parcel in) {
return new PlaybackMetrics(in);
}
};
@Override
public PlaybackMetrics createFromParcel(@NonNull Parcel in) {
return new PlaybackMetrics(in);
}
};
/**
* A builder for {@link PlaybackMetrics}
*/
public static final class Builder {
private long mMediaDurationMillis;
private int mStreamSource;
private int mStreamType;
private int mPlaybackType;
private int mDrmType;
private int mContentType;
private @Nullable String mPlayerName;
private @Nullable String mPlayerVersion;
private @NonNull List<Long> mExperimentIds = new ArrayList<>();
private int mVideoFramesPlayed;
private int mVideoFramesDropped;
private int mAudioUnderrunCount;
private long mNetworkBytesRead;
private long mLocalBytesRead;
private long mNetworkTransferDurationMillis;
/**
* Creates a new Builder.
*
* @hide
*/
public Builder() {
}
/**
* Sets the media duration in milliseconds.
*/
public @NonNull Builder setMediaDurationMillis(long value) {
mMediaDurationMillis = value;
return this;
}
/**
* Sets the stream source type.
*/
public @NonNull Builder setStreamSource(@StreamSource int value) {
mStreamSource = value;
return this;
}
/**
* Sets the stream type.
*/
public @NonNull Builder setStreamType(@StreamType int value) {
mStreamType = value;
return this;
}
/**
* Sets the playback type.
*/
public @NonNull Builder setPlaybackType(@PlaybackType int value) {
mPlaybackType = value;
return this;
}
/**
* Sets the DRM type.
*/
public @NonNull Builder setDrmType(@StreamType int value) {
mDrmType = value;
return this;
}
/**
* Sets the content type.
*/
public @NonNull Builder setContentType(@ContentType int value) {
mContentType = value;
return this;
}
/**
* Sets the player name.
*/
public @NonNull Builder setPlayerName(@NonNull String value) {
mPlayerName = value;
return this;
}
/**
* Sets the player version.
*/
public @NonNull Builder setPlayerVersion(@NonNull String value) {
mPlayerVersion = value;
return this;
}
/**
* Adds the experiment ID.
*/
public @NonNull Builder addExperimentId(long value) {
mExperimentIds.add(value);
return this;
}
/**
* Sets the video frames played.
*/
public @NonNull Builder setVideoFramesPlayed(int value) {
mVideoFramesPlayed = value;
return this;
}
/**
* Sets the video frames dropped.
*/
public @NonNull Builder setVideoFramesDropped(int value) {
mVideoFramesDropped = value;
return this;
}
/**
* Sets the audio underrun count.
*/
public @NonNull Builder setAudioUnderrunCount(int value) {
mAudioUnderrunCount = value;
return this;
}
/**
* Sets the number of network bytes read.
*/
public @NonNull Builder setNetworkBytesRead(long value) {
mNetworkBytesRead = value;
return this;
}
/**
* Sets the number of local bytes read.
*/
public @NonNull Builder setLocalBytesRead(long value) {
mLocalBytesRead = value;
return this;
}
/**
* Sets the network transfer duration in milliseconds.
*/
public @NonNull Builder setNetworkTransferDurationMillis(long value) {
mNetworkTransferDurationMillis = value;
return this;
}
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull PlaybackMetrics build() {
PlaybackMetrics o = new PlaybackMetrics(
mMediaDurationMillis,
mStreamSource,
mStreamType,
mPlaybackType,
mDrmType,
mContentType,
mPlayerName,
mPlayerVersion,
idsToLongArray(),
mVideoFramesPlayed,
mVideoFramesDropped,
mAudioUnderrunCount,
mNetworkBytesRead,
mLocalBytesRead,
mNetworkTransferDurationMillis);
return o;
}
private long[] idsToLongArray() {
long[] ids = new long[mExperimentIds.size()];
for (int i = 0; i < mExperimentIds.size(); i++) {
ids[i] = mExperimentIds.get(i);
}
return ids;
}
}
}

View File

@@ -21,6 +21,7 @@ import android.media.metrics.IPlaybackMetricsManager;
import android.media.metrics.NetworkEvent;
import android.media.metrics.PlaybackErrorEvent;
import android.media.metrics.PlaybackMetrics;
import android.os.Binder;
import android.util.Base64;
import android.util.StatsEvent;
import android.util.StatsLog;
@@ -54,7 +55,28 @@ public final class PlaybackMetricsManagerService extends SystemService {
private final class BinderService extends IPlaybackMetricsManager.Stub {
@Override
public void reportPlaybackMetrics(String sessionId, PlaybackMetrics metrics, int userId) {
// TODO: log it to statsd
StatsEvent statsEvent = StatsEvent.newBuilder()
.setAtomId(320)
.writeInt(Binder.getCallingUid())
.writeString(sessionId)
.writeLong(metrics.getMediaDurationMillis())
.writeInt(metrics.getStreamSource())
.writeInt(metrics.getStreamType())
.writeInt(metrics.getPlaybackType())
.writeInt(metrics.getDrmType())
.writeInt(metrics.getContentType())
.writeString(metrics.getPlayerName())
.writeString(metrics.getPlayerVersion())
.writeByteArray(new byte[0]) // TODO: write experiments proto
.writeInt(metrics.getVideoFramesPlayed())
.writeInt(metrics.getVideoFramesDropped())
.writeInt(metrics.getAudioUnderrunCount())
.writeLong(metrics.getNetworkBytesRead())
.writeLong(metrics.getLocalBytesRead())
.writeLong(metrics.getNetworkTransferDurationMillis())
.usePooledBuffer()
.build();
StatsLog.write(statsEvent);
}
@Override