Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d233f80a authored by shubang's avatar shubang
Browse files

Add all fields to PlaybackMetrics

Bug: 167036690
Test: mmm
Change-Id: Ia52441bb1b40c684c72eab691ade293acb927a29
parent 77214311
Loading
Loading
Loading
Loading
+525 −21
Original line number Diff line number Diff line
@@ -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 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;
    }

    public int getStreamSourceType() {
        return mStreamSourceType;
    /**
     * 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 boolean equals(@Nullable Object o) {
    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,8 +362,39 @@ 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 =
@@ -85,4 +409,184 @@ public final class PlaybackMetrics implements Parcelable {
            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;
        }
    }
}
+23 −1
Original line number Diff line number Diff line
@@ -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