public abstract class

BasePreviewProgram

extends BaseProgram

 java.lang.Object

androidx.tvprovider.media.tv.BaseProgram

↳androidx.tvprovider.media.tv.BasePreviewProgram

Subclasses:

PreviewProgram, WatchNextProgram

Gradle dependencies

compile group: 'androidx.tvprovider', name: 'tvprovider', version: '1.1.0-alpha01'

  • groupId: androidx.tvprovider
  • artifactId: tvprovider
  • version: 1.1.0-alpha01

Artifact androidx.tvprovider:tvprovider:1.1.0-alpha01 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.tvprovider:tvprovider com.android.support:support-tv-provider

Androidx class mapping:

androidx.tvprovider.media.tv.BasePreviewProgram android.support.media.tv.BasePreviewProgram

Overview

Base class for derived classes that want to have common fields for preview programs.

Summary

Fields
public static final java.lang.StringPROJECTION

from BaseProgrammValues
Methods
public booleanequals(java.lang.Object other)

public java.lang.StringgetAuthor()

public intgetAvailability()

public java.lang.StringgetContentId()

public intgetDurationMillis()

public longgetEndTimeUtcMillis()

public java.lang.StringgetGenre()

public IntentgetIntent()

public UrigetIntentUri()

public longgetInteractionCount()

public intgetInteractionType()

public java.lang.StringgetInternalProviderId()

public intgetItemCount()

public intgetLastPlaybackPositionMillis()

public java.lang.StringgetLogoContentDescription()

public UrigetLogoUri()

public java.lang.StringgetOfferPrice()

public intgetPosterArtAspectRatio()

public UrigetPreviewAudioUri()

public UrigetPreviewVideoUri()

public java.lang.StringgetReleaseDate()

public java.lang.StringgetStartingPrice()

public longgetStartTimeUtcMillis()

public intgetThumbnailAspectRatio()

public intgetTvSeriesItemType()

public intgetType()

public booleanisBrowsable()

public booleanisLive()

public booleanisTransient()

public ContentValuestoContentValues()

public ContentValuestoContentValues(boolean includeProtectedFields)

Returns fields of the BasePreviewProgram in the ContentValues format to be easily inserted into the TV Input Framework database.

from BaseProgramgetAudioLanguages, getCanonicalGenres, getContentRatings, getDescription, getEpisodeNumber, getEpisodeTitle, getId, getInternalProviderDataByteArray, getInternalProviderFlag1, getInternalProviderFlag2, getInternalProviderFlag3, getInternalProviderFlag4, getLongDescription, getPackageName, getPosterArtUri, getReviewRating, getReviewRatingStyle, getSeasonNumber, getSeasonTitle, getSeriesId, getThumbnailUri, getTitle, getVideoHeight, getVideoWidth, hashCode, isSearchable, toString
from java.lang.Objectclone, finalize, getClass, notify, notifyAll, wait, wait, wait

Fields

public static final java.lang.String PROJECTION

Methods

public java.lang.String getInternalProviderId()

Returns:

The internal provider ID for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_INTERNAL_PROVIDER_ID

public Uri getPreviewVideoUri()

Returns:

The preview video URI for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_PREVIEW_VIDEO_URI

public int getLastPlaybackPositionMillis()

Returns:

The last playback position of the program in millis.

See also: .PreviewPrograms#COLUMN_LAST_PLAYBACK_POSITION_MILLIS

public int getDurationMillis()

Returns:

The duration of the program in millis.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_DURATION_MILLIS

public Uri getIntentUri()

Returns:

The intent URI which is launched when the program is selected.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_INTENT_URI

public Intent getIntent()

Returns:

The intent which is launched when the program is selected.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_INTENT_URI

public boolean isTransient()

Returns:

Whether the program is transient or not.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_TRANSIENT

public int getType()

Returns:

The type of the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_TYPE

public int getTvSeriesItemType()

Returns:

The TV series item type for the program.

public int getPosterArtAspectRatio()

Returns:

The poster art aspect ratio for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_POSTER_ART_ASPECT_RATIO, COLUMN_POSTER_ART_URI

public int getThumbnailAspectRatio()

Returns:

The thumbnail aspect ratio for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_THUMBNAIL_ASPECT_RATIO, COLUMN_THUMBNAIL_URI

public Uri getLogoUri()

Returns:

The logo URI for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_LOGO_URI

public int getAvailability()

Returns:

The availability of the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_AVAILABILITY

public java.lang.String getStartingPrice()

Returns:

The starting price of the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_STARTING_PRICE

public java.lang.String getOfferPrice()

Returns:

The offer price of the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_OFFER_PRICE

public java.lang.String getReleaseDate()

Returns:

The release date of the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_RELEASE_DATE

public int getItemCount()

Returns:

The item count for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_ITEM_COUNT

public boolean isLive()

Returns:

Whether the program is live or not.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_LIVE

public int getInteractionType()

Returns:

The interaction type for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_INTERACTION_TYPE

public long getInteractionCount()

Returns:

The interaction count for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_INTERACTION_COUNT

public java.lang.String getAuthor()

Returns:

The author for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_AUTHOR

public boolean isBrowsable()

Returns:

Whether the program is browsable or not.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_BROWSABLE

public java.lang.String getContentId()

Returns:

The content ID for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_CONTENT_ID

public java.lang.String getLogoContentDescription()

Returns:

The logo content description for the program.

See also: .PreviewPrograms#COLUMN_LOGO_CONTENT_DESCRIPTION, TvContractCompat.PreviewProgramColumns.COLUMN_LOGO_URI

public java.lang.String getGenre()

Returns:

The genre for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_GENRE

public long getStartTimeUtcMillis()

Returns:

The start time for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_START_TIME_UTC_MILLIS

public long getEndTimeUtcMillis()

Returns:

The end time for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_END_TIME_UTC_MILLIS

public Uri getPreviewAudioUri()

Returns:

The preview audio URI for the program.

See also: TvContractCompat.PreviewProgramColumns.COLUMN_PREVIEW_AUDIO_URI

public boolean equals(java.lang.Object other)

public ContentValues toContentValues()

Returns:

The fields of the BasePreviewProgram in format to be easily inserted into the TV Input Framework database.

public ContentValues toContentValues(boolean includeProtectedFields)

Returns fields of the BasePreviewProgram in the ContentValues format to be easily inserted into the TV Input Framework database.

Parameters:

includeProtectedFields: Whether the fields protected by system is included or not.

Source

/*
 * Copyright (C) 2017 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 androidx.tvprovider.media.tv;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;

import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;

import androidx.annotation.IntDef;
import androidx.annotation.RestrictTo;
import androidx.tvprovider.media.tv.TvContractCompat.PreviewProgramColumns;
import androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * Base class for derived classes that want to have common fields for preview programs.
 *
 * @hide
 */
@RestrictTo(LIBRARY)
@SuppressWarnings("unchecked")
public abstract class BasePreviewProgram extends BaseProgram {
    /**
     * @hide
     */
    @RestrictTo(LIBRARY)
    public static final String[] PROJECTION = getProjection();

    private static final int INVALID_INT_VALUE = -1;
    private static final long INVALID_LONG_VALUE = -1;
    private static final int IS_TRANSIENT = 1;
    private static final int IS_LIVE = 1;
    private static final int IS_BROWSABLE = 1;

    /** @hide */
    @IntDef({
            TYPE_UNKNOWN,
            PreviewProgramColumns.TYPE_MOVIE,
            PreviewProgramColumns.TYPE_TV_SERIES,
            PreviewProgramColumns.TYPE_TV_SEASON,
            PreviewProgramColumns.TYPE_TV_EPISODE,
            PreviewProgramColumns.TYPE_CLIP,
            PreviewProgramColumns.TYPE_EVENT,
            PreviewProgramColumns.TYPE_CHANNEL,
            PreviewProgramColumns.TYPE_TRACK,
            PreviewProgramColumns.TYPE_ALBUM,
            PreviewProgramColumns.TYPE_ARTIST,
            PreviewProgramColumns.TYPE_PLAYLIST,
            PreviewProgramColumns.TYPE_STATION,
            PreviewProgramColumns.TYPE_GAME
    })
    @Retention(RetentionPolicy.SOURCE)
    @RestrictTo(LIBRARY)
    public @interface Type {}

    /**
     * The unknown program type.
     */
    private static final int TYPE_UNKNOWN = -1;

    /** @hide */
    @IntDef({
            ASPECT_RATIO_UNKNOWN,
            PreviewProgramColumns.ASPECT_RATIO_16_9,
            PreviewProgramColumns.ASPECT_RATIO_3_2,
            PreviewProgramColumns.ASPECT_RATIO_4_3,
            PreviewProgramColumns.ASPECT_RATIO_1_1,
            PreviewProgramColumns.ASPECT_RATIO_2_3,
            PreviewProgramColumns.ASPECT_RATIO_MOVIE_POSTER
    })
    @Retention(RetentionPolicy.SOURCE)
    @RestrictTo(LIBRARY)
    public @interface AspectRatio {}

    /**
     * The aspect ratio for unknown aspect ratios.
     */
    private static final int ASPECT_RATIO_UNKNOWN = -1;

    /** @hide */
    @IntDef({
            AVAILABILITY_UNKNOWN,
            PreviewProgramColumns.AVAILABILITY_AVAILABLE,
            PreviewProgramColumns.AVAILABILITY_FREE_WITH_SUBSCRIPTION,
            PreviewProgramColumns.AVAILABILITY_PAID_CONTENT,
            PreviewProgramColumns.AVAILABILITY_PURCHASED,
            PreviewProgramColumns.AVAILABILITY_FREE
    })
    @Retention(RetentionPolicy.SOURCE)
    @RestrictTo(LIBRARY)
    public @interface Availability {}

    /**
     * The unknown availability.
     */
    private static final int AVAILABILITY_UNKNOWN = -1;

    /** @hide */
    @IntDef({
            INTERACTION_TYPE_UNKNOWN,
            PreviewProgramColumns.INTERACTION_TYPE_VIEWS,
            PreviewProgramColumns.INTERACTION_TYPE_LISTENS,
            PreviewProgramColumns.INTERACTION_TYPE_FOLLOWERS,
            PreviewProgramColumns.INTERACTION_TYPE_FANS,
            PreviewProgramColumns.INTERACTION_TYPE_LIKES,
            PreviewProgramColumns.INTERACTION_TYPE_THUMBS,
            PreviewProgramColumns.INTERACTION_TYPE_VIEWERS,
    })
    @Retention(RetentionPolicy.SOURCE)
    @RestrictTo(LIBRARY)
    public @interface InteractionType {}

    /** @hide */
    @IntDef({
            PreviewProgramColumns.TV_SERIES_ITEM_TYPE_EPISODE,
            PreviewProgramColumns.TV_SERIES_ITEM_TYPE_CHAPTER
    })
    @Retention(RetentionPolicy.SOURCE)
    @RestrictTo(LIBRARY)
    public @interface TvSeriesItemType {}

    /**
     * The unknown interaction type.
     */
    private static final int INTERACTION_TYPE_UNKNOWN = -1;

    BasePreviewProgram(Builder builder) {
        super(builder);
    }

    /**
     * @return The internal provider ID for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_INTERNAL_PROVIDER_ID
     */
    public String getInternalProviderId() {
        return mValues.getAsString(PreviewPrograms.COLUMN_INTERNAL_PROVIDER_ID);
    }

    /**
     * @return The preview video URI for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_PREVIEW_VIDEO_URI
     */
    public Uri getPreviewVideoUri() {
        String uri = mValues.getAsString(PreviewPrograms.COLUMN_PREVIEW_VIDEO_URI);
        return uri == null ? null : Uri.parse(uri);
    }

    /**
     * @return The last playback position of the program in millis.
     * @see androidx.tvprovider.media.tv.TvContractCompat
     * .PreviewPrograms#COLUMN_LAST_PLAYBACK_POSITION_MILLIS
     */
    public int getLastPlaybackPositionMillis() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_LAST_PLAYBACK_POSITION_MILLIS);
        return i == null ? INVALID_INT_VALUE : i;
    }

    /**
     * @return The duration of the program in millis.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_DURATION_MILLIS
     */
    public int getDurationMillis() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_DURATION_MILLIS);
        return i == null ? INVALID_INT_VALUE : i;
    }

    /**
     * @return The intent URI which is launched when the program is selected.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_INTENT_URI
     */
    public Uri getIntentUri() {
        String uri = mValues.getAsString(PreviewPrograms.COLUMN_INTENT_URI);
        return uri == null ? null : Uri.parse(uri);
    }

    /**
     * @return The intent which is launched when the program is selected.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_INTENT_URI
     */
    public Intent getIntent() throws URISyntaxException {
        String uri = mValues.getAsString(PreviewPrograms.COLUMN_INTENT_URI);
        return uri == null ? null : Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
    }

    /**
     * @return Whether the program is transient or not.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_TRANSIENT
     */
    public boolean isTransient() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_TRANSIENT);
        return i != null && i == IS_TRANSIENT;
    }

    /**
     * @return The type of the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_TYPE
     */
    public @Type int getType() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_TYPE);
        return i == null ? TYPE_UNKNOWN : i;
    }

    /**
     * @return The TV series item type for the program.
     */
    public @TvSeriesItemType int getTvSeriesItemType() {
        return mValues.getAsInteger(PreviewProgramColumns.COLUMN_TV_SERIES_ITEM_TYPE);
    }

    /**
     * @return The poster art aspect ratio for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_POSTER_ART_ASPECT_RATIO
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_POSTER_ART_URI
     */
    public @AspectRatio int getPosterArtAspectRatio() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_POSTER_ART_ASPECT_RATIO);
        return i == null ? ASPECT_RATIO_UNKNOWN : i;
    }

    /**
     * @return The thumbnail aspect ratio for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_THUMBNAIL_ASPECT_RATIO
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_THUMBNAIL_URI
     */
    public @AspectRatio int getThumbnailAspectRatio() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_THUMBNAIL_ASPECT_RATIO);
        return i == null ? ASPECT_RATIO_UNKNOWN : i;
    }

    /**
     * @return The logo URI for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_LOGO_URI
     */
    public Uri getLogoUri() {
        String uri = mValues.getAsString(PreviewPrograms.COLUMN_LOGO_URI);
        return uri == null ? null : Uri.parse(uri);
    }

    /**
     * @return The availability of the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_AVAILABILITY
     */
    public @Availability int getAvailability() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_AVAILABILITY);
        return i == null ? AVAILABILITY_UNKNOWN : i;
    }

    /**
     * @return The starting price of the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_STARTING_PRICE
     */
    public String getStartingPrice() {
        return mValues.getAsString(PreviewPrograms.COLUMN_STARTING_PRICE);
    }

    /**
     * @return The offer price of the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_OFFER_PRICE
     */
    public String getOfferPrice() {
        return mValues.getAsString(PreviewPrograms.COLUMN_OFFER_PRICE);
    }

    /**
     * @return The release date of the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_RELEASE_DATE
     */
    public String getReleaseDate() {
        return mValues.getAsString(PreviewPrograms.COLUMN_RELEASE_DATE);
    }

    /**
     * @return The item count for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_ITEM_COUNT
     */
    public int getItemCount() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_ITEM_COUNT);
        return i == null ? INVALID_INT_VALUE : i;
    }

    /**
     * @return Whether the program is live or not.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_LIVE
     */
    public boolean isLive() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_LIVE);
        return i != null && i == IS_LIVE;
    }

    /**
     * @return The interaction type for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_INTERACTION_TYPE
     */
    public @InteractionType int getInteractionType() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_INTERACTION_TYPE);
        return i == null ? INTERACTION_TYPE_UNKNOWN : i;
    }

    /**
     * @return The interaction count for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_INTERACTION_COUNT
     */
    public long getInteractionCount() {
        Long l = mValues.getAsLong(PreviewPrograms.COLUMN_INTERACTION_COUNT);
        return l == null ? INVALID_LONG_VALUE : l;
    }

    /**
     * @return The author for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_AUTHOR
     */
    public String getAuthor() {
        return mValues.getAsString(PreviewPrograms.COLUMN_AUTHOR);
    }

    /**
     * @return Whether the program is browsable or not.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_BROWSABLE
     */
    public boolean isBrowsable() {
        Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_BROWSABLE);
        return i != null && i == IS_BROWSABLE;
    }

    /**
     * @return The content ID for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_CONTENT_ID
     */
    public String getContentId() {
        return mValues.getAsString(PreviewPrograms.COLUMN_CONTENT_ID);
    }

    /**
     * @return The logo content description for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat
     * .PreviewPrograms#COLUMN_LOGO_CONTENT_DESCRIPTION
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_LOGO_URI
     */
    public String getLogoContentDescription() {
        return mValues.getAsString(PreviewPrograms.COLUMN_LOGO_CONTENT_DESCRIPTION);
    }

    /**
     * @return The genre for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_GENRE
     */
    public String getGenre() {
        return mValues.getAsString(PreviewPrograms.COLUMN_GENRE);
    }

    /**
     * @return The start time for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_START_TIME_UTC_MILLIS
     */
    public long getStartTimeUtcMillis() {
        Long l = mValues.getAsLong(PreviewPrograms.COLUMN_START_TIME_UTC_MILLIS);
        return l == null ? INVALID_LONG_VALUE : l;
    }

    /**
     * @return The end time for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_END_TIME_UTC_MILLIS
     */
    public long getEndTimeUtcMillis() {
        Long l = mValues.getAsLong(PreviewPrograms.COLUMN_END_TIME_UTC_MILLIS);
        return l == null ? INVALID_LONG_VALUE : l;
    }

    /**
     * @return The preview audio URI for the program.
     * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_PREVIEW_AUDIO_URI
     */
    public Uri getPreviewAudioUri() {
        String uri = mValues.getAsString(PreviewPrograms.COLUMN_PREVIEW_AUDIO_URI);
        return uri == null ? null : Uri.parse(uri);
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof BasePreviewProgram)) {
            return false;
        }
        return mValues.equals(((BasePreviewProgram) other).mValues);
    }

    /**
     * @return The fields of the BasePreviewProgram in {@link ContentValues} format to be easily
     * inserted into the TV Input Framework database.
     */
    @Override
    public ContentValues toContentValues() {
        return toContentValues(false);
    }

    /**
     * Returns fields of the BasePreviewProgram in the ContentValues format to be easily inserted
     * into the TV Input Framework database.
     *
     * @param includeProtectedFields Whether the fields protected by system is included or not.
     * @hide
     */
    @RestrictTo(LIBRARY)
    public ContentValues toContentValues(boolean includeProtectedFields) {
        ContentValues values = super.toContentValues();
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            values.remove(PreviewProgramColumns.COLUMN_INTERNAL_PROVIDER_ID);
            values.remove(PreviewProgramColumns.COLUMN_PREVIEW_VIDEO_URI);
            values.remove(PreviewProgramColumns.COLUMN_LAST_PLAYBACK_POSITION_MILLIS);
            values.remove(PreviewProgramColumns.COLUMN_DURATION_MILLIS);
            values.remove(PreviewProgramColumns.COLUMN_INTENT_URI);
            values.remove(PreviewProgramColumns.COLUMN_TRANSIENT);
            values.remove(PreviewProgramColumns.COLUMN_TYPE);
            values.remove(PreviewProgramColumns.COLUMN_POSTER_ART_ASPECT_RATIO);
            values.remove(PreviewProgramColumns.COLUMN_THUMBNAIL_ASPECT_RATIO);
            values.remove(PreviewProgramColumns.COLUMN_LOGO_URI);
            values.remove(PreviewProgramColumns.COLUMN_AVAILABILITY);
            values.remove(PreviewProgramColumns.COLUMN_STARTING_PRICE);
            values.remove(PreviewProgramColumns.COLUMN_OFFER_PRICE);
            values.remove(PreviewProgramColumns.COLUMN_RELEASE_DATE);
            values.remove(PreviewProgramColumns.COLUMN_ITEM_COUNT);
            values.remove(PreviewProgramColumns.COLUMN_LIVE);
            values.remove(PreviewProgramColumns.COLUMN_INTERACTION_COUNT);
            values.remove(PreviewProgramColumns.COLUMN_AUTHOR);
            values.remove(PreviewProgramColumns.COLUMN_CONTENT_ID);
            values.remove(PreviewProgramColumns.COLUMN_LOGO_CONTENT_DESCRIPTION);
            values.remove(PreviewProgramColumns.COLUMN_GENRE);
            values.remove(PreviewProgramColumns.COLUMN_START_TIME_UTC_MILLIS);
            values.remove(PreviewProgramColumns.COLUMN_END_TIME_UTC_MILLIS);
            values.remove(PreviewProgramColumns.COLUMN_PREVIEW_AUDIO_URI);
            values.remove(PreviewProgramColumns.COLUMN_TV_SERIES_ITEM_TYPE);
        }
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || !includeProtectedFields) {
            values.remove(PreviewProgramColumns.COLUMN_BROWSABLE);
        }
        return values;
    }

    /**
     * Sets the fields in the cursor to the given builder instance.
     *
     * @param cursor A row from the TV Input Framework database.
     * @param builder A Builder to set the fields.
     */
    static void setFieldsFromCursor(Cursor cursor, Builder builder) {
        // TODO: Add additional API which does not use costly getColumnIndex().
        BaseProgram.setFieldsFromCursor(cursor, builder);
        int index;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if ((index =
                    cursor.getColumnIndex(PreviewProgramColumns.COLUMN_INTERNAL_PROVIDER_ID)) >= 0
                    && !cursor.isNull(index)) {
                builder.setInternalProviderId(cursor.getString(index));
            }
            if ((index =
                    cursor.getColumnIndex(PreviewProgramColumns.COLUMN_PREVIEW_VIDEO_URI)) >= 0
                    && !cursor.isNull(index)) {
                builder.setPreviewVideoUri(Uri.parse(cursor.getString(index)));
            }
            if ((index = cursor.getColumnIndex(
                    PreviewProgramColumns.COLUMN_LAST_PLAYBACK_POSITION_MILLIS)) >= 0
                    && !cursor.isNull(index)) {
                builder.setLastPlaybackPositionMillis(cursor.getInt(index));
            }
            if ((index =
                    cursor.getColumnIndex(PreviewProgramColumns.COLUMN_DURATION_MILLIS)) >= 0
                    && !cursor.isNull(index)) {
                builder.setDurationMillis(cursor.getInt(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_INTENT_URI)) >= 0
                    && !cursor.isNull(index)) {
                builder.setIntentUri(Uri.parse(cursor.getString(index)));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_TRANSIENT)) >= 0
                    && !cursor.isNull(index)) {
                builder.setTransient(cursor.getInt(index) == IS_TRANSIENT);
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_TYPE)) >= 0
                    && !cursor.isNull(index)) {
                builder.setType(cursor.getInt(index));
            }
            if ((index = cursor.getColumnIndex(
                    PreviewProgramColumns.COLUMN_POSTER_ART_ASPECT_RATIO)) >= 0
                    && !cursor.isNull(index)) {
                builder.setPosterArtAspectRatio(cursor.getInt(index));
            }
            if ((index =
                    cursor.getColumnIndex(PreviewProgramColumns.COLUMN_THUMBNAIL_ASPECT_RATIO)) >= 0
                    && !cursor.isNull(index)) {
                builder.setThumbnailAspectRatio(cursor.getInt(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_LOGO_URI)) >= 0
                    && !cursor.isNull(index)) {
                builder.setLogoUri(Uri.parse(cursor.getString(index)));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_AVAILABILITY)) >= 0
                    && !cursor.isNull(index)) {
                builder.setAvailability(cursor.getInt(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_STARTING_PRICE)) >= 0
                    && !cursor.isNull(index)) {
                builder.setStartingPrice(cursor.getString(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_OFFER_PRICE)) >= 0
                    && !cursor.isNull(index)) {
                builder.setOfferPrice(cursor.getString(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_RELEASE_DATE)) >= 0
                    && !cursor.isNull(index)) {
                builder.setReleaseDate(cursor.getString(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_ITEM_COUNT)) >= 0
                    && !cursor.isNull(index)) {
                builder.setItemCount(cursor.getInt(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_LIVE)) >= 0
                    && !cursor.isNull(index)) {
                builder.setLive(cursor.getInt(index) == IS_LIVE);
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_INTERACTION_TYPE)) >= 0
                    && !cursor.isNull(index)) {
                builder.setInteractionType(cursor.getInt(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_INTERACTION_COUNT)) >= 0
                    && !cursor.isNull(index)) {
                builder.setInteractionCount(cursor.getInt(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_AUTHOR)) >= 0
                    && !cursor.isNull(index)) {
                builder.setAuthor(cursor.getString(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_BROWSABLE)) >= 0
                    && !cursor.isNull(index)) {
                builder.setBrowsable(cursor.getInt(index) == IS_BROWSABLE);
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_CONTENT_ID)) >= 0
                    && !cursor.isNull(index)) {
                builder.setContentId(cursor.getString(index));
            }
            if ((index = cursor.getColumnIndex(
                    PreviewProgramColumns.COLUMN_LOGO_CONTENT_DESCRIPTION)) >= 0
                    && !cursor.isNull(index)) {
                builder.setLogoContentDescription(cursor.getString(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_GENRE)) >= 0
                    && !cursor.isNull(index)) {
                builder.setGenre(cursor.getString(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_START_TIME_UTC_MILLIS))
                    >= 0 && !cursor.isNull(index)) {
                builder.setStartTimeUtcMillis(cursor.getLong(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_END_TIME_UTC_MILLIS))
                    >= 0 && !cursor.isNull(index)) {
                builder.setEndTimeUtcMillis(cursor.getLong(index));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_PREVIEW_AUDIO_URI)) >= 0
                    && !cursor.isNull(index)) {
                builder.setPreviewAudioUri(Uri.parse(cursor.getString(index)));
            }
            if ((index = cursor.getColumnIndex(PreviewProgramColumns.COLUMN_TV_SERIES_ITEM_TYPE))
                    >= 0 && !cursor.isNull(index)) {
                builder.setTvSeriesItemType(cursor.getInt(index));
            }
        }
    }

    private static String[] getProjection() {
        String[] oColumns = new String[] {
                PreviewProgramColumns.COLUMN_INTERNAL_PROVIDER_ID,
                PreviewProgramColumns.COLUMN_PREVIEW_VIDEO_URI,
                PreviewProgramColumns.COLUMN_LAST_PLAYBACK_POSITION_MILLIS,
                PreviewProgramColumns.COLUMN_DURATION_MILLIS,
                PreviewProgramColumns.COLUMN_INTENT_URI,
                PreviewProgramColumns.COLUMN_TRANSIENT,
                PreviewProgramColumns.COLUMN_TYPE,
                PreviewProgramColumns.COLUMN_POSTER_ART_ASPECT_RATIO,
                PreviewProgramColumns.COLUMN_THUMBNAIL_ASPECT_RATIO,
                PreviewProgramColumns.COLUMN_LOGO_URI,
                PreviewProgramColumns.COLUMN_AVAILABILITY,
                PreviewProgramColumns.COLUMN_STARTING_PRICE,
                PreviewProgramColumns.COLUMN_OFFER_PRICE,
                PreviewProgramColumns.COLUMN_RELEASE_DATE,
                PreviewProgramColumns.COLUMN_ITEM_COUNT,
                PreviewProgramColumns.COLUMN_LIVE,
                PreviewProgramColumns.COLUMN_INTERACTION_TYPE,
                PreviewProgramColumns.COLUMN_INTERACTION_COUNT,
                PreviewProgramColumns.COLUMN_AUTHOR,
                PreviewProgramColumns.COLUMN_BROWSABLE,
                PreviewProgramColumns.COLUMN_CONTENT_ID,
                PreviewProgramColumns.COLUMN_LOGO_CONTENT_DESCRIPTION,
                PreviewProgramColumns.COLUMN_GENRE,
                PreviewProgramColumns.COLUMN_START_TIME_UTC_MILLIS,
                PreviewProgramColumns.COLUMN_END_TIME_UTC_MILLIS,
                PreviewProgramColumns.COLUMN_PREVIEW_AUDIO_URI,
                PreviewProgramColumns.COLUMN_TV_SERIES_ITEM_TYPE
        };
        return CollectionUtils.concatAll(BaseProgram.PROJECTION, oColumns);
    }

    /**
     * This Builder class simplifies the creation of a {@link BasePreviewProgram} object.
     *
     * @param <T> The Builder of the derived classe.
     */
    public abstract static class Builder<T extends Builder> extends BaseProgram.Builder<T> {
        private static final SimpleDateFormat sFormat =
                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

        static {
            sFormat.setTimeZone(TimeZone.getTimeZone("GMT-0"));
        }

        /**
         * Creates a new Builder object.
         */
        public Builder() {
        }

        /**
         * Creates a new Builder object with values copied from another Program.
         *
         * @param other The Program you're copying from.
         */
        public Builder(BasePreviewProgram other) {
            mValues = new ContentValues(other.mValues);
        }

        /**
         * Sets external ID for the program.
         *
         * @param externalId The internal provider ID for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#COLUMN_INTERNAL_PROVIDER_ID
         */
        public T setInternalProviderId(String externalId) {
            mValues.put(PreviewPrograms.COLUMN_INTERNAL_PROVIDER_ID, externalId);
            return (T) this;
        }

        /**
         * Sets a URI for the preview video.
         *
         * @param previewVideoUri The preview video URI for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_PREVIEW_VIDEO_URI
         */
        public T setPreviewVideoUri(Uri previewVideoUri) {
            mValues.put(PreviewPrograms.COLUMN_PREVIEW_VIDEO_URI,
                    previewVideoUri == null ? null : previewVideoUri.toString());
            return (T) this;
        }

        /**
         * Sets the last playback position (in milliseconds) of the preview video.
         *
         * @param position The last playback posirion for the program in millis.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#COLUMN_LAST_PLAYBACK_POSITION_MILLIS
         */
        public T setLastPlaybackPositionMillis(int position) {
            mValues.put(PreviewPrograms.COLUMN_LAST_PLAYBACK_POSITION_MILLIS, position);
            return (T) this;
        }

        /**
         * Sets the last playback duration (in milliseconds) of the preview video.
         *
         * @param duration The duration the program in millis.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_DURATION_MILLIS
         */
        public T setDurationMillis(int duration) {
            mValues.put(PreviewPrograms.COLUMN_DURATION_MILLIS, duration);
            return (T) this;
        }

        /**
         * Sets the intent URI which is launched when the program is selected.
         *
         * @param intentUri The intent URI for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_INTENT_URI
         */
        public T setIntentUri(Uri intentUri) {
            mValues.put(PreviewPrograms.COLUMN_INTENT_URI,
                    intentUri == null ? null : intentUri.toString());
            return (T) this;
        }

        /**
         * Sets the intent which is launched when the program is selected.
         *
         * @param intent The Intent to be executed when the preview program is selected
         * @return This Builder object to allow for chaining of calls to builder methods.
         */
        public T setIntent(Intent intent) {
            return setIntentUri(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
        }

        /**
         * Sets whether this program is transient or not.
         *
         * @param transientValue Whether the program is transient or not.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_TRANSIENT
         */
        public T setTransient(boolean transientValue) {
            mValues.put(PreviewPrograms.COLUMN_TRANSIENT, transientValue ? IS_TRANSIENT : 0);
            return (T) this;
        }

        /**
         * Sets the type of this program content.
         *
         * <p>The value should match one of the followings:
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_MOVIE},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_TV_SERIES},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_TV_SEASON},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_TV_EPISODE},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_CLIP},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_EVENT},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_CHANNEL},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_TRACK},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_ALBUM},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_ARTIST},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_PLAYLIST},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_STATION}, and
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#TYPE_GAME}.
         *
         * @param type The type of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_TYPE
         */
        public T setType(@Type int type) {
            mValues.put(PreviewPrograms.COLUMN_TYPE, type);
            return (T) this;
        }

        /**
         * Sets the aspect ratio of the poster art for this TV program.
         *
         * <p>The value should match one of the followings:
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_16_9},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_3_2},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_4_3},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_1_1},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_2_3}, and
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#ASPECT_RATIO_MOVIE_POSTER}.
         *
         * @param ratio The poster art aspect ratio for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#COLUMN_POSTER_ART_ASPECT_RATIO
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_POSTER_ART_URI
         */
        public T setPosterArtAspectRatio(@AspectRatio int ratio) {
            mValues.put(PreviewPrograms.COLUMN_POSTER_ART_ASPECT_RATIO, ratio);
            return (T) this;
        }

        /**
         * Sets the aspect ratio of the thumbnail for this TV program.
         *
         * <p>The value should match one of the followings:
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_16_9},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_3_2},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_4_3},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_1_1},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#ASPECT_RATIO_2_3}, and
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#ASPECT_RATIO_MOVIE_POSTER}.
         *
         * @param ratio The thumbnail aspect ratio of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#COLUMN_THUMBNAIL_ASPECT_RATIO
         */
        public T setThumbnailAspectRatio(@AspectRatio int ratio) {
            mValues.put(PreviewPrograms.COLUMN_THUMBNAIL_ASPECT_RATIO, ratio);
            return (T) this;
        }

        /**
         * Sets the URI for the logo of this TV program.
         *
         * @param logoUri The logo URI for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_LOGO_URI
         */
        public T setLogoUri(Uri logoUri) {
            mValues.put(PreviewPrograms.COLUMN_LOGO_URI,
                    logoUri == null ? null : logoUri.toString());
            return (T) this;
        }

        /**
         * Sets the availability of this TV program.
         *
         * <p>The value should match one of the followings:
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#AVAILABILITY_AVAILABLE},
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#AVAILABILITY_FREE_WITH_SUBSCRIPTION},
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#AVAILABILITY_PAID_CONTENT},
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#AVAILABILITY_PURCHASED}, and
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#AVAILABILITY_FREE}.
         *
         * @param availability The availability of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_AVAILABILITY
         */
        public T setAvailability(@Availability int availability) {
            mValues.put(PreviewPrograms.COLUMN_AVAILABILITY, availability);
            return (T) this;
        }

        /**
         * Sets the starting price of this TV program.
         *
         * @param price The starting price of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_STARTING_PRICE
         */
        public T setStartingPrice(String price) {
            mValues.put(PreviewPrograms.COLUMN_STARTING_PRICE, price);
            return (T) this;
        }

        /**
         * Sets the offer price of this TV program.
         *
         * @param price The offer price of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_OFFER_PRICE
         */
        public T setOfferPrice(String price) {
            mValues.put(PreviewPrograms.COLUMN_OFFER_PRICE, price);
            return (T) this;
        }

        /**
         * Sets the release date of this TV program.
         *
         * <p>The value should be in one of the following formats:
         * "yyyy", "yyyy-MM-dd", and "yyyy-MM-ddTHH:mm:ssZ" (UTC in ISO 8601).
         *
         * @param releaseDate The release date of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_RELEASE_DATE
         */
        public T setReleaseDate(String releaseDate) {
            mValues.put(PreviewPrograms.COLUMN_RELEASE_DATE, releaseDate);
            return (T) this;
        }

        /**
         * Sets the release date of this TV program.
         *
         * @param releaseDate The release date of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_RELEASE_DATE
         */
        public T setReleaseDate(Date releaseDate) {
            mValues.put(PreviewPrograms.COLUMN_RELEASE_DATE, sFormat.format(releaseDate));
            return (T) this;
        }

        /**
         * Sets the count of the items included in this TV program.
         *
         * @param itemCount The item count for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_ITEM_COUNT
         */
        public T setItemCount(int itemCount) {
            mValues.put(PreviewPrograms.COLUMN_ITEM_COUNT, itemCount);
            return (T) this;
        }

        /**
         * Sets whether this TV program is live or not.
         *
         * @param live Whether the program is live or not.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_LIVE
         */
        public T setLive(boolean live) {
            mValues.put(PreviewPrograms.COLUMN_LIVE, live ? IS_LIVE : 0);
            return (T) this;
        }

        /**
         * Sets the type of interaction for this TV program.
         *
         * <p> The value should match one of the followings:
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#INTERACTION_TYPE_LISTENS},
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#INTERACTION_TYPE_FOLLOWERS},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#INTERACTION_TYPE_FANS},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#INTERACTION_TYPE_LIKES},
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#INTERACTION_TYPE_THUMBS},
         * {@link androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#INTERACTION_TYPE_VIEWS},
         * and
         * {@link androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#INTERACTION_TYPE_VIEWERS}.
         *
         * @param interactionType The interaction type of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_INTERACTION_TYPE
         */
        public T setInteractionType(@InteractionType int interactionType) {
            mValues.put(PreviewPrograms.COLUMN_INTERACTION_TYPE, interactionType);
            return (T) this;
        }

        /**
         * Sets the interaction count for this program.
         *
         * @param interactionCount The interaction count for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_INTERACTION_COUNT
         */
        public T setInteractionCount(long interactionCount) {
            mValues.put(PreviewPrograms.COLUMN_INTERACTION_COUNT, interactionCount);
            return (T) this;
        }

        /**
         * Sets the author or artist of this content.
         *
         * @param author The author of the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_AUTHOR
         */
        public T setAuthor(String author) {
            mValues.put(PreviewPrograms.COLUMN_AUTHOR, author);
            return (T) this;
        }

        /**
         * Sets whether this TV program is browsable or not.
         *
         * @param browsable Whether the program is browsable or not.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_BROWSABLE
         * @hide
         */
        @RestrictTo(LIBRARY)
        public T setBrowsable(boolean browsable) {
            mValues.put(PreviewPrograms.COLUMN_BROWSABLE, browsable ? IS_BROWSABLE : 0);
            return (T) this;
        }

        /**
         * Sets the content ID for this program.
         *
         * @param contentId The content ID for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_CONTENT_ID
         */
        public T setContentId(String contentId) {
            mValues.put(PreviewPrograms.COLUMN_CONTENT_ID, contentId);
            return (T) this;
        }

        /**
         * Sets the logo's content description for this program.
         *
         * @param logoContentDescription The content description for the logo displayed in the
         *                               program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#COLUMN_LOGO_CONTENT_DESCRIPTION
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_LOGO_URI
         */
        public T setLogoContentDescription(String logoContentDescription) {
            mValues.put(PreviewPrograms.COLUMN_LOGO_CONTENT_DESCRIPTION, logoContentDescription);
            return (T) this;
        }

        /**
         * Sets the genre for this program.
         *
         * @param genre The genre for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_GENRE
         */
        public T setGenre(String genre) {
            mValues.put(PreviewPrograms.COLUMN_GENRE, genre);
            return (T) this;
        }

        /**
         * Sets the start time of the program (for live programs).
         *
         * @param startTime The start time for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat
         * .PreviewPrograms#COLUMN_START_TIME_UTC_MILLIS
         */
        public T setStartTimeUtcMillis(long startTime) {
            mValues.put(PreviewPrograms.COLUMN_START_TIME_UTC_MILLIS, startTime);
            return (T) this;
        }

        /**
         * Sets the end time of the program (for live programs).
         *
         * @param endTime The end time for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_END_TIME_UTC_MILLIS
         */
        public T setEndTimeUtcMillis(long endTime) {
            mValues.put(PreviewPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime);
            return (T) this;
        }

        /**
         * Sets a URI for the preview audio.
         *
         * @param previewAudioUri The preview audio URI for the program.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms#COLUMN_PREVIEW_AUDIO_URI
         */
        public T setPreviewAudioUri(Uri previewAudioUri) {
            mValues.put(PreviewPrograms.COLUMN_PREVIEW_AUDIO_URI,
                    previewAudioUri == null ? null : previewAudioUri.toString());
            return (T) this;
        }

        /**
         * Set the TV series item type for this program.
         *
         * @param type the TV series item type
         * @return This Builder object to allow for chaining of calls to builder methods.
         */
        public T setTvSeriesItemType(@TvSeriesItemType int type) {
            mValues.put(PreviewPrograms.COLUMN_TV_SERIES_ITEM_TYPE, type);
            return (T) this;
        }
    }
}