diff --git a/core/api/current.txt b/core/api/current.txt index 8b9562dcd3784..233be5a325efe 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -27130,6 +27130,39 @@ package android.media.tv { method public void onTuned(android.net.Uri); } + public final class TvRecordingInfo implements android.os.Parcelable { + ctor public TvRecordingInfo(@NonNull String, long, long, int, @NonNull String, @NonNull String, long, long, @NonNull android.net.Uri, @Nullable android.net.Uri, @NonNull java.util.List, @Nullable android.net.Uri, long, long); + method public int describeContents(); + method @NonNull public android.net.Uri getChannelUri(); + method @NonNull public java.util.List getContentRatings(); + method @NonNull public String getDescription(); + method @NonNull public long getEndPaddingMillis(); + method @NonNull public String getName(); + method @Nullable public android.net.Uri getProgramUri(); + method @IntRange(from=0xffffffff) @NonNull public long getRecordingDurationMillis(); + method @NonNull public String getRecordingId(); + method @IntRange(from=0xffffffff) @NonNull public long getRecordingStartTimeMillis(); + method @Nullable public android.net.Uri getRecordingUri(); + method @NonNull public int getRepeatDays(); + method @IntRange(from=0) @NonNull public long getScheduledDurationMillis(); + method @IntRange(from=0) @NonNull public long getScheduledStartTimeMillis(); + method @NonNull public long getStartPaddingMillis(); + method public void setDescription(@NonNull String); + method public void setName(@NonNull String); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int FRIDAY = 32; // 0x20 + field public static final int MONDAY = 2; // 0x2 + field public static final int RECORDING_ALL = 3; // 0x3 + field public static final int RECORDING_IN_PROGRESS = 2; // 0x2 + field public static final int RECORDING_SCHEDULED = 1; // 0x1 + field public static final int SATURDAY = 64; // 0x40 + field public static final int SUNDAY = 1; // 0x1 + field public static final int THURSDAY = 16; // 0x10 + field public static final int TUESDAY = 4; // 0x4 + field public static final int WEDNESDAY = 8; // 0x8 + } + public final class TvTrackInfo implements android.os.Parcelable { method public int describeContents(); method public int getAudioChannelCount(); @@ -27371,8 +27404,11 @@ package android.media.tv.interactive { method @CallSuper public void requestStopRecording(@NonNull String); method @CallSuper public void requestStreamVolume(); method @CallSuper public void requestTrackInfoList(); + method @CallSuper public void requestTvRecordingInfo(@NonNull String); + method @CallSuper public void requestTvRecordingInfoList(@NonNull int); method @CallSuper public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle); method @CallSuper public void setMediaViewEnabled(boolean); + method @CallSuper public void setTvRecordingInfo(@NonNull String, @NonNull android.media.tv.TvRecordingInfo); method @CallSuper public void setVideoBounds(@NonNull android.graphics.Rect); } @@ -27447,6 +27483,9 @@ package android.media.tv.interactive { method public void onRequestStopRecording(@NonNull String, @NonNull String); method public void onRequestStreamVolume(@NonNull String); method public void onRequestTrackInfoList(@NonNull String); + method public void onRequestTvRecordingInfo(@NonNull String, @NonNull String); + method public void onRequestTvRecordingInfoList(@NonNull String, @NonNull int); + method public void onSetTvRecordingInfo(@NonNull String, @NonNull String, @NonNull android.media.tv.TvRecordingInfo); method public void onSetVideoBounds(@NonNull String, @NonNull android.graphics.Rect); method public void onStateChanged(@NonNull String, int, int); method public void onTeletextAppStateChanged(@NonNull String, int); diff --git a/media/java/android/media/tv/TvRecordingInfo.java b/media/java/android/media/tv/TvRecordingInfo.java index 8de42f32a75d9..60ceb83941594 100644 --- a/media/java/android/media/tv/TvRecordingInfo.java +++ b/media/java/android/media/tv/TvRecordingInfo.java @@ -17,6 +17,7 @@ package android.media.tv; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.Uri; @@ -25,9 +26,13 @@ import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.List; + /** - @hide + * This class is used to describe the meta information for a TV recording. It can be retrieved by + * the {@link android.media.tv.interactive.TvInteractiveAppService} by using getTvRecordingInfo + * or getTvRecordingInfoList. It can then be updated to the TV app using setTvRecordingInfo. */ public final class TvRecordingInfo implements Parcelable { /* @@ -54,105 +59,256 @@ public final class TvRecordingInfo implements Parcelable { }) public @interface TvRecordingListType {} + public static final int SUNDAY = 1; + public static final int MONDAY = 1 << 1; + public static final int TUESDAY = 1 << 2; + public static final int WEDNESDAY = 1 << 3; + public static final int THURSDAY = 1 << 4; + public static final int FRIDAY = 1 << 5; + public static final int SATURDAY = 1 << 6; + + /** + * The days of the week defined in {@link java.time.DayOfWeek} are not used here because they + * map to integers that increment by 1. The intended use case in {@link #getRepeatDays()} uses + * a bitfield, which requires integers that map to 2^n. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY}) + public @interface DaysOfWeek {} + private String mRecordingId; - private int mStartPadding; - private int mEndPadding; + private long mStartPaddingMillis; + private long mEndPaddingMillis; private int mRepeatDays; private String mName; private String mDescription; - private int mScheduledStartTime; - private int mScheduledDuration; + private long mScheduledStartTimeMillis; + private long mScheduledDurationMillis; private Uri mChannelUri; - private Uri mProgramId; - private List mParentalRatings; - private String mRecordingUri; - private int mRecordingStartTime; - private int mRecordingDuration; + private Uri mProgramUri; + private List mContentRatings; + private Uri mRecordingUri; + private long mRecordingStartTimeMillis; + private long mRecordingDurationMillis; public TvRecordingInfo( - @NonNull String recordingId, @NonNull int startPadding, @NonNull int endPadding, - @NonNull int repeatDays, @NonNull int scheduledStartTime, - @NonNull int scheduledDuration, @NonNull Uri channelUri, @Nullable Uri programId, - @NonNull List parentalRatings, @NonNull String recordingUri, - @NonNull int recordingStartTime, @NonNull int recordingDuration) { + @NonNull String recordingId, long startPadding, long endPadding, int repeatDays, + @NonNull String name, @NonNull String description, long scheduledStartTime, + long scheduledDuration, @NonNull Uri channelUri, @Nullable Uri programUri, + @NonNull List contentRatings, @Nullable Uri recordingUri, + long recordingStartTime, long recordingDuration) { mRecordingId = recordingId; - mStartPadding = startPadding; - mEndPadding = endPadding; + mStartPaddingMillis = startPadding; + mEndPaddingMillis = endPadding; mRepeatDays = repeatDays; - mScheduledStartTime = scheduledStartTime; - mScheduledDuration = scheduledDuration; + mName = name; + mDescription = description; + mScheduledStartTimeMillis = scheduledStartTime; + mScheduledDurationMillis = scheduledDuration; mChannelUri = channelUri; - mScheduledDuration = scheduledDuration; - mChannelUri = channelUri; - mProgramId = programId; - mParentalRatings = parentalRatings; + mProgramUri = programUri; + mContentRatings = contentRatings; mRecordingUri = recordingUri; - mRecordingStartTime = recordingStartTime; - mRecordingDuration = recordingDuration; + mRecordingStartTimeMillis = recordingStartTime; + mRecordingDurationMillis = recordingDuration; } + + /** + * Returns the ID of this recording. This ID is created and maintained by the TV app. + */ @NonNull public String getRecordingId() { return mRecordingId; } + + /** + * Returns the start padding duration of this recording in milliseconds since the epoch. + * + *

A positive value should cause the recording to start earlier than the specified time. + * This should cause the actual duration of the recording to increase. A negative value should + * cause the recording to start later than the specified time. This should cause the actual + * duration of the recording to decrease. + */ @NonNull - public int getStartPadding() { - return mStartPadding; + public long getStartPaddingMillis() { + return mStartPaddingMillis; } + + /** + * Returns the ending padding duration of this recording in milliseconds since the epoch. + * + *

A positive value should cause the recording to end later than the specified time. + * This should cause the actual duration of the recording to increase. A negative value should + * cause the recording to end earlier than the specified time. This should cause the actual + * duration of the recording to decrease. + */ @NonNull - public int getEndPadding() { - return mEndPadding; + public long getEndPaddingMillis() { + return mEndPaddingMillis; } + + /** + * Returns the days of the week for which this recording should be repeated for. + * + *

This information is represented in the form of a bitfield, with each bit + * representing the day which the recording should be repeated. + * + *

The bitfield corresponds to each day of the week with the following format: + *

    + *
  • {@link #SUNDAY} - 0x01 (00000001)
  • + *
  • {@link #MONDAY} - 0x02 (00000010)
  • + *
  • {@link #TUESDAY} - 0x04 (00000100)
  • + *
  • {@link #WEDNESDAY} - 0x08 (00001000)
  • + *
  • {@link #THURSDAY} - 0x10 (00010000)
  • + *
  • {@link #FRIDAY} - 0x20 (00100000)
  • + *
  • {@link #SATURDAY} - 0x40 (01000000)
  • + *
+ * + *

You can specify multiple days to repeat the recording by performing a bitwise 'OR' on the + * bitfield. For example, for a recording to repeat on Sunday and Mondays, this function should + * return 0x03 (00000011). + * + *

A value of 0x00 indicates that the recording will not be repeated. + * + *

This format comes from the Open IPTV Forum Release 2 Specification. It is described in Volume 5, section 7.10.1.1. + */ @NonNull + @DaysOfWeek public int getRepeatDays() { return mRepeatDays; } + + /** + * Returns the name of the scheduled recording. + * + *

This is set with {@link TvRecordingInfo#setName(String)} and sent to tv app with + * {@link android.media.tv.interactive.TvInteractiveAppService.Session#setTvRecordingInfo(String, TvRecordingInfo)} + */ @NonNull public String getName() { return mName; } - @NonNull - public void setName(String name) { + + /** + * Sets the name of the scheduled recording. + * + *

Updates to the {@link TvRecordingInfo} can be sent to the TV app with + * {@link android.media.tv.interactive.TvInteractiveAppService.Session#setTvRecordingInfo(String, TvRecordingInfo)} + */ + public void setName(@NonNull String name) { mName = name; } + + /** + * Returns the description of the scheduled recording. + * + *

This is set with {@link TvRecordingInfo#setDescription(String)} and sent to tv app with + * {@link android.media.tv.interactive.TvInteractiveAppService.Session#setTvRecordingInfo(String, TvRecordingInfo)} + */ @NonNull public String getDescription() { return mDescription; } - @NonNull - public void setDescription(String description) { + + /** + * Sets the description of the scheduled recording. + * + *

Updates to the {@link TvRecordingInfo} can be sent to the TV app with + * {@link android.media.tv.interactive.TvInteractiveAppService.Session#setTvRecordingInfo(String, TvRecordingInfo)} + */ + public void setDescription(@NonNull String description) { mDescription = description; } + + /** + * Returns the scheduled start time of the recording in milliseconds since the epoch. + */ + @IntRange(from = 0) @NonNull - public int getScheduledStartTime() { - return mScheduledStartTime; + public long getScheduledStartTimeMillis() { + return mScheduledStartTimeMillis; } + + /** + * Returns the scheduled duration of the recording in milliseconds since the epoch. + */ + @IntRange(from = 0) @NonNull - public int getScheduledDuration() { - return mScheduledDuration; + public long getScheduledDurationMillis() { + return mScheduledDurationMillis; } + + /** + * Returns the uri of the broadcast channel where the recording will take place. + */ @NonNull public Uri getChannelUri() { return mChannelUri; } + + /** + * Returns the uri of the scheduled program or series. + * + *

For recordings scheduled using scheduleRecording, this value may be null. A non-null + * programUri implies the started recording should be of that specific program, whereas a null + * programUri does not impose such a requirement and the recording can span across + * multiple TV programs. + */ @Nullable - public Uri getProgramId() { - return mProgramId; + public Uri getProgramUri() { + return mProgramUri; } + + /** + * Returns a list of content ratings for the program(s) in this recording. + * + *

Returns an empty list if no content rating information is available. + */ @NonNull - public List getParentalRatings() { - return mParentalRatings; + public List getContentRatings() { + return mContentRatings; } - @NonNull - public String getRecordingUri() { + + /** + * The uri of the recording in local storage. + * + *

Could be null in the event that the recording has not been completed. + */ + @Nullable + public Uri getRecordingUri() { return mRecordingUri; } + + /** + * The real start time of the recording, including any padding, in milliseconds since the epoch. + * + *

This may not be the same as the value of {@link #getScheduledStartTimeMillis()} due to a + * recording starting late, or due to start/end padding. + * + *

Returns -1 for recordings that have not yet started. + */ + @IntRange(from = -1) @NonNull - public int getRecordingStartTime() { - return mRecordingStartTime; + public long getRecordingStartTimeMillis() { + return mRecordingStartTimeMillis; } + + /** + * The real duration of the recording, including any padding, in milliseconds since the epoch. + * + *

This may not be the same as the value of {@link #getScheduledDurationMillis()} due to a + * recording starting late, or due to start/end padding. + * + *

Returns -1 for recordings that have not yet started. + */ + @IntRange(from = -1) @NonNull - public int getRecordingDuration() { - return mRecordingDuration; + public long getRecordingDurationMillis() { + return mRecordingDurationMillis; } @Override @@ -169,36 +325,42 @@ public final class TvRecordingInfo implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mRecordingId); - dest.writeInt(mStartPadding); - dest.writeInt(mEndPadding); + dest.writeLong(mStartPaddingMillis); + dest.writeLong(mEndPaddingMillis); dest.writeInt(mRepeatDays); dest.writeString(mName); dest.writeString(mDescription); - dest.writeInt(mScheduledStartTime); - dest.writeInt(mScheduledDuration); + dest.writeLong(mScheduledStartTimeMillis); + dest.writeLong(mScheduledDurationMillis); dest.writeString(mChannelUri == null ? null : mChannelUri.toString()); - dest.writeString(mProgramId == null ? null : mProgramId.toString()); - dest.writeStringList(mParentalRatings); - dest.writeString(mRecordingUri); - dest.writeInt(mRecordingDuration); - dest.writeInt(mRecordingStartTime); + dest.writeString(mProgramUri == null ? null : mProgramUri.toString()); + List flattenedContentRatings = new ArrayList(); + mContentRatings.forEach((rating) -> flattenedContentRatings.add(rating.flattenToString())); + dest.writeList(mContentRatings); + dest.writeString(mRecordingUri == null ? null : mProgramUri.toString()); + dest.writeLong(mRecordingDurationMillis); + dest.writeLong(mRecordingStartTimeMillis); } private TvRecordingInfo(Parcel in) { mRecordingId = in.readString(); - mStartPadding = in.readInt(); - mEndPadding = in.readInt(); + mStartPaddingMillis = in.readLong(); + mEndPaddingMillis = in.readLong(); mRepeatDays = in.readInt(); mName = in.readString(); mDescription = in.readString(); - mScheduledStartTime = in.readInt(); - mScheduledDuration = in.readInt(); + mScheduledStartTimeMillis = in.readLong(); + mScheduledDurationMillis = in.readLong(); mChannelUri = Uri.parse(in.readString()); - mProgramId = Uri.parse(in.readString()); - in.readStringList(mParentalRatings); - mRecordingUri = in.readString(); - mRecordingDuration = in.readInt(); - mRecordingStartTime = in.readInt(); + mProgramUri = Uri.parse(in.readString()); + mContentRatings = new ArrayList(); + List flattenedContentRatings = new ArrayList(); + in.readStringList(flattenedContentRatings); + flattenedContentRatings.forEach((rating) -> + mContentRatings.add(TvContentRating.unflattenFromString(rating))); + mRecordingUri = Uri.parse(in.readString()); + mRecordingDurationMillis = in.readLong(); + mRecordingStartTimeMillis = in.readLong(); } diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java index be2c16c90b9e1..d1777cc8cbeed 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java @@ -1219,13 +1219,15 @@ public abstract class TvInteractiveAppService extends Service { } /** - * Sets the recording info for the specified recording + * Sets the recording info for the specified recording. * - * @hide + * @param recordingId The ID of the recording to set the info for. This is provided by the + * TV app in {@link TvInteractiveAppView#notifyRecordingStarted(String)} + * @param recordingInfo The {@link TvRecordingInfo} to set to the recording. */ @CallSuper - public void setTvRecordingInfo(@NonNull String recordingId, - @NonNull TvRecordingInfo recordingInfo) { + public void setTvRecordingInfo( + @NonNull String recordingId, @NonNull TvRecordingInfo recordingInfo) { executeOrPostRunnableOnMainThread(() -> { try { if (DEBUG) { @@ -1242,8 +1244,8 @@ public abstract class TvInteractiveAppService extends Service { /** * Gets the recording info for the specified recording - * - * @hide + * @param recordingId The ID of the recording to set the info for. This is provided by the + * TV app in {@link TvInteractiveAppView#notifyRecordingStarted(String)} */ @CallSuper public void requestTvRecordingInfo(@NonNull String recordingId) { @@ -1262,9 +1264,9 @@ public abstract class TvInteractiveAppService extends Service { } /** - * Gets the recording info list for the specified recording type + * Gets a list of {@link TvRecordingInfo} for the specified recording type. * - * @hide + * @param type The type of recording to retrieve. */ @CallSuper public void requestTvRecordingInfoList(@NonNull @TvRecordingInfo.TvRecordingListType diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java index af03bb86d3648..4a0144041f513 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java @@ -1055,6 +1055,47 @@ public class TvInteractiveAppView extends ViewGroup { @NonNull String algorithm, @NonNull String alias, @NonNull byte[] data) { } + /** + * This is called when {@link TvInteractiveAppService.Session#setTvRecordingInfo(String, + * TvRecordingInfo)} is called. + * + * @param iAppServiceId The ID of the TV interactive app service bound to this view. + * @param recordingId The ID of the recording to set the info for. This is provided by the + * TV app in {@link TvInteractiveAppView#notifyRecordingStarted(String)} + * @param recordingInfo The {@link TvRecordingInfo} to set to the recording. + */ + public void onSetTvRecordingInfo( + @NonNull String iAppServiceId, + @NonNull String recordingId, + @NonNull TvRecordingInfo recordingInfo) { + } + + /** + * This is called when + * {@link TvInteractiveAppService.Session#requestTvRecordingInfo(String)} is + * called. + * + * @param iAppServiceId The ID of the TV interactive app service bound to this view. + * @param recordingId The ID of the recording to get the info for. This is provided by the + * TV app in {@link TvInteractiveAppView#notifyRecordingStarted(String)} + */ + public void onRequestTvRecordingInfo( + @NonNull String iAppServiceId, + @NonNull String recordingId) { + } + + /** + * This is called when + * {@link TvInteractiveAppService.Session#requestTvRecordingInfoList(int)} is + * called. + * + * @param iAppServiceId The ID of the TV interactive app service bound to this view. + * @param type The type of recording requested to retrieve. + */ + public void onRequestTvRecordingInfoList( + @NonNull String iAppServiceId, + @NonNull @TvRecordingInfo.TvRecordingListType int type) { + } } /** @@ -1439,6 +1480,51 @@ public class TvInteractiveAppView extends ViewGroup { } } + @Override + public void onSetTvRecordingInfo( + Session session, String recordingId, TvRecordingInfo recordingInfo) { + if (DEBUG) { + Log.d(TAG, "onSetRecordingInfo"); + } + if (this != mSessionCallback) { + Log.w(TAG, "onSetRecordingInfo - session not created"); + return; + } + if (mCallback != null) { + mCallback.onSetTvRecordingInfo(mIAppServiceId, recordingId, recordingInfo); + } + } + + @Override + public void onRequestTvRecordingInfo(Session session, + String recordingId) { + if (DEBUG) { + Log.d(TAG, "onRequestRecordingInfo"); + } + if (this != mSessionCallback) { + Log.w(TAG, "onRequestRecordingInfo - session not created"); + return; + } + if (mCallback != null) { + mCallback.onRequestTvRecordingInfo(mIAppServiceId, recordingId); + } + } + + @Override + public void onRequestTvRecordingInfoList(Session session, + int type) { + if (DEBUG) { + Log.d(TAG, "onRequestRecordingInfoList"); + } + if (this != mSessionCallback) { + Log.w(TAG, "onRequestRecordingInfoList - session not created"); + return; + } + if (mCallback != null) { + mCallback.onRequestTvRecordingInfoList(mIAppServiceId, type); + } + } + @Override public void onRequestSigning( Session session, String id, String algorithm, String alias, byte[] data) {