diff --git a/media/java/android/media/metrics/Event.java b/media/java/android/media/metrics/Event.java index 5646dcdb6c9cf..96b61d2eaf4d0 100644 --- a/media/java/android/media/metrics/Event.java +++ b/media/java/android/media/metrics/Event.java @@ -17,22 +17,30 @@ package android.media.metrics; import android.annotation.IntRange; +import android.os.Bundle; /** * Abstract class for metrics events. */ public abstract class Event { - private final long mTimeSinceCreatedMillis; + final long mTimeSinceCreatedMillis; + Bundle mExtras; // hide default constructor /* package */ Event() { mTimeSinceCreatedMillis = MediaMetricsManager.INVALID_TIMESTAMP; } + // TODO: remove protected Event(long timeSinceCreatedMillis) { mTimeSinceCreatedMillis = timeSinceCreatedMillis; } + /* package */ Event(long timeSinceCreatedMillis, Bundle extras) { + mTimeSinceCreatedMillis = timeSinceCreatedMillis; + mExtras = extras; + } + /** * Gets time since the corresponding instance is created in millisecond. * @return the timestamp since the instance is created, or -1 if unknown. @@ -41,4 +49,9 @@ public abstract class Event { public long getTimeSinceCreatedMillis() { return mTimeSinceCreatedMillis; } + + /** @hide */ + public Bundle getExtras() { + return mExtras; + } } diff --git a/media/java/android/media/metrics/IMediaMetricsManager.aidl b/media/java/android/media/metrics/IMediaMetricsManager.aidl index 2cb2ab5c42b5e..f2c0d44a00b1e 100644 --- a/media/java/android/media/metrics/IMediaMetricsManager.aidl +++ b/media/java/android/media/metrics/IMediaMetricsManager.aidl @@ -28,7 +28,8 @@ import android.media.metrics.TrackChangeEvent; */ interface IMediaMetricsManager { void reportPlaybackMetrics(in String sessionId, in PlaybackMetrics metrics, int userId); - String getSessionId(int userId); + String getPlaybackSessionId(int userId); + String getRecordingSessionId(int userId); void reportNetworkEvent(in String sessionId, in NetworkEvent event, int userId); void reportPlaybackErrorEvent(in String sessionId, in PlaybackErrorEvent event, int userId); void reportPlaybackStateEvent(in String sessionId, in PlaybackStateEvent event, int userId); diff --git a/media/java/android/media/metrics/LogSessionId.java b/media/java/android/media/metrics/LogSessionId.java new file mode 100644 index 0000000000000..7ddb259f7f282 --- /dev/null +++ b/media/java/android/media/metrics/LogSessionId.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 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; + +/** + * An instances of this class represents the ID of a log session. + * @hide + */ +public class LogSessionId { + private final String mSessionId; + + /* package */ LogSessionId(String id) { + mSessionId = id; + } + + /** @hide */ + public String getStringId() { + return mSessionId; + } +} diff --git a/media/java/android/media/metrics/MediaMetricsManager.java b/media/java/android/media/metrics/MediaMetricsManager.java index de780f672b28e..9710e88cf24bb 100644 --- a/media/java/android/media/metrics/MediaMetricsManager.java +++ b/media/java/android/media/metrics/MediaMetricsManager.java @@ -94,7 +94,7 @@ public class MediaMetricsManager { @NonNull public PlaybackSession createPlaybackSession() { try { - String id = mService.getSessionId(mUserId); + String id = mService.getPlaybackSessionId(mUserId); PlaybackSession session = new PlaybackSession(id, this); return session; } catch (RemoteException e) { @@ -102,6 +102,21 @@ public class MediaMetricsManager { } } + /** + * Creates a recording session. + * @hide + */ + @NonNull + public RecordingSession createRecordingSession() { + try { + String id = mService.getRecordingSessionId(mUserId); + RecordingSession session = new RecordingSession(id, this); + return session; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Reports error event. * @hide diff --git a/media/java/android/media/metrics/NetworkEvent.java b/media/java/android/media/metrics/NetworkEvent.java index 029edeb933749..098885cc9bdd3 100644 --- a/media/java/android/media/metrics/NetworkEvent.java +++ b/media/java/android/media/metrics/NetworkEvent.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -33,6 +34,9 @@ import java.util.Objects; public final class NetworkEvent extends Event implements Parcelable { /** Network type is not specified. Default type. */ public static final int NETWORK_TYPE_NONE = 0; + // TODO: replace NONE with UNKNOWN + /** @hide */ + public static final int NETWORK_TYPE_UNKNOWN = 0; /** Other network type */ public static final int NETWORK_TYPE_OTHER = 1; /** Wi-Fi network */ @@ -49,6 +53,9 @@ public final class NetworkEvent extends Event implements Parcelable { public static final int NETWORK_TYPE_5G_NSA = 7; /** 5G SA network */ public static final int NETWORK_TYPE_5G_SA = 8; + /** Not network connected */ + /** @hide */ + public static final int NETWORK_TYPE_OFFLINE = 9; private final int mNetworkType; private final long mTimeSinceCreatedMillis; @@ -56,6 +63,7 @@ public final class NetworkEvent extends Event implements Parcelable { /** @hide */ @IntDef(prefix = "NETWORK_TYPE_", value = { NETWORK_TYPE_NONE, + NETWORK_TYPE_UNKNOWN, NETWORK_TYPE_OTHER, NETWORK_TYPE_WIFI, NETWORK_TYPE_ETHERNET, @@ -63,7 +71,8 @@ public final class NetworkEvent extends Event implements Parcelable { NETWORK_TYPE_3G, NETWORK_TYPE_4G, NETWORK_TYPE_5G_NSA, - NETWORK_TYPE_5G_SA + NETWORK_TYPE_5G_SA, + NETWORK_TYPE_OFFLINE }) @Retention(RetentionPolicy.SOURCE) public @interface NetworkType {} @@ -92,6 +101,8 @@ public final class NetworkEvent extends Event implements Parcelable { return "NETWORK_TYPE_5G_NSA"; case NETWORK_TYPE_5G_SA: return "NETWORK_TYPE_5G_SA"; + case NETWORK_TYPE_OFFLINE: + return "NETWORK_TYPE_OFFLINE"; default: return Integer.toHexString(value); } @@ -102,9 +113,10 @@ public final class NetworkEvent extends Event implements Parcelable { * * @hide */ - public NetworkEvent(@NetworkType int type, long timeSinceCreatedMillis) { + public NetworkEvent(@NetworkType int type, long timeSinceCreatedMillis, Bundle extras) { this.mNetworkType = type; this.mTimeSinceCreatedMillis = timeSinceCreatedMillis; + this.mExtras = extras.deepCopy(); } /** @@ -149,8 +161,12 @@ public final class NetworkEvent extends Event implements Parcelable { @Override public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { + byte flg = 0; + if (mExtras != null) flg |= 0x1; + dest.writeByte(flg); dest.writeInt(mNetworkType); dest.writeLong(mTimeSinceCreatedMillis); + if (mExtras != null) dest.writeBundle(mExtras); } @Override @@ -160,11 +176,14 @@ public final class NetworkEvent extends Event implements Parcelable { /** @hide */ /* package-private */ NetworkEvent(@NonNull android.os.Parcel in) { + byte flg = in.readByte(); int type = in.readInt(); long timeSinceCreatedMillis = in.readLong(); + Bundle extras = (flg & 0x2) == 0 ? null : in.readBundle(); this.mNetworkType = type; this.mTimeSinceCreatedMillis = timeSinceCreatedMillis; + this.mExtras = extras; } /** @@ -189,6 +208,7 @@ public final class NetworkEvent extends Event implements Parcelable { public static final class Builder { private int mNetworkType = NETWORK_TYPE_NONE; private long mTimeSinceCreatedMillis = -1; + private Bundle mExtras; /** * Creates a new Builder. @@ -214,9 +234,19 @@ public final class NetworkEvent extends Event implements Parcelable { return this; } + /** + * Set extras for compatibility. + *
Should be used by support library only. + * @hide + */ + public @NonNull Builder setExtras(@NonNull Bundle extras) { + mExtras = extras; + return this; + } + /** Builds the instance. */ public @NonNull NetworkEvent build() { - NetworkEvent o = new NetworkEvent(mNetworkType, mTimeSinceCreatedMillis); + NetworkEvent o = new NetworkEvent(mNetworkType, mTimeSinceCreatedMillis, mExtras); return o; } } diff --git a/media/java/android/media/metrics/PlaybackErrorEvent.java b/media/java/android/media/metrics/PlaybackErrorEvent.java index 5a0820d16cb9e..b23b4d2728b4e 100644 --- a/media/java/android/media/metrics/PlaybackErrorEvent.java +++ b/media/java/android/media/metrics/PlaybackErrorEvent.java @@ -21,6 +21,7 @@ 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; @@ -63,11 +64,13 @@ public final class PlaybackErrorEvent extends Event implements Parcelable { @Nullable String exceptionStack, int errorCode, int subErrorCode, - long timeSinceCreatedMillis) { + long timeSinceCreatedMillis, + Bundle extras) { this.mExceptionStack = exceptionStack; this.mErrorCode = errorCode; this.mSubErrorCode = subErrorCode; this.mTimeSinceCreatedMillis = timeSinceCreatedMillis; + this.mExtras = extras.deepCopy(); } /** @hide */ @@ -135,11 +138,13 @@ public final class PlaybackErrorEvent extends Event implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { byte flg = 0; if (mExceptionStack != null) flg |= 0x1; + if (mExtras != null) flg |= 0x2; dest.writeByte(flg); if (mExceptionStack != null) dest.writeString(mExceptionStack); dest.writeInt(mErrorCode); dest.writeInt(mSubErrorCode); dest.writeLong(mTimeSinceCreatedMillis); + if (mExtras != null) dest.writeBundle(mExtras); } @Override @@ -154,11 +159,13 @@ public final class PlaybackErrorEvent extends Event implements Parcelable { int errorCode = in.readInt(); int subErrorCode = in.readInt(); long timeSinceCreatedMillis = in.readLong(); + Bundle extras = (flg & 0x2) == 0 ? null : in.readBundle(); this.mExceptionStack = exceptionStack; this.mErrorCode = errorCode; this.mSubErrorCode = subErrorCode; this.mTimeSinceCreatedMillis = timeSinceCreatedMillis; + this.mExtras = extras; } @@ -183,6 +190,7 @@ public final class PlaybackErrorEvent extends Event implements Parcelable { private int mErrorCode; private int mSubErrorCode; private long mTimeSinceCreatedMillis = -1; + private Bundle mExtras; /** * Creates a new Builder. @@ -226,6 +234,16 @@ public final class PlaybackErrorEvent extends Event implements Parcelable { return this; } + /** + * Set extras for compatibility. + *
Should be used by support library only.
+ * @hide
+ */
+ public @NonNull Builder setExtras(@NonNull Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
/** Builds the instance. */
public @NonNull PlaybackErrorEvent build() {
@@ -241,7 +259,8 @@ public final class PlaybackErrorEvent extends Event implements Parcelable {
stack,
mErrorCode,
mSubErrorCode,
- mTimeSinceCreatedMillis);
+ mTimeSinceCreatedMillis,
+ mExtras);
return o;
}
}
diff --git a/media/java/android/media/metrics/PlaybackMetrics.java b/media/java/android/media/metrics/PlaybackMetrics.java
index 4aa61662ba52b..7e7f44a97b9c5 100644
--- a/media/java/android/media/metrics/PlaybackMetrics.java
+++ b/media/java/android/media/metrics/PlaybackMetrics.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -58,6 +59,10 @@ public final class PlaybackMetrics implements Parcelable {
/** SS (HTTP Smooth Streaming) stream type. */
public static final int STREAM_TYPE_SS = 5;
+ /** Unknown playback type. */
+ // TODO: change the PLAYBACK_TYPE_ values
+ /** @hide */
+ public static final int PLAYBACK_TYPE_UNKNOWN = 0;
/** VOD (Video on Demand) playback type. */
public static final int PLAYBACK_TYPE_VOD = 0;
/** Live playback type. */
@@ -80,6 +85,10 @@ public final class PlaybackMetrics implements Parcelable {
/** Clear key DRM type. */
public static final int DRM_TYPE_CLEARKEY = 6;
+ /** Unknown content type. */
+ // TODO: change the CONTENT_TYPE_ values
+ /** @hide */
+ public static final int CONTENT_TYPE_UNKNOWN = 0;
/** Main contents. */
public static final int CONTENT_TYPE_MAIN = 0;
/** Advertisement contents. */
@@ -112,6 +121,7 @@ public final class PlaybackMetrics implements Parcelable {
/** @hide */
@IntDef(prefix = "PLAYBACK_TYPE_", value = {
+ PLAYBACK_TYPE_UNKNOWN,
PLAYBACK_TYPE_VOD,
PLAYBACK_TYPE_LIVE,
PLAYBACK_TYPE_OTHER
@@ -134,6 +144,7 @@ public final class PlaybackMetrics implements Parcelable {
/** @hide */
@IntDef(prefix = "CONTENT_TYPE_", value = {
+ CONTENT_TYPE_UNKNOWN,
CONTENT_TYPE_MAIN,
CONTENT_TYPE_AD,
CONTENT_TYPE_OTHER
@@ -158,6 +169,8 @@ public final class PlaybackMetrics implements Parcelable {
private final long mNetworkBytesRead;
private final long mLocalBytesRead;
private final long mNetworkTransferDurationMillis;
+ private final byte[] mDrmSessionId;
+ private final Bundle mExtras;
/**
* Creates a new PlaybackMetrics.
@@ -179,7 +192,9 @@ public final class PlaybackMetrics implements Parcelable {
int audioUnderrunCount,
long networkBytesRead,
long localBytesRead,
- long networkTransferDurationMillis) {
+ long networkTransferDurationMillis,
+ byte[] drmSessionId,
+ Bundle extras) {
this.mMediaDurationMillis = mediaDurationMillis;
this.mStreamSource = streamSource;
this.mStreamType = streamType;
@@ -196,6 +211,8 @@ public final class PlaybackMetrics implements Parcelable {
this.mNetworkBytesRead = networkBytesRead;
this.mLocalBytesRead = localBytesRead;
this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
+ this.mDrmSessionId = drmSessionId;
+ this.mExtras = extras.deepCopy();
}
/**
@@ -321,6 +338,12 @@ public final class PlaybackMetrics implements Parcelable {
return mNetworkTransferDurationMillis;
}
+ /** @hide */
+ @NonNull
+ public byte[] getDrmSessionId() {
+ return mDrmSessionId;
+ }
+
@Override
public String toString() {
return "PlaybackMetrics { "
@@ -339,6 +362,7 @@ public final class PlaybackMetrics implements Parcelable {
+ "networkBytesRead = " + mNetworkBytesRead + ", "
+ "localBytesRead = " + mLocalBytesRead + ", "
+ "networkTransferDurationMillis = " + mNetworkTransferDurationMillis
+ + "drmSessionId = " + Arrays.toString(mDrmSessionId)
+ " }";
}
@@ -361,7 +385,8 @@ public final class PlaybackMetrics implements Parcelable {
&& mAudioUnderrunCount == that.mAudioUnderrunCount
&& mNetworkBytesRead == that.mNetworkBytesRead
&& mLocalBytesRead == that.mLocalBytesRead
- && mNetworkTransferDurationMillis == that.mNetworkTransferDurationMillis;
+ && mNetworkTransferDurationMillis == that.mNetworkTransferDurationMillis
+ && Arrays.equals(mDrmSessionId, that.mDrmSessionId);
}
@Override
@@ -369,7 +394,7 @@ public final class PlaybackMetrics implements Parcelable {
return Objects.hash(mMediaDurationMillis, mStreamSource, mStreamType, mPlaybackType,
mDrmType, mContentType, mPlayerName, mPlayerVersion, mExperimentIds,
mVideoFramesPlayed, mVideoFramesDropped, mAudioUnderrunCount, mNetworkBytesRead,
- mLocalBytesRead, mNetworkTransferDurationMillis);
+ mLocalBytesRead, mNetworkTransferDurationMillis, mDrmSessionId);
}
@Override
@@ -377,6 +402,7 @@ public final class PlaybackMetrics implements Parcelable {
long flg = 0;
if (mPlayerName != null) flg |= 0x80;
if (mPlayerVersion != null) flg |= 0x100;
+ if (mExtras != null) flg |= 0x200;
dest.writeLong(flg);
dest.writeLong(mMediaDurationMillis);
dest.writeInt(mStreamSource);
@@ -386,6 +412,7 @@ public final class PlaybackMetrics implements Parcelable {
dest.writeInt(mContentType);
if (mPlayerName != null) dest.writeString(mPlayerName);
if (mPlayerVersion != null) dest.writeString(mPlayerVersion);
+ if (mExtras != null) dest.writeBundle(mExtras);
dest.writeLongArray(mExperimentIds);
dest.writeInt(mVideoFramesPlayed);
dest.writeInt(mVideoFramesDropped);
@@ -393,6 +420,8 @@ public final class PlaybackMetrics implements Parcelable {
dest.writeLong(mNetworkBytesRead);
dest.writeLong(mLocalBytesRead);
dest.writeLong(mNetworkTransferDurationMillis);
+ dest.writeInt(mDrmSessionId.length);
+ dest.writeByteArray(mDrmSessionId);
}
@Override
@@ -411,6 +440,7 @@ public final class PlaybackMetrics implements Parcelable {
int contentType = in.readInt();
String playerName = (flg & 0x80) == 0 ? null : in.readString();
String playerVersion = (flg & 0x100) == 0 ? null : in.readString();
+ Bundle extras = (flg & 0x200) == 0 ? null : in.readBundle();
long[] experimentIds = in.createLongArray();
int videoFramesPlayed = in.readInt();
int videoFramesDropped = in.readInt();
@@ -418,6 +448,9 @@ public final class PlaybackMetrics implements Parcelable {
long networkBytesRead = in.readLong();
long localBytesRead = in.readLong();
long networkTransferDurationMillis = in.readLong();
+ int drmSessionIdLen = in.readInt();
+ byte[] drmSessionId = new byte[drmSessionIdLen];
+ in.readByteArray(drmSessionId);
this.mMediaDurationMillis = mediaDurationMillis;
this.mStreamSource = streamSource;
@@ -435,6 +468,8 @@ public final class PlaybackMetrics implements Parcelable {
this.mNetworkBytesRead = networkBytesRead;
this.mLocalBytesRead = localBytesRead;
this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
+ this.mDrmSessionId = drmSessionId;
+ this.mExtras = extras;
}
public static final @NonNull Parcelable.Creator Should be used by support library only.
+ * @hide
+ */
+ public @NonNull Builder setExtras(@NonNull Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull PlaybackMetrics build() {
@@ -626,7 +681,9 @@ public final class PlaybackMetrics implements Parcelable {
mAudioUnderrunCount,
mNetworkBytesRead,
mLocalBytesRead,
- mNetworkTransferDurationMillis);
+ mNetworkTransferDurationMillis,
+ mDrmSessionId,
+ mExtras);
return o;
}
diff --git a/media/java/android/media/metrics/PlaybackSession.java b/media/java/android/media/metrics/PlaybackSession.java
index 4ee8a45fe1960..272fd9bd55767 100644
--- a/media/java/android/media/metrics/PlaybackSession.java
+++ b/media/java/android/media/metrics/PlaybackSession.java
@@ -29,6 +29,7 @@ import java.util.Objects;
public final class PlaybackSession implements AutoCloseable {
private final @NonNull String mId;
private final @NonNull MediaMetricsManager mManager;
+ private final @NonNull LogSessionId mLogSessionId;
private boolean mClosed = false;
/**
@@ -41,6 +42,7 @@ public final class PlaybackSession implements AutoCloseable {
mManager = manager;
AnnotationValidations.validate(NonNull.class, null, mId);
AnnotationValidations.validate(NonNull.class, null, mManager);
+ mLogSessionId = new LogSessionId(mId);
}
/**
@@ -79,9 +81,16 @@ public final class PlaybackSession implements AutoCloseable {
}
public @NonNull String getId() {
+ // TODO: remove this method and use getSessionId();
return mId;
}
+ /** @hide */
+ public @NonNull LogSessionId getSessionId() {
+ // TODO: remove getId() and use this method;
+ return mLogSessionId;
+ }
+
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
diff --git a/media/java/android/media/metrics/PlaybackStateEvent.java b/media/java/android/media/metrics/PlaybackStateEvent.java
index 8ca5b75dec988..dea8c1db71def 100644
--- a/media/java/android/media/metrics/PlaybackStateEvent.java
+++ b/media/java/android/media/metrics/PlaybackStateEvent.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -136,9 +137,11 @@ public final class PlaybackStateEvent extends Event implements Parcelable {
*/
public PlaybackStateEvent(
int state,
- long timeSinceCreatedMillis) {
+ long timeSinceCreatedMillis,
+ Bundle extras) {
this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
this.mState = state;
+ this.mExtras = extras.deepCopy();
}
/**
@@ -174,8 +177,12 @@ public final class PlaybackStateEvent extends Event implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
+ byte flg = 0;
+ if (mExtras != null) flg |= 0x1;
+ dest.writeByte(flg);
dest.writeInt(mState);
dest.writeLong(mTimeSinceCreatedMillis);
+ if (mExtras != null) dest.writeBundle(mExtras);
}
@Override
@@ -185,11 +192,14 @@ public final class PlaybackStateEvent extends Event implements Parcelable {
/** @hide */
/* package-private */ PlaybackStateEvent(@NonNull Parcel in) {
+ byte flg = in.readByte();
int state = in.readInt();
long timeSinceCreatedMillis = in.readLong();
+ Bundle extras = (flg & 0x1) == 0 ? null : in.readBundle();
this.mState = state;
this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
+ this.mExtras = extras;
}
public static final @NonNull Parcelable.Creator Should be used by support library only.
+ * @hide
+ */
+ public @NonNull Builder setExtras(@NonNull Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
/** Builds the instance. */
public @NonNull PlaybackStateEvent build() {
PlaybackStateEvent o = new PlaybackStateEvent(
mState,
- mTimeSinceCreatedMillis);
+ mTimeSinceCreatedMillis,
+ mExtras);
return o;
}
}
diff --git a/media/java/android/media/metrics/RecordingSession.java b/media/java/android/media/metrics/RecordingSession.java
new file mode 100644
index 0000000000000..541d129604ad3
--- /dev/null
+++ b/media/java/android/media/metrics/RecordingSession.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 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.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.util.AnnotationValidations;
+
+import java.util.Objects;
+
+/**
+ * An instances of this class represents a session of media recording.
+ * @hide
+ */
+public final class RecordingSession implements AutoCloseable {
+ private final @NonNull String mId;
+ private final @NonNull MediaMetricsManager mManager;
+ private final @NonNull LogSessionId mLogSessionId;
+ private boolean mClosed = false;
+
+ /** @hide */
+ public RecordingSession(@NonNull String id, @NonNull MediaMetricsManager manager) {
+ mId = id;
+ mManager = manager;
+ AnnotationValidations.validate(NonNull.class, null, mId);
+ AnnotationValidations.validate(NonNull.class, null, mManager);
+ mLogSessionId = new LogSessionId(mId);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ RecordingSession that = (RecordingSession) o;
+ return Objects.equals(mId, that.mId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mId);
+ }
+
+ @Override
+ public void close() {
+ mClosed = true;
+ }
+}
diff --git a/media/java/android/media/metrics/TrackChangeEvent.java b/media/java/android/media/metrics/TrackChangeEvent.java
index ef25357457c55..aa519782ec80b 100644
--- a/media/java/android/media/metrics/TrackChangeEvent.java
+++ b/media/java/android/media/metrics/TrackChangeEvent.java
@@ -16,10 +16,12 @@
package android.media.metrics;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -65,9 +67,10 @@ public final class TrackChangeEvent extends Event implements Parcelable {
private final @Nullable String mLanguage;
private final @Nullable String mLanguageRegion;
private final int mChannelCount;
- private final int mSampleRate;
+ private final int mAudioSampleRate;
private final int mWidth;
private final int mHeight;
+ private final float mVideoFrameRate;
@@ -99,6 +102,7 @@ public final class TrackChangeEvent extends Event implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface TrackType {}
+ // TODO: remove this constructor. Use the private one below.
public TrackChangeEvent(
int state,
int reason,
@@ -125,9 +129,45 @@ public final class TrackChangeEvent extends Event implements Parcelable {
this.mLanguage = language;
this.mLanguageRegion = languageRegion;
this.mChannelCount = channelCount;
- this.mSampleRate = sampleRate;
+ this.mAudioSampleRate = sampleRate;
this.mWidth = width;
this.mHeight = height;
+ this.mVideoFrameRate = -1;
+ }
+
+ private TrackChangeEvent(
+ int state,
+ int reason,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecName,
+ int bitrate,
+ long timeSinceCreatedMillis,
+ int type,
+ @Nullable String language,
+ @Nullable String languageRegion,
+ int channelCount,
+ int sampleRate,
+ int width,
+ int height,
+ float videoFrameRate,
+ @Nullable Bundle extras) {
+ this.mState = state;
+ this.mReason = reason;
+ this.mContainerMimeType = containerMimeType;
+ this.mSampleMimeType = sampleMimeType;
+ this.mCodecName = codecName;
+ this.mBitrate = bitrate;
+ this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
+ this.mType = type;
+ this.mLanguage = language;
+ this.mLanguageRegion = languageRegion;
+ this.mChannelCount = channelCount;
+ this.mAudioSampleRate = sampleRate;
+ this.mWidth = width;
+ this.mHeight = height;
+ this.mVideoFrameRate = videoFrameRate;
+ this.mExtras = extras.deepCopy();
}
/**
@@ -223,7 +263,7 @@ public final class TrackChangeEvent extends Event implements Parcelable {
*/
@IntRange(from = -1, to = Integer.MAX_VALUE)
public int getSampleRate() {
- return mSampleRate;
+ return mAudioSampleRate;
}
/**
@@ -244,6 +284,16 @@ public final class TrackChangeEvent extends Event implements Parcelable {
return mHeight;
}
+ /**
+ * Gets video frame rate.
+ * @return the video frame rate, or -1 if unknown.
+ * @hide
+ */
+ @FloatRange(from = -1, to = Float.MAX_VALUE)
+ public float getVideoFrameRate() {
+ return mVideoFrameRate;
+ }
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
int flg = 0;
@@ -252,6 +302,7 @@ public final class TrackChangeEvent extends Event implements Parcelable {
if (mCodecName != null) flg |= 0x10;
if (mLanguage != null) flg |= 0x100;
if (mLanguageRegion != null) flg |= 0x200;
+ if (mExtras != null) flg |= 0x400;
dest.writeInt(flg);
dest.writeInt(mState);
dest.writeInt(mReason);
@@ -264,9 +315,11 @@ public final class TrackChangeEvent extends Event implements Parcelable {
if (mLanguage != null) dest.writeString(mLanguage);
if (mLanguageRegion != null) dest.writeString(mLanguageRegion);
dest.writeInt(mChannelCount);
- dest.writeInt(mSampleRate);
+ dest.writeInt(mAudioSampleRate);
dest.writeInt(mWidth);
dest.writeInt(mHeight);
+ dest.writeFloat(mVideoFrameRate);
+ if (mExtras != null) dest.writeBundle(mExtras);
}
@Override
@@ -291,6 +344,8 @@ public final class TrackChangeEvent extends Event implements Parcelable {
int sampleRate = in.readInt();
int width = in.readInt();
int height = in.readInt();
+ float videoFrameRate = in.readFloat();
+ Bundle extras = (flg & 0x400) == 0 ? null : in.readBundle();
this.mState = state;
this.mReason = reason;
@@ -303,9 +358,11 @@ public final class TrackChangeEvent extends Event implements Parcelable {
this.mLanguage = language;
this.mLanguageRegion = languageRegion;
this.mChannelCount = channelCount;
- this.mSampleRate = sampleRate;
+ this.mAudioSampleRate = sampleRate;
this.mWidth = width;
this.mHeight = height;
+ this.mVideoFrameRate = videoFrameRate;
+ this.mExtras = extras;
}
public static final @NonNull Parcelable.Creator Should be used by support library only.
+ * @hide
+ */
+ public @NonNull Builder setExtras(@NonNull Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull TrackChangeEvent build() {
checkNotUsed();
@@ -557,9 +641,11 @@ public final class TrackChangeEvent extends Event implements Parcelable {
mLanguage,
mLanguageRegion,
mChannelCount,
- mSampleRate,
+ mAudioSampleRate,
mWidth,
- mHeight);
+ mHeight,
+ mVideoFrameRate,
+ mExtras);
return o;
}
diff --git a/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
index 639dda6f8981c..23195bbe5d7eb 100644
--- a/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
+++ b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
@@ -93,14 +93,23 @@ public final class MediaMetricsManagerService extends SystemService {
StatsLog.write(statsEvent);
}
- @Override
- public String getSessionId(int userId) {
+ private String getSessionIdInternal(int userId) {
byte[] byteId = new byte[16]; // 128 bits
mSecureRandom.nextBytes(byteId);
String id = Base64.encodeToString(byteId, Base64.DEFAULT);
return id;
}
+ @Override
+ public String getPlaybackSessionId(int userId) {
+ return getSessionIdInternal(userId);
+ }
+
+ @Override
+ public String getRecordingSessionId(int userId) {
+ return getSessionIdInternal(userId);
+ }
+
@Override
public void reportPlaybackErrorEvent(
String sessionId, PlaybackErrorEvent event, int userId) {