blob: dd744f803f89c0c978311082cd2cfbf05963fedd [file] [log] [blame]
/*
* Copyright (C) 2016 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 com.android.tv.dvr;
import static android.media.tv.TvContract.RecordedPrograms;
import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.media.tv.TvContract;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.android.tv.common.R;
import com.android.tv.data.BaseProgram;
import com.android.tv.data.GenreItems;
import com.android.tv.data.InternalDataUtils;
import com.android.tv.util.Utils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* Immutable instance of {@link android.media.tv.TvContract.RecordedPrograms}.
*/
@TargetApi(Build.VERSION_CODES.N)
public class RecordedProgram extends BaseProgram {
public static final int ID_NOT_SET = -1;
public final static String[] PROJECTION = {
// These are in exactly the order listed in RecordedPrograms
RecordedPrograms._ID,
RecordedPrograms.COLUMN_PACKAGE_NAME,
RecordedPrograms.COLUMN_INPUT_ID,
RecordedPrograms.COLUMN_CHANNEL_ID,
RecordedPrograms.COLUMN_TITLE,
RecordedPrograms.COLUMN_SEASON_DISPLAY_NUMBER,
RecordedPrograms.COLUMN_SEASON_TITLE,
RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER,
RecordedPrograms.COLUMN_EPISODE_TITLE,
RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS,
RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS,
RecordedPrograms.COLUMN_BROADCAST_GENRE,
RecordedPrograms.COLUMN_CANONICAL_GENRE,
RecordedPrograms.COLUMN_SHORT_DESCRIPTION,
RecordedPrograms.COLUMN_LONG_DESCRIPTION,
RecordedPrograms.COLUMN_VIDEO_WIDTH,
RecordedPrograms.COLUMN_VIDEO_HEIGHT,
RecordedPrograms.COLUMN_AUDIO_LANGUAGE,
RecordedPrograms.COLUMN_CONTENT_RATING,
RecordedPrograms.COLUMN_POSTER_ART_URI,
RecordedPrograms.COLUMN_THUMBNAIL_URI,
RecordedPrograms.COLUMN_SEARCHABLE,
RecordedPrograms.COLUMN_RECORDING_DATA_URI,
RecordedPrograms.COLUMN_RECORDING_DATA_BYTES,
RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS,
RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS,
RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1,
RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2,
RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3,
RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4,
RecordedPrograms.COLUMN_VERSION_NUMBER,
RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA,
};
public static RecordedProgram fromCursor(Cursor cursor) {
int index = 0;
Builder builder = builder()
.setId(cursor.getLong(index++))
.setPackageName(cursor.getString(index++))
.setInputId(cursor.getString(index++))
.setChannelId(cursor.getLong(index++))
.setTitle(cursor.getString(index++))
.setSeasonNumber(cursor.getString(index++))
.setSeasonTitle(cursor.getString(index++))
.setEpisodeNumber(cursor.getString(index++))
.setEpisodeTitle(cursor.getString(index++))
.setStartTimeUtcMillis(cursor.getLong(index++))
.setEndTimeUtcMillis(cursor.getLong(index++))
.setBroadcastGenres(cursor.getString(index++))
.setCanonicalGenres(cursor.getString(index++))
.setShortDescription(cursor.getString(index++))
.setLongDescription(cursor.getString(index++))
.setVideoWidth(cursor.getInt(index++))
.setVideoHeight(cursor.getInt(index++))
.setAudioLanguage(cursor.getString(index++))
.setContentRating(cursor.getString(index++))
.setPosterArtUri(cursor.getString(index++))
.setThumbnailUri(cursor.getString(index++))
.setSearchable(cursor.getInt(index++) == 1)
.setDataUri(cursor.getString(index++))
.setDataBytes(cursor.getLong(index++))
.setDurationMillis(cursor.getLong(index++))
.setExpireTimeUtcMillis(cursor.getLong(index++))
.setInternalProviderFlag1(cursor.getInt(index++))
.setInternalProviderFlag2(cursor.getInt(index++))
.setInternalProviderFlag3(cursor.getInt(index++))
.setInternalProviderFlag4(cursor.getInt(index++))
.setVersionNumber(cursor.getInt(index++));
if (Utils.isInBundledPackageSet(builder.mPackageName)) {
InternalDataUtils.deserializeInternalProviderData(cursor.getBlob(index), builder);
}
return builder.build();
}
public static ContentValues toValues(RecordedProgram recordedProgram) {
ContentValues values = new ContentValues();
if (recordedProgram.mId != ID_NOT_SET) {
values.put(RecordedPrograms._ID, recordedProgram.mId);
}
values.put(RecordedPrograms.COLUMN_INPUT_ID, recordedProgram.mInputId);
values.put(RecordedPrograms.COLUMN_CHANNEL_ID, recordedProgram.mChannelId);
values.put(RecordedPrograms.COLUMN_TITLE, recordedProgram.mTitle);
values.put(RecordedPrograms.COLUMN_SEASON_DISPLAY_NUMBER, recordedProgram.mSeasonNumber);
values.put(RecordedPrograms.COLUMN_SEASON_TITLE, recordedProgram.mSeasonTitle);
values.put(RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER, recordedProgram.mEpisodeNumber);
values.put(RecordedPrograms.COLUMN_EPISODE_TITLE, recordedProgram.mTitle);
values.put(RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS,
recordedProgram.mStartTimeUtcMillis);
values.put(RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS, recordedProgram.mEndTimeUtcMillis);
values.put(RecordedPrograms.COLUMN_BROADCAST_GENRE,
safeEncode(recordedProgram.mBroadcastGenres));
values.put(RecordedPrograms.COLUMN_CANONICAL_GENRE,
safeEncode(recordedProgram.mCanonicalGenres));
values.put(RecordedPrograms.COLUMN_SHORT_DESCRIPTION, recordedProgram.mShortDescription);
values.put(RecordedPrograms.COLUMN_LONG_DESCRIPTION, recordedProgram.mLongDescription);
if (recordedProgram.mVideoWidth == 0) {
values.putNull(RecordedPrograms.COLUMN_VIDEO_WIDTH);
} else {
values.put(RecordedPrograms.COLUMN_VIDEO_WIDTH, recordedProgram.mVideoWidth);
}
if (recordedProgram.mVideoHeight == 0) {
values.putNull(RecordedPrograms.COLUMN_VIDEO_HEIGHT);
} else {
values.put(RecordedPrograms.COLUMN_VIDEO_HEIGHT, recordedProgram.mVideoHeight);
}
values.put(RecordedPrograms.COLUMN_AUDIO_LANGUAGE, recordedProgram.mAudioLanguage);
values.put(RecordedPrograms.COLUMN_CONTENT_RATING, recordedProgram.mContentRating);
values.put(RecordedPrograms.COLUMN_POSTER_ART_URI, recordedProgram.mPosterArtUri);
values.put(RecordedPrograms.COLUMN_THUMBNAIL_URI, recordedProgram.mThumbnailUri);
values.put(RecordedPrograms.COLUMN_SEARCHABLE, recordedProgram.mSearchable ? 1 : 0);
values.put(RecordedPrograms.COLUMN_RECORDING_DATA_URI,
safeToString(recordedProgram.mDataUri));
values.put(RecordedPrograms.COLUMN_RECORDING_DATA_BYTES, recordedProgram.mDataBytes);
values.put(RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS,
recordedProgram.mDurationMillis);
values.put(RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS,
recordedProgram.mExpireTimeUtcMillis);
values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA,
InternalDataUtils.serializeInternalProviderData(recordedProgram));
values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1,
recordedProgram.mInternalProviderFlag1);
values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2,
recordedProgram.mInternalProviderFlag2);
values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3,
recordedProgram.mInternalProviderFlag3);
values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4,
recordedProgram.mInternalProviderFlag4);
values.put(RecordedPrograms.COLUMN_VERSION_NUMBER, recordedProgram.mVersionNumber);
return values;
}
public static class Builder{
private long mId = ID_NOT_SET;
private String mPackageName;
private String mInputId;
private long mChannelId;
private String mTitle;
private String mSeriesId;
private String mSeasonNumber;
private String mSeasonTitle;
private String mEpisodeNumber;
private String mEpisodeTitle;
private long mStartTimeUtcMillis;
private long mEndTimeUtcMillis;
private String[] mBroadcastGenres;
private String[] mCanonicalGenres;
private String mShortDescription;
private String mLongDescription;
private int mVideoWidth;
private int mVideoHeight;
private String mAudioLanguage;
private String mContentRating;
private String mPosterArtUri;
private String mThumbnailUri;
private boolean mSearchable = true;
private Uri mDataUri;
private long mDataBytes;
private long mDurationMillis;
private long mExpireTimeUtcMillis;
private int mInternalProviderFlag1;
private int mInternalProviderFlag2;
private int mInternalProviderFlag3;
private int mInternalProviderFlag4;
private int mVersionNumber;
public Builder setId(long id) {
mId = id;
return this;
}
public Builder setPackageName(String packageName) {
mPackageName = packageName;
return this;
}
public Builder setInputId(String inputId) {
mInputId = inputId;
return this;
}
public Builder setChannelId(long channelId) {
mChannelId = channelId;
return this;
}
public Builder setTitle(String title) {
mTitle = title;
return this;
}
public Builder setSeriesId(String seriesId) {
mSeriesId = seriesId;
return this;
}
public Builder setSeasonNumber(String seasonNumber) {
mSeasonNumber = seasonNumber;
return this;
}
public Builder setSeasonTitle(String seasonTitle) {
mSeasonTitle = seasonTitle;
return this;
}
public Builder setEpisodeNumber(String episodeNumber) {
mEpisodeNumber = episodeNumber;
return this;
}
public Builder setEpisodeTitle(String episodeTitle) {
mEpisodeTitle = episodeTitle;
return this;
}
public Builder setStartTimeUtcMillis(long startTimeUtcMillis) {
mStartTimeUtcMillis = startTimeUtcMillis;
return this;
}
public Builder setEndTimeUtcMillis(long endTimeUtcMillis) {
mEndTimeUtcMillis = endTimeUtcMillis;
return this;
}
public Builder setBroadcastGenres(String broadcastGenres) {
if (TextUtils.isEmpty(broadcastGenres)) {
mBroadcastGenres = null;
return this;
}
return setBroadcastGenres(TvContract.Programs.Genres.decode(broadcastGenres));
}
private Builder setBroadcastGenres(String[] broadcastGenres) {
mBroadcastGenres = broadcastGenres;
return this;
}
public Builder setCanonicalGenres(String canonicalGenres) {
if (TextUtils.isEmpty(canonicalGenres)) {
mCanonicalGenres = null;
return this;
}
return setCanonicalGenres(TvContract.Programs.Genres.decode(canonicalGenres));
}
private Builder setCanonicalGenres(String[] canonicalGenres) {
mCanonicalGenres = canonicalGenres;
return this;
}
public Builder setShortDescription(String shortDescription) {
mShortDescription = shortDescription;
return this;
}
public Builder setLongDescription(String longDescription) {
mLongDescription = longDescription;
return this;
}
public Builder setVideoWidth(int videoWidth) {
mVideoWidth = videoWidth;
return this;
}
public Builder setVideoHeight(int videoHeight) {
mVideoHeight = videoHeight;
return this;
}
public Builder setAudioLanguage(String audioLanguage) {
mAudioLanguage = audioLanguage;
return this;
}
public Builder setContentRating(String contentRating) {
mContentRating = contentRating;
return this;
}
private Uri toUri(String uriString) {
try {
return uriString == null ? null : Uri.parse(uriString);
} catch (Exception e) {
return null;
}
}
public Builder setPosterArtUri(String posterArtUri) {
mPosterArtUri = posterArtUri;
return this;
}
public Builder setThumbnailUri(String thumbnailUri) {
mThumbnailUri = thumbnailUri;
return this;
}
public Builder setSearchable(boolean searchable) {
mSearchable = searchable;
return this;
}
public Builder setDataUri(String dataUri) {
return setDataUri(toUri(dataUri));
}
public Builder setDataUri(Uri dataUri) {
mDataUri = dataUri;
return this;
}
public Builder setDataBytes(long dataBytes) {
mDataBytes = dataBytes;
return this;
}
public Builder setDurationMillis(long durationMillis) {
mDurationMillis = durationMillis;
return this;
}
public Builder setExpireTimeUtcMillis(long expireTimeUtcMillis) {
mExpireTimeUtcMillis = expireTimeUtcMillis;
return this;
}
public Builder setInternalProviderFlag1(int internalProviderFlag1) {
mInternalProviderFlag1 = internalProviderFlag1;
return this;
}
public Builder setInternalProviderFlag2(int internalProviderFlag2) {
mInternalProviderFlag2 = internalProviderFlag2;
return this;
}
public Builder setInternalProviderFlag3(int internalProviderFlag3) {
mInternalProviderFlag3 = internalProviderFlag3;
return this;
}
public Builder setInternalProviderFlag4(int internalProviderFlag4) {
mInternalProviderFlag4 = internalProviderFlag4;
return this;
}
public Builder setVersionNumber(int versionNumber) {
mVersionNumber = versionNumber;
return this;
}
public RecordedProgram build() {
// Generate the series ID for the episodic program of other TV input.
if (TextUtils.isEmpty(mSeriesId)
&& !TextUtils.isEmpty(mEpisodeNumber)) {
setSeriesId(BaseProgram.generateSeriesId(mPackageName, mTitle));
}
return new RecordedProgram(mId, mPackageName, mInputId, mChannelId, mTitle, mSeriesId,
mSeasonNumber, mSeasonTitle, mEpisodeNumber, mEpisodeTitle, mStartTimeUtcMillis,
mEndTimeUtcMillis, mBroadcastGenres, mCanonicalGenres, mShortDescription,
mLongDescription, mVideoWidth, mVideoHeight, mAudioLanguage, mContentRating,
mPosterArtUri, mThumbnailUri, mSearchable, mDataUri, mDataBytes,
mDurationMillis, mExpireTimeUtcMillis, mInternalProviderFlag1,
mInternalProviderFlag2, mInternalProviderFlag3, mInternalProviderFlag4,
mVersionNumber);
}
}
public static Builder builder() { return new Builder(); }
public static Builder buildFrom(RecordedProgram orig) {
return builder()
.setId(orig.getId())
.setPackageName(orig.getPackageName())
.setInputId(orig.getInputId())
.setChannelId(orig.getChannelId())
.setTitle(orig.getTitle())
.setSeriesId(orig.getSeriesId())
.setSeasonNumber(orig.getSeasonNumber())
.setSeasonTitle(orig.getSeasonTitle())
.setEpisodeNumber(orig.getEpisodeNumber())
.setEpisodeTitle(orig.getEpisodeTitle())
.setStartTimeUtcMillis(orig.getStartTimeUtcMillis())
.setEndTimeUtcMillis(orig.getEndTimeUtcMillis())
.setBroadcastGenres(orig.getBroadcastGenres())
.setCanonicalGenres(orig.getCanonicalGenres())
.setShortDescription(orig.getDescription())
.setLongDescription(orig.getLongDescription())
.setVideoWidth(orig.getVideoWidth())
.setVideoHeight(orig.getVideoHeight())
.setAudioLanguage(orig.getAudioLanguage())
.setContentRating(orig.getContentRating())
.setPosterArtUri(orig.getPosterArtUri())
.setThumbnailUri(orig.getThumbnailUri())
.setSearchable(orig.isSearchable())
.setInternalProviderFlag1(orig.getInternalProviderFlag1())
.setInternalProviderFlag2(orig.getInternalProviderFlag2())
.setInternalProviderFlag3(orig.getInternalProviderFlag3())
.setInternalProviderFlag4(orig.getInternalProviderFlag4())
.setVersionNumber(orig.getVersionNumber());
}
public static final Comparator<RecordedProgram> START_TIME_THEN_ID_COMPARATOR =
new Comparator<RecordedProgram>() {
@Override
public int compare(RecordedProgram lhs, RecordedProgram rhs) {
int res =
Long.compare(lhs.getStartTimeUtcMillis(), rhs.getStartTimeUtcMillis());
if (res != 0) {
return res;
}
return Long.compare(lhs.mId, rhs.mId);
}
};
private static final long CLIPPED_THRESHOLD_MS = TimeUnit.MINUTES.toMillis(5);
private final long mId;
private final String mPackageName;
private final String mInputId;
private final long mChannelId;
private final String mTitle;
private final String mSeriesId;
private final String mSeasonNumber;
private final String mSeasonTitle;
private final String mEpisodeNumber;
private final String mEpisodeTitle;
private final long mStartTimeUtcMillis;
private final long mEndTimeUtcMillis;
private final String[] mBroadcastGenres;
private final String[] mCanonicalGenres;
private final String mShortDescription;
private final String mLongDescription;
private final int mVideoWidth;
private final int mVideoHeight;
private final String mAudioLanguage;
private final String mContentRating;
private final String mPosterArtUri;
private final String mThumbnailUri;
private final boolean mSearchable;
private final Uri mDataUri;
private final long mDataBytes;
private final long mDurationMillis;
private final long mExpireTimeUtcMillis;
private final int mInternalProviderFlag1;
private final int mInternalProviderFlag2;
private final int mInternalProviderFlag3;
private final int mInternalProviderFlag4;
private final int mVersionNumber;
private RecordedProgram(long id, String packageName, String inputId, long channelId,
String title, String seriesId, String seasonNumber, String seasonTitle,
String episodeNumber, String episodeTitle, long startTimeUtcMillis,
long endTimeUtcMillis, String[] broadcastGenres, String[] canonicalGenres,
String shortDescription, String longDescription, int videoWidth, int videoHeight,
String audioLanguage, String contentRating, String posterArtUri, String thumbnailUri,
boolean searchable, Uri dataUri, long dataBytes, long durationMillis,
long expireTimeUtcMillis, int internalProviderFlag1, int internalProviderFlag2,
int internalProviderFlag3, int internalProviderFlag4, int versionNumber) {
mId = id;
mPackageName = packageName;
mInputId = inputId;
mChannelId = channelId;
mTitle = title;
mSeriesId = seriesId;
mSeasonNumber = seasonNumber;
mSeasonTitle = seasonTitle;
mEpisodeNumber = episodeNumber;
mEpisodeTitle = episodeTitle;
mStartTimeUtcMillis = startTimeUtcMillis;
mEndTimeUtcMillis = endTimeUtcMillis;
mBroadcastGenres = broadcastGenres;
mCanonicalGenres = canonicalGenres;
mShortDescription = shortDescription;
mLongDescription = longDescription;
mVideoWidth = videoWidth;
mVideoHeight = videoHeight;
mAudioLanguage = audioLanguage;
mContentRating = contentRating;
mPosterArtUri = posterArtUri;
mThumbnailUri = thumbnailUri;
mSearchable = searchable;
mDataUri = dataUri;
mDataBytes = dataBytes;
mDurationMillis = durationMillis;
mExpireTimeUtcMillis = expireTimeUtcMillis;
mInternalProviderFlag1 = internalProviderFlag1;
mInternalProviderFlag2 = internalProviderFlag2;
mInternalProviderFlag3 = internalProviderFlag3;
mInternalProviderFlag4 = internalProviderFlag4;
mVersionNumber = versionNumber;
}
public String getAudioLanguage() {
return mAudioLanguage;
}
public String[] getBroadcastGenres() {
return mBroadcastGenres;
}
public String[] getCanonicalGenres() {
return mCanonicalGenres;
}
/**
* Returns array of canonical genre ID's for this recorded program.
*/
@Override
public int[] getCanonicalGenreIds() {
if (mCanonicalGenres == null) {
return null;
}
int[] genreIds = new int[mCanonicalGenres.length];
for (int i = 0; i < mCanonicalGenres.length; i++) {
genreIds[i] = GenreItems.getId(mCanonicalGenres[i]);
}
return genreIds;
}
@Override
public long getChannelId() {
return mChannelId;
}
public String getContentRating() {
return mContentRating;
}
public Uri getDataUri() {
return mDataUri;
}
public long getDataBytes() {
return mDataBytes;
}
@Override
public long getDurationMillis() {
return mDurationMillis;
}
@Override
public long getEndTimeUtcMillis() {
return mEndTimeUtcMillis;
}
@Override
public String getEpisodeNumber() {
return mEpisodeNumber;
}
public String getEpisodeTitle() {
return mEpisodeTitle;
}
@Override
public String getEpisodeDisplayTitle(Context context) {
if (!TextUtils.isEmpty(mEpisodeNumber)) {
String episodeTitle = mEpisodeTitle == null ? "" : mEpisodeTitle;
if (TextUtils.equals(mSeasonNumber, "0")) {
// Do not show "S0: ".
return String.format(context.getResources().getString(
R.string.display_episode_title_format_no_season_number),
mEpisodeNumber, episodeTitle);
} else {
return String.format(context.getResources().getString(
R.string.display_episode_title_format),
mSeasonNumber, mEpisodeNumber, episodeTitle);
}
}
return mEpisodeTitle;
}
@Nullable
@Override
public String getTitleWithEpisodeNumber(Context context) {
if (TextUtils.isEmpty(mTitle)) {
return mTitle;
}
if (TextUtils.isEmpty(mSeasonNumber) || mSeasonNumber.equals("0")) {
return TextUtils.isEmpty(mEpisodeNumber) ? mTitle : context.getString(
R.string.program_title_with_episode_number_no_season, mTitle, mEpisodeNumber);
} else {
return context.getString(R.string.program_title_with_episode_number, mTitle,
mSeasonNumber, mEpisodeNumber);
}
}
@Nullable
public String getEpisodeDisplayNumber(Context context) {
if (!TextUtils.isEmpty(mEpisodeNumber)) {
if (TextUtils.equals(mSeasonNumber, "0")) {
// Do not show "S0: ".
return String.format(context.getResources().getString(
R.string.display_episode_number_format_no_season_number), mEpisodeNumber);
} else {
return String.format(context.getResources().getString(
R.string.display_episode_number_format), mSeasonNumber, mEpisodeNumber);
}
}
return null;
}
public long getExpireTimeUtcMillis() {
return mExpireTimeUtcMillis;
}
public long getId() {
return mId;
}
public String getPackageName() {
return mPackageName;
}
public String getInputId() {
return mInputId;
}
public int getInternalProviderFlag1() {
return mInternalProviderFlag1;
}
public int getInternalProviderFlag2() {
return mInternalProviderFlag2;
}
public int getInternalProviderFlag3() {
return mInternalProviderFlag3;
}
public int getInternalProviderFlag4() {
return mInternalProviderFlag4;
}
@Override
public String getDescription() {
return mShortDescription;
}
@Override
public String getLongDescription() {
return mLongDescription;
}
@Override
public String getPosterArtUri() {
return mPosterArtUri;
}
@Override
public boolean isValid() {
return true;
}
public boolean isSearchable() {
return mSearchable;
}
@Override
public String getSeriesId() {
return mSeriesId;
}
@Override
public String getSeasonNumber() {
return mSeasonNumber;
}
public String getSeasonTitle() {
return mSeasonTitle;
}
@Override
public long getStartTimeUtcMillis() {
return mStartTimeUtcMillis;
}
@Override
public String getThumbnailUri() {
return mThumbnailUri;
}
@Override
public String getTitle() {
return mTitle;
}
public Uri getUri() {
return ContentUris.withAppendedId(RecordedPrograms.CONTENT_URI, mId);
}
public int getVersionNumber() {
return mVersionNumber;
}
public int getVideoHeight() {
return mVideoHeight;
}
public int getVideoWidth() {
return mVideoWidth;
}
/**
* Checks whether the recording has been clipped or not.
*/
public boolean isClipped() {
return mEndTimeUtcMillis - mStartTimeUtcMillis - mDurationMillis > CLIPPED_THRESHOLD_MS;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RecordedProgram that = (RecordedProgram) o;
return Objects.equals(mId, that.mId) &&
Objects.equals(mChannelId, that.mChannelId) &&
Objects.equals(mSeriesId, that.mSeriesId) &&
Objects.equals(mSeasonNumber, that.mSeasonNumber) &&
Objects.equals(mSeasonTitle, that.mSeasonTitle) &&
Objects.equals(mEpisodeNumber, that.mEpisodeNumber) &&
Objects.equals(mStartTimeUtcMillis, that.mStartTimeUtcMillis) &&
Objects.equals(mEndTimeUtcMillis, that.mEndTimeUtcMillis) &&
Objects.equals(mVideoWidth, that.mVideoWidth) &&
Objects.equals(mVideoHeight, that.mVideoHeight) &&
Objects.equals(mSearchable, that.mSearchable) &&
Objects.equals(mDataBytes, that.mDataBytes) &&
Objects.equals(mDurationMillis, that.mDurationMillis) &&
Objects.equals(mExpireTimeUtcMillis, that.mExpireTimeUtcMillis) &&
Objects.equals(mInternalProviderFlag1, that.mInternalProviderFlag1) &&
Objects.equals(mInternalProviderFlag2, that.mInternalProviderFlag2) &&
Objects.equals(mInternalProviderFlag3, that.mInternalProviderFlag3) &&
Objects.equals(mInternalProviderFlag4, that.mInternalProviderFlag4) &&
Objects.equals(mVersionNumber, that.mVersionNumber) &&
Objects.equals(mTitle, that.mTitle) &&
Objects.equals(mEpisodeTitle, that.mEpisodeTitle) &&
Arrays.equals(mBroadcastGenres, that.mBroadcastGenres) &&
Arrays.equals(mCanonicalGenres, that.mCanonicalGenres) &&
Objects.equals(mShortDescription, that.mShortDescription) &&
Objects.equals(mLongDescription, that.mLongDescription) &&
Objects.equals(mAudioLanguage, that.mAudioLanguage) &&
Objects.equals(mContentRating, that.mContentRating) &&
Objects.equals(mPosterArtUri, that.mPosterArtUri) &&
Objects.equals(mThumbnailUri, that.mThumbnailUri);
}
/**
* Hashes based on the ID.
*/
@Override
public int hashCode() {
return Objects.hash(mId);
}
@Override
public String toString() {
return "RecordedProgram"
+ "[" + mId +
"]{ mPackageName=" + mPackageName +
", mInputId='" + mInputId + '\'' +
", mChannelId='" + mChannelId + '\'' +
", mTitle='" + mTitle + '\'' +
", mSeriesId='" + mSeriesId + '\'' +
", mEpisodeNumber=" + mEpisodeNumber +
", mEpisodeTitle='" + mEpisodeTitle + '\'' +
", mStartTimeUtcMillis=" + mStartTimeUtcMillis +
", mEndTimeUtcMillis=" + mEndTimeUtcMillis +
", mBroadcastGenres=" +
(mBroadcastGenres != null ? Arrays.toString(mBroadcastGenres) : "null") +
", mCanonicalGenres=" +
(mCanonicalGenres != null ? Arrays.toString(mCanonicalGenres) : "null") +
", mShortDescription='" + mShortDescription + '\'' +
", mLongDescription='" + mLongDescription + '\'' +
", mVideoHeight=" + mVideoHeight +
", mVideoWidth=" + mVideoWidth +
", mAudioLanguage='" + mAudioLanguage + '\'' +
", mContentRating='" + mContentRating + '\'' +
", mPosterArtUri=" + mPosterArtUri +
", mThumbnailUri=" + mThumbnailUri +
", mSearchable=" + mSearchable +
", mDataUri=" + mDataUri +
", mDataBytes=" + mDataBytes +
", mDurationMillis=" + mDurationMillis +
", mExpireTimeUtcMillis=" + mExpireTimeUtcMillis +
", mInternalProviderFlag1=" + mInternalProviderFlag1 +
", mInternalProviderFlag2=" + mInternalProviderFlag2 +
", mInternalProviderFlag3=" + mInternalProviderFlag3 +
", mInternalProviderFlag4=" + mInternalProviderFlag4 +
", mSeasonNumber=" + mSeasonNumber +
", mSeasonTitle=" + mSeasonTitle +
", mVersionNumber=" + mVersionNumber +
'}';
}
@Nullable
private static String safeToString(@Nullable Object o) {
return o == null ? null : o.toString();
}
@Nullable
private static String safeEncode(@Nullable String[] genres) {
return genres == null ? null : TvContract.Programs.Genres.encode(genres);
}
/**
* Returns an array containing all of the elements in the list.
*/
public static RecordedProgram[] toArray(Collection<RecordedProgram> recordedPrograms) {
return recordedPrograms.toArray(new RecordedProgram[recordedPrograms.size()]);
}
}