Home | History | Annotate | Download | only in tv
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.media.tv;
     18 
     19 import android.annotation.SystemApi;
     20 import android.content.ComponentName;
     21 import android.content.ContentResolver;
     22 import android.content.ContentUris;
     23 import android.net.Uri;
     24 import android.os.IBinder;
     25 import android.provider.BaseColumns;
     26 import android.util.ArraySet;
     27 
     28 import java.util.HashMap;
     29 import java.util.List;
     30 import java.util.Map;
     31 
     32 /**
     33  * <p>
     34  * The contract between the TV provider and applications. Contains definitions for the supported
     35  * URIs and columns.
     36  * </p>
     37  * <h3>Overview</h3>
     38  * <p>
     39  * TvContract defines a basic database of TV content metadata such as channel and program
     40  * information. The information is stored in {@link Channels} and {@link Programs} tables.
     41  * </p>
     42  * <ul>
     43  *     <li>A row in the {@link Channels} table represents information about a TV channel. The data
     44  *         format can vary greatly from standard to standard or according to service provider, thus
     45  *         the columns here are mostly comprised of basic entities that are usually seen to users
     46  *         regardless of standard such as channel number and name.</li>
     47  *     <li>A row in the {@link Programs} table represents a set of data describing a TV program such
     48  *         as program title and start time.</li>
     49  * </ul>
     50  */
     51 public final class TvContract {
     52     /** The authority for the TV provider. */
     53     public static final String AUTHORITY = "android.media.tv";
     54 
     55     private static final String PATH_CHANNEL = "channel";
     56     private static final String PATH_PROGRAM = "program";
     57     private static final String PATH_PASSTHROUGH = "passthrough";
     58 
     59     /**
     60      * An optional query, update or delete URI parameter that allows the caller to specify TV input
     61      * ID to filter channels.
     62      * @hide
     63      */
     64     public static final String PARAM_INPUT = "input";
     65 
     66     /**
     67      * An optional query, update or delete URI parameter that allows the caller to specify channel
     68      * ID to filter programs.
     69      * @hide
     70      */
     71     public static final String PARAM_CHANNEL = "channel";
     72 
     73     /**
     74      * An optional query, update or delete URI parameter that allows the caller to specify start
     75      * time (in milliseconds since the epoch) to filter programs.
     76      * @hide
     77      */
     78     public static final String PARAM_START_TIME = "start_time";
     79 
     80     /**
     81      * An optional query, update or delete URI parameter that allows the caller to specify end time
     82      * (in milliseconds since the epoch) to filter programs.
     83      * @hide
     84      */
     85     public static final String PARAM_END_TIME = "end_time";
     86 
     87     /**
     88      * A query, update or delete URI parameter that allows the caller to operate on all or
     89      * browsable-only channels. If set to "true", the rows that contain non-browsable channels are
     90      * not affected.
     91      * @hide
     92      */
     93     public static final String PARAM_BROWSABLE_ONLY = "browsable_only";
     94 
     95     /**
     96      * A optional query, update or delete URI parameter that allows the caller to specify canonical
     97      * genre to filter programs.
     98      * @hide
     99      */
    100     public static final String PARAM_CANONICAL_GENRE = "canonical_genre";
    101 
    102     /**
    103      * Builds an ID that uniquely identifies a TV input service.
    104      *
    105      * @param name The {@link ComponentName} of the TV input service to build ID for.
    106      * @return the ID for the given TV input service.
    107      */
    108     public static final String buildInputId(ComponentName name) {
    109         return name.flattenToShortString();
    110     }
    111 
    112     /**
    113      * Builds a URI that points to a specific channel.
    114      *
    115      * @param channelId The ID of the channel to point to.
    116      */
    117     public static final Uri buildChannelUri(long channelId) {
    118         return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId);
    119     }
    120 
    121     /**
    122      * Build a special channel URI intended to be used with pass-through inputs. (e.g. HDMI)
    123      *
    124      * @param inputId The ID of the pass-through input to build a channels URI for.
    125      * @see TvInputInfo#isPassthroughInput()
    126      */
    127     public static final Uri buildChannelUriForPassthroughInput(String inputId) {
    128         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
    129                 .appendPath(PATH_PASSTHROUGH).appendPath(inputId).build();
    130     }
    131 
    132     /**
    133      * Builds a URI that points to a channel logo. See {@link Channels.Logo}.
    134      *
    135      * @param channelId The ID of the channel whose logo is pointed to.
    136      */
    137     public static final Uri buildChannelLogoUri(long channelId) {
    138         return buildChannelLogoUri(buildChannelUri(channelId));
    139     }
    140 
    141     /**
    142      * Builds a URI that points to a channel logo. See {@link Channels.Logo}.
    143      *
    144      * @param channelUri The URI of the channel whose logo is pointed to.
    145      */
    146     public static final Uri buildChannelLogoUri(Uri channelUri) {
    147         if (!isChannelUriForTunerInput(channelUri)) {
    148             throw new IllegalArgumentException("Not a channel: " + channelUri);
    149         }
    150         return Uri.withAppendedPath(channelUri, Channels.Logo.CONTENT_DIRECTORY);
    151     }
    152 
    153     /**
    154      * Builds a URI that points to all channels from a given TV input.
    155      *
    156      * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
    157      *            URI for all the TV inputs.
    158      */
    159     public static final Uri buildChannelsUriForInput(String inputId) {
    160         return buildChannelsUriForInput(inputId, false);
    161     }
    162 
    163     /**
    164      * Builds a URI that points to all or browsable-only channels from a given TV input.
    165      *
    166      * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
    167      *            URI for all the TV inputs.
    168      * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
    169      *            to {@code false} the URI points to all channels regardless of whether they are
    170      *            browsable or not.
    171      * @hide
    172      */
    173     @SystemApi
    174     public static final Uri buildChannelsUriForInput(String inputId, boolean browsableOnly) {
    175         Uri.Builder builder = Channels.CONTENT_URI.buildUpon();
    176         if (inputId != null) {
    177             builder.appendQueryParameter(PARAM_INPUT, inputId);
    178         }
    179         return builder.appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly))
    180                 .build();
    181     }
    182 
    183     /**
    184      * Builds a URI that points to all or browsable-only channels which have programs with the given
    185      * genre from the given TV input.
    186      *
    187      * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
    188      *            URI for all the TV inputs.
    189      * @param genre {@link Programs.Genres} to search. If {@code null}, builds a URI for all genres.
    190      * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
    191      *            to {@code false} the URI points to all channels regardless of whether they are
    192      *            browsable or not.
    193      * @hide
    194      */
    195     @SystemApi
    196     public static final Uri buildChannelsUriForInput(String inputId, String genre,
    197             boolean browsableOnly) {
    198         if (genre == null) {
    199             return buildChannelsUriForInput(inputId, browsableOnly);
    200         }
    201         if (!Programs.Genres.isCanonical(genre)) {
    202             throw new IllegalArgumentException("Not a canonical genre: '" + genre + "'");
    203         }
    204         return buildChannelsUriForInput(inputId, browsableOnly).buildUpon()
    205                 .appendQueryParameter(PARAM_CANONICAL_GENRE, genre).build();
    206     }
    207 
    208     /**
    209      * Builds a URI that points to a specific program.
    210      *
    211      * @param programId The ID of the program to point to.
    212      */
    213     public static final Uri buildProgramUri(long programId) {
    214         return ContentUris.withAppendedId(Programs.CONTENT_URI, programId);
    215     }
    216 
    217     /**
    218      * Builds a URI that points to all programs on a given channel.
    219      *
    220      * @param channelId The ID of the channel to return programs for.
    221      */
    222     public static final Uri buildProgramsUriForChannel(long channelId) {
    223         return Programs.CONTENT_URI.buildUpon()
    224                 .appendQueryParameter(PARAM_CHANNEL, String.valueOf(channelId)).build();
    225     }
    226 
    227     /**
    228      * Builds a URI that points to all programs on a given channel.
    229      *
    230      * @param channelUri The URI of the channel to return programs for.
    231      */
    232     public static final Uri buildProgramsUriForChannel(Uri channelUri) {
    233         if (!isChannelUriForTunerInput(channelUri)) {
    234             throw new IllegalArgumentException("Not a channel: " + channelUri);
    235         }
    236         return buildProgramsUriForChannel(ContentUris.parseId(channelUri));
    237     }
    238 
    239     /**
    240      * Builds a URI that points to programs on a specific channel whose schedules overlap with the
    241      * given time frame.
    242      *
    243      * @param channelId The ID of the channel to return programs for.
    244      * @param startTime The start time used to filter programs. The returned programs should have
    245      *            {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time.
    246      * @param endTime The end time used to filter programs. The returned programs should have
    247      *            {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time.
    248      */
    249     public static final Uri buildProgramsUriForChannel(long channelId, long startTime,
    250             long endTime) {
    251         Uri uri = buildProgramsUriForChannel(channelId);
    252         return uri.buildUpon().appendQueryParameter(PARAM_START_TIME, String.valueOf(startTime))
    253                 .appendQueryParameter(PARAM_END_TIME, String.valueOf(endTime)).build();
    254     }
    255 
    256     /**
    257      * Builds a URI that points to programs on a specific channel whose schedules overlap with the
    258      * given time frame.
    259      *
    260      * @param channelUri The URI of the channel to return programs for.
    261      * @param startTime The start time used to filter programs. The returned programs should have
    262      *            {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time.
    263      * @param endTime The end time used to filter programs. The returned programs should have
    264      *            {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time.
    265      */
    266     public static final Uri buildProgramsUriForChannel(Uri channelUri, long startTime,
    267             long endTime) {
    268         if (!isChannelUriForTunerInput(channelUri)) {
    269             throw new IllegalArgumentException("Not a channel: " + channelUri);
    270         }
    271         return buildProgramsUriForChannel(ContentUris.parseId(channelUri), startTime, endTime);
    272     }
    273 
    274     /**
    275      * Builds a URI that points to a specific program the user watched.
    276      *
    277      * @param watchedProgramId The ID of the watched program to point to.
    278      * @hide
    279      */
    280     public static final Uri buildWatchedProgramUri(long watchedProgramId) {
    281         return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId);
    282     }
    283 
    284     private static final boolean isTvUri(Uri uri) {
    285         return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())
    286                 && AUTHORITY.equals(uri.getAuthority());
    287     }
    288 
    289     private static final boolean isTwoSegmentUriStartingWith(Uri uri, String pathSegment) {
    290         List<String> pathSegments = uri.getPathSegments();
    291         return pathSegments.size() == 2 && pathSegment.equals(pathSegments.get(0));
    292     }
    293 
    294     /**
    295      * Returns true, if {@code uri} is a channel URI.
    296      * @hide
    297      */
    298     public static final boolean isChannelUri(Uri uri) {
    299         return isChannelUriForTunerInput(uri) || isChannelUriForPassthroughInput(uri);
    300     }
    301 
    302     /**
    303      * Returns true, if {@code uri} is a channel URI for a tuner input.
    304      * @hide
    305      */
    306     public static final boolean isChannelUriForTunerInput(Uri uri) {
    307         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_CHANNEL);
    308     }
    309 
    310     /**
    311      * Returns true, if {@code uri} is a channel URI for a passthrough input.
    312      * @hide
    313      */
    314     @SystemApi
    315     public static final boolean isChannelUriForPassthroughInput(Uri uri) {
    316         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PASSTHROUGH);
    317     }
    318 
    319     /**
    320      * Returns true, if {@code uri} is a program URI.
    321      * @hide
    322      */
    323     public static final boolean isProgramUri(Uri uri) {
    324         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM);
    325     }
    326 
    327 
    328     private TvContract() {}
    329 
    330     /**
    331      * Common base for the tables of TV channels/programs.
    332      */
    333     public interface BaseTvColumns extends BaseColumns {
    334         /**
    335          * The name of the package that owns a row in each table.
    336          * <p>
    337          * The TV provider fills it in with the name of the package that provides the initial data
    338          * of that row. If the package is later uninstalled, the rows it owns are automatically
    339          * removed from the tables.
    340          * </p><p>
    341          * Type: TEXT
    342          * </p>
    343          */
    344         public static final String COLUMN_PACKAGE_NAME = "package_name";
    345     }
    346 
    347     /** Column definitions for the TV channels table. */
    348     public static final class Channels implements BaseTvColumns {
    349 
    350         /** The content:// style URI for this table. */
    351         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
    352                 + PATH_CHANNEL);
    353 
    354         /** The MIME type of a directory of TV channels. */
    355         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/channel";
    356 
    357         /** The MIME type of a single TV channel. */
    358         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
    359 
    360         /** A generic channel type. */
    361         public static final String TYPE_OTHER = "TYPE_OTHER";
    362 
    363         /** The channel type for NTSC. */
    364         public static final String TYPE_NTSC = "TYPE_NTSC";
    365 
    366         /** The channel type for PAL. */
    367         public static final String TYPE_PAL = "TYPE_PAL";
    368 
    369         /** The channel type for SECAM. */
    370         public static final String TYPE_SECAM = "TYPE_SECAM";
    371 
    372         /** The channel type for DVB-T (terrestrial). */
    373         public static final String TYPE_DVB_T = "TYPE_DVB_T";
    374 
    375         /** The channel type for DVB-T2 (terrestrial). */
    376         public static final String TYPE_DVB_T2 = "TYPE_DVB_T2";
    377 
    378         /** The channel type for DVB-S (satellite). */
    379         public static final String TYPE_DVB_S = "TYPE_DVB_S";
    380 
    381         /** The channel type for DVB-S2 (satellite). */
    382         public static final String TYPE_DVB_S2 = "TYPE_DVB_S2";
    383 
    384         /** The channel type for DVB-C (cable). */
    385         public static final String TYPE_DVB_C = "TYPE_DVB_C";
    386 
    387         /** The channel type for DVB-C2 (cable). */
    388         public static final String TYPE_DVB_C2 = "TYPE_DVB_C2";
    389 
    390         /** The channel type for DVB-H (handheld). */
    391         public static final String TYPE_DVB_H = "TYPE_DVB_H";
    392 
    393         /** The channel type for DVB-SH (satellite). */
    394         public static final String TYPE_DVB_SH = "TYPE_DVB_SH";
    395 
    396         /** The channel type for ATSC (terrestrial). */
    397         public static final String TYPE_ATSC_T = "TYPE_ATSC_T";
    398 
    399         /** The channel type for ATSC (cable). */
    400         public static final String TYPE_ATSC_C = "TYPE_ATSC_C";
    401 
    402         /** The channel type for ATSC-M/H (mobile/handheld). */
    403         public static final String TYPE_ATSC_M_H = "TYPE_ATSC_M_H";
    404 
    405         /** The channel type for ISDB-T (terrestrial). */
    406         public static final String TYPE_ISDB_T = "TYPE_ISDB_T";
    407 
    408         /** The channel type for ISDB-Tb (Brazil). */
    409         public static final String TYPE_ISDB_TB = "TYPE_ISDB_TB";
    410 
    411         /** The channel type for ISDB-S (satellite). */
    412         public static final String TYPE_ISDB_S = "TYPE_ISDB_S";
    413 
    414         /** The channel type for ISDB-C (cable). */
    415         public static final String TYPE_ISDB_C = "TYPE_ISDB_C";
    416 
    417         /** The channel type for 1seg (handheld). */
    418         public static final String TYPE_1SEG = "TYPE_1SEG";
    419 
    420         /** The channel type for DTMB (terrestrial). */
    421         public static final String TYPE_DTMB = "TYPE_DTMB";
    422 
    423         /** The channel type for CMMB (handheld). */
    424         public static final String TYPE_CMMB = "TYPE_CMMB";
    425 
    426         /** The channel type for T-DMB (terrestrial). */
    427         public static final String TYPE_T_DMB = "TYPE_T_DMB";
    428 
    429         /** The channel type for S-DMB (satellite). */
    430         public static final String TYPE_S_DMB = "TYPE_S_DMB";
    431 
    432         /** A generic service type. */
    433         public static final String SERVICE_TYPE_OTHER = "SERVICE_TYPE_OTHER";
    434 
    435         /** The service type for regular TV channels that have both audio and video. */
    436         public static final String SERVICE_TYPE_AUDIO_VIDEO = "SERVICE_TYPE_AUDIO_VIDEO";
    437 
    438         /** The service type for radio channels that have audio only. */
    439         public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO";
    440 
    441         /** The video format for 240p. */
    442         public static final String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P";
    443 
    444         /** The video format for 360p. */
    445         public static final String VIDEO_FORMAT_360P = "VIDEO_FORMAT_360P";
    446 
    447         /** The video format for 480i. */
    448         public static final String VIDEO_FORMAT_480I = "VIDEO_FORMAT_480I";
    449 
    450         /** The video format for 480p. */
    451         public static final String VIDEO_FORMAT_480P = "VIDEO_FORMAT_480P";
    452 
    453         /** The video format for 576i. */
    454         public static final String VIDEO_FORMAT_576I = "VIDEO_FORMAT_576I";
    455 
    456         /** The video format for 576p. */
    457         public static final String VIDEO_FORMAT_576P = "VIDEO_FORMAT_576P";
    458 
    459         /** The video format for 720p. */
    460         public static final String VIDEO_FORMAT_720P = "VIDEO_FORMAT_720P";
    461 
    462         /** The video format for 1080i. */
    463         public static final String VIDEO_FORMAT_1080I = "VIDEO_FORMAT_1080I";
    464 
    465         /** The video format for 1080p. */
    466         public static final String VIDEO_FORMAT_1080P = "VIDEO_FORMAT_1080P";
    467 
    468         /** The video format for 2160p. */
    469         public static final String VIDEO_FORMAT_2160P = "VIDEO_FORMAT_2160P";
    470 
    471         /** The video format for 4320p. */
    472         public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P";
    473 
    474         /** The video resolution for standard-definition. */
    475         public static final String VIDEO_RESOLUTION_SD = "VIDEO_RESOLUTION_SD";
    476 
    477         /** The video resolution for enhanced-definition. */
    478         public static final String VIDEO_RESOLUTION_ED = "VIDEO_RESOLUTION_ED";
    479 
    480         /** The video resolution for high-definition. */
    481         public static final String VIDEO_RESOLUTION_HD = "VIDEO_RESOLUTION_HD";
    482 
    483         /** The video resolution for full high-definition. */
    484         public static final String VIDEO_RESOLUTION_FHD = "VIDEO_RESOLUTION_FHD";
    485 
    486         /** The video resolution for ultra high-definition. */
    487         public static final String VIDEO_RESOLUTION_UHD = "VIDEO_RESOLUTION_UHD";
    488 
    489         private static final Map<String, String> VIDEO_FORMAT_TO_RESOLUTION_MAP =
    490                 new HashMap<String, String>();
    491 
    492         static {
    493             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480I, VIDEO_RESOLUTION_SD);
    494             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480P, VIDEO_RESOLUTION_ED);
    495             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576I, VIDEO_RESOLUTION_SD);
    496             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576P, VIDEO_RESOLUTION_ED);
    497             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_720P, VIDEO_RESOLUTION_HD);
    498             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080I, VIDEO_RESOLUTION_HD);
    499             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080P, VIDEO_RESOLUTION_FHD);
    500             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_2160P, VIDEO_RESOLUTION_UHD);
    501             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_4320P, VIDEO_RESOLUTION_UHD);
    502         }
    503 
    504         /**
    505          * Returns the video resolution (definition) for a given video format.
    506          *
    507          * @param videoFormat The video format defined in {@link Channels}.
    508          * @return the corresponding video resolution string. {@code null} if the resolution string
    509          *         is not defined for the given video format.
    510          * @see #COLUMN_VIDEO_FORMAT
    511          */
    512         public static final String getVideoResolution(String videoFormat) {
    513             return VIDEO_FORMAT_TO_RESOLUTION_MAP.get(videoFormat);
    514         }
    515 
    516         /**
    517          * The ID of the TV input service that provides this TV channel.
    518          * <p>
    519          * Use {@link #buildInputId} to build the ID.
    520          * </p><p>
    521          * This is a required field.
    522          * </p><p>
    523          * Type: TEXT
    524          * </p>
    525          */
    526         public static final String COLUMN_INPUT_ID = "input_id";
    527 
    528         /**
    529          * The predefined type of this TV channel.
    530          * <p>
    531          * This is primarily used to indicate which broadcast standard (e.g. ATSC, DVB or ISDB) the
    532          * current channel conforms to. The value should match to one of the followings:
    533          * {@link #TYPE_OTHER}, {@link #TYPE_DVB_T}, {@link #TYPE_DVB_T2}, {@link #TYPE_DVB_S},
    534          * {@link #TYPE_DVB_S2}, {@link #TYPE_DVB_C}, {@link #TYPE_DVB_C2}, {@link #TYPE_DVB_H},
    535          * {@link #TYPE_DVB_SH}, {@link #TYPE_ATSC_T}, {@link #TYPE_ATSC_C},
    536          * {@link #TYPE_ATSC_M_H}, {@link #TYPE_ISDB_T}, {@link #TYPE_ISDB_TB},
    537          * {@link #TYPE_ISDB_S}, {@link #TYPE_ISDB_C}, {@link #TYPE_1SEG}, {@link #TYPE_DTMB},
    538          * {@link #TYPE_CMMB}, {@link #TYPE_T_DMB}, {@link #TYPE_S_DMB}
    539          * </p><p>
    540          * This is a required field.
    541          * </p><p>
    542          * Type: TEXT
    543          * </p>
    544          */
    545         public static final String COLUMN_TYPE = "type";
    546 
    547         /**
    548          * The predefined service type of this TV channel.
    549          * <p>
    550          * This is primarily used to indicate whether the current channel is a regular TV channel or
    551          * a radio-like channel. Use the same coding for {@code service_type} in the underlying
    552          * broadcast standard if it is defined there (e.g. ATSC A/53, ETSI EN 300 468 and ARIB
    553          * STD-B10). Otherwise use one of the followings: {@link #SERVICE_TYPE_OTHER},
    554          * {@link #SERVICE_TYPE_AUDIO_VIDEO}, {@link #SERVICE_TYPE_AUDIO}
    555          * </p><p>
    556          * This is a required field.
    557          * </p><p>
    558          * Type: TEXT
    559          * </p>
    560          */
    561         public static final String COLUMN_SERVICE_TYPE = "service_type";
    562 
    563         /**
    564          * The original network ID of this TV channel.
    565          * <p>
    566          * This is used to identify the originating delivery system, if applicable. Use the same
    567          * coding for {@code original_network_id} in the underlying broadcast standard if it is
    568          * defined there (e.g. ETSI EN 300 468/TR 101 211 and ARIB STD-B10). If channels cannot be
    569          * globally identified by 2-tuple {{@link #COLUMN_TRANSPORT_STREAM_ID},
    570          * {@link #COLUMN_SERVICE_ID}}, one must carefully assign a value to this field to form a
    571          * unique 3-tuple identification {{@link #COLUMN_ORIGINAL_NETWORK_ID},
    572          * {@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}} for its channels.
    573          * </p><p>
    574          * This is a required field if the channel cannot be uniquely identified by a 2-tuple
    575          * {{@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}}.
    576          * </p><p>
    577          * Type: INTEGER
    578          * </p>
    579          */
    580         public static final String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
    581 
    582         /**
    583          * The transport stream ID of this channel.
    584          * <p>
    585          * This is used to identify the Transport Stream that contains the current channel from any
    586          * other multiplex within a network, if applicable. Use the same coding for
    587          * {@code transport_stream_id} defined in ISO/IEC 13818-1 if the channel is transmitted via
    588          * the MPEG Transport Stream as is the case for many digital broadcast standards.
    589          * </p><p>
    590          * This is a required field if the current channel is transmitted via the MPEG Transport
    591          * Stream.
    592          * </p><p>
    593          * Type: INTEGER
    594          * </p>
    595          */
    596         public static final String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
    597 
    598         /**
    599          * The service ID of this channel.
    600          * <p>
    601          * This is used to identify the current service (roughly equivalent to channel) from any
    602          * other service within the Transport Stream, if applicable. Use the same coding for
    603          * {@code service_id} in the underlying broadcast standard if it is defined there (e.g. ETSI
    604          * EN 300 468 and ARIB STD-B10) or {@code program_number} (which usually has the same value
    605          * as {@code service_id}) in ISO/IEC 13818-1 if the channel is transmitted via the MPEG
    606          * Transport Stream.
    607          * </p><p>
    608          * This is a required field if the current channel is transmitted via the MPEG Transport
    609          * Stream.
    610          * </p><p>
    611          * Type: INTEGER
    612          * </p>
    613          */
    614         public static final String COLUMN_SERVICE_ID = "service_id";
    615 
    616         /**
    617          * The channel number that is displayed to the user.
    618          * <p>
    619          * The format can vary depending on broadcast standard and product specification.
    620          * </p><p>
    621          * Type: TEXT
    622          * </p>
    623          */
    624         public static final String COLUMN_DISPLAY_NUMBER = "display_number";
    625 
    626         /**
    627          * The channel name that is displayed to the user.
    628          * <p>
    629          * A call sign is a good candidate to use for this purpose but any name that helps the user
    630          * recognize the current channel will be enough. Can also be empty depending on broadcast
    631          * standard.
    632          * </p><p>
    633          * Type: TEXT
    634          * </p>
    635          */
    636         public static final String COLUMN_DISPLAY_NAME = "display_name";
    637 
    638         /**
    639          * The network affiliation for this TV channel.
    640          * <p>
    641          * This is used to identify a channel that is commonly called by its network affiliation
    642          * instead of the display name. Examples include ABC for the channel KGO-HD, FOX for the
    643          * channel KTVU-HD and NBC for the channel KNTV-HD. Can be empty if not applicable.
    644          * </p><p>
    645          * Type: TEXT
    646          * </p>
    647          */
    648         public static final String COLUMN_NETWORK_AFFILIATION = "network_affiliation";
    649 
    650         /**
    651          * The description of this TV channel.
    652          * <p>
    653          * Can be empty initially.
    654          * </p><p>
    655          * Type: TEXT
    656          * </p>
    657          */
    658         public static final String COLUMN_DESCRIPTION = "description";
    659 
    660         /**
    661          * The typical video format for programs from this TV channel.
    662          * <p>
    663          * This is primarily used to filter out channels based on video format by applications. The
    664          * value should match one of the followings: {@link #VIDEO_FORMAT_240P},
    665          * {@link #VIDEO_FORMAT_360P}, {@link #VIDEO_FORMAT_480I}, {@link #VIDEO_FORMAT_480P},
    666          * {@link #VIDEO_FORMAT_576I}, {@link #VIDEO_FORMAT_576P}, {@link #VIDEO_FORMAT_720P},
    667          * {@link #VIDEO_FORMAT_1080I}, {@link #VIDEO_FORMAT_1080P}, {@link #VIDEO_FORMAT_2160P},
    668          * {@link #VIDEO_FORMAT_4320P}. Note that the actual video resolution of each program from a
    669          * given channel can vary thus one should use {@link Programs#COLUMN_VIDEO_WIDTH} and
    670          * {@link Programs#COLUMN_VIDEO_HEIGHT} to get more accurate video resolution.
    671          * </p><p>
    672          * Type: TEXT
    673          * </p>
    674          * @see #getVideoResolution
    675          */
    676         public static final String COLUMN_VIDEO_FORMAT = "video_format";
    677 
    678         /**
    679          * The flag indicating whether this TV channel is browsable or not.
    680          * <p>
    681          * A value of 1 indicates the channel is included in the channel list that applications use
    682          * to browse channels, a value of 0 indicates the channel is not included in the list. If
    683          * not specified, this value is set to 0 (not browsable) by default.
    684          * </p><p>
    685          * Type: INTEGER (boolean)
    686          * </p>
    687          * @hide
    688          */
    689         @SystemApi
    690         public static final String COLUMN_BROWSABLE = "browsable";
    691 
    692         /**
    693          * The flag indicating whether this TV channel is searchable or not.
    694          * <p>
    695          * In some regions, it is not allowed to surface search results for a given channel without
    696          * broadcaster's consent. This is used to impose such restriction. Channels marked with
    697          * "not searchable" cannot be used by other services except for the system service that
    698          * shows the TV content. A value of 1 indicates the channel is searchable and can be
    699          * included in search results, a value of 0 indicates the channel and its TV programs are
    700          * hidden from search. If not specified, this value is set to 1 (searchable) by default.
    701          * </p><p>
    702          * Type: INTEGER (boolean)
    703          * </p>
    704          */
    705         public static final String COLUMN_SEARCHABLE = "searchable";
    706 
    707         /**
    708          * The flag indicating whether this TV channel is locked or not.
    709          * <p>
    710          * This is primarily used for alternative parental control to prevent unauthorized users
    711          * from watching the current channel regardless of the content rating. A value of 1
    712          * indicates the channel is locked and the user is required to enter passcode to unlock it
    713          * in order to watch the current program from the channel, a value of 0 indicates the
    714          * channel is not locked thus the user is not prompted to enter passcode If not specified,
    715          * this value is set to 0 (not locked) by default.
    716          * </p><p>
    717          * Type: INTEGER (boolean)
    718          * </p>
    719          * @hide
    720          */
    721         @SystemApi
    722         public static final String COLUMN_LOCKED = "locked";
    723 
    724         /**
    725          * Internal data used by individual TV input services.
    726          * <p>
    727          * This is internal to the provider that inserted it, and should not be decoded by other
    728          * apps.
    729          * </p><p>
    730          * Type: BLOB
    731          * </p>
    732          */
    733         public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
    734 
    735         /**
    736          * The version number of this row entry used by TV input services.
    737          * <p>
    738          * This is best used by sync adapters to identify the rows to update. The number can be
    739          * defined by individual TV input services. One may assign the same value as
    740          * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are
    741          * coming from a TV broadcast.
    742          * </p><p>
    743          * Type: INTEGER
    744          * </p>
    745          */
    746         public static final String COLUMN_VERSION_NUMBER = "version_number";
    747 
    748         private Channels() {}
    749 
    750         /**
    751          * A sub-directory of a single TV channel that represents its primary logo.
    752          * <p>
    753          * To access this directory, append {@link Channels.Logo#CONTENT_DIRECTORY} to the raw
    754          * channel URI.  The resulting URI represents an image file, and should be interacted
    755          * using ContentResolver.openAssetFileDescriptor.
    756          * </p><p>
    757          * Note that this sub-directory also supports opening the logo as an asset file in write
    758          * mode.  Callers can create or replace the primary logo associated with this channel by
    759          * opening the asset file and writing the full-size photo contents into it.  When the file
    760          * is closed, the image will be parsed, sized down if necessary, and stored.
    761          * </p><p>
    762          * Usage example:
    763          * <pre>
    764          * public void writeChannelLogo(long channelId, byte[] logo) {
    765          *     Uri channelLogoUri = TvContract.buildChannelLogoUri(channelId);
    766          *     try {
    767          *         AssetFileDescriptor fd =
    768          *             getContentResolver().openAssetFileDescriptor(channelLogoUri, "rw");
    769          *         OutputStream os = fd.createOutputStream();
    770          *         os.write(logo);
    771          *         os.close();
    772          *         fd.close();
    773          *     } catch (IOException e) {
    774          *         // Handle error cases.
    775          *     }
    776          * }
    777          * </pre>
    778          * </p>
    779          */
    780         public static final class Logo {
    781 
    782             /**
    783              * The directory twig for this sub-table.
    784              */
    785             public static final String CONTENT_DIRECTORY = "logo";
    786 
    787             private Logo() {}
    788         }
    789     }
    790 
    791     /** Column definitions for the TV programs table. */
    792     public static final class Programs implements BaseTvColumns {
    793 
    794         /** The content:// style URI for this table. */
    795         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
    796                 + PATH_PROGRAM);
    797 
    798         /** The MIME type of a directory of TV programs. */
    799         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/program";
    800 
    801         /** The MIME type of a single TV program. */
    802         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
    803 
    804         /**
    805          * The ID of the TV channel that provides this TV program.
    806          * <p>
    807          * This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
    808          * </p><p>
    809          * Type: INTEGER (long)
    810          * </p>
    811          */
    812         public static final String COLUMN_CHANNEL_ID = "channel_id";
    813 
    814         /**
    815          * The title of this TV program.
    816          * <p>
    817          * If this program is an episodic TV show, it is recommended that the title is the series
    818          * title and its related fields ({@link #COLUMN_SEASON_NUMBER},
    819          * {@link #COLUMN_EPISODE_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
    820          * </p><p>
    821          * Type: TEXT
    822          * </p>
    823          **/
    824         public static final String COLUMN_TITLE = "title";
    825 
    826         /**
    827          * The season number of this TV program for episodic TV shows.
    828          * <p>
    829          * Can be empty.
    830          * </p><p>
    831          * Type: INTEGER
    832          * </p>
    833          **/
    834         public static final String COLUMN_SEASON_NUMBER = "season_number";
    835 
    836         /**
    837          * The episode number of this TV program for episodic TV shows.
    838          * <p>
    839          * Can be empty.
    840          * </p><p>
    841          * Type: INTEGER
    842          * </p>
    843          **/
    844         public static final String COLUMN_EPISODE_NUMBER = "episode_number";
    845 
    846         /**
    847          * The episode title of this TV program for episodic TV shows.
    848          * <p>
    849          * Can be empty.
    850          * </p><p>
    851          * Type: TEXT
    852          * </p>
    853          **/
    854         public static final String COLUMN_EPISODE_TITLE = "episode_title";
    855 
    856         /**
    857          * The start time of this TV program, in milliseconds since the epoch.
    858          * <p>
    859          * The value should be equal to or larger than {@link #COLUMN_END_TIME_UTC_MILLIS} of the
    860          * previous program in the same channel.
    861          * </p><p>
    862          * Type: INTEGER (long)
    863          * </p>
    864          */
    865         public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
    866 
    867         /**
    868          * The end time of this TV program, in milliseconds since the epoch.
    869          * <p>
    870          * The value should be equal to or less than {@link #COLUMN_START_TIME_UTC_MILLIS} of the
    871          * next program in the same channel.
    872          * </p><p>
    873          * Type: INTEGER (long)
    874          * </p>
    875          */
    876         public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
    877 
    878         /**
    879          * The comma-separated genre string of this TV program.
    880          * <p>
    881          * Use the same language appeared in the underlying broadcast standard, if applicable. (For
    882          * example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
    883          * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty.
    884          * </p><p>
    885          * Type: TEXT
    886          * </p>
    887          */
    888         public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";
    889 
    890         /**
    891          * The comma-separated canonical genre string of this TV program.
    892          * <p>
    893          * Canonical genres are defined in {@link Genres}. Use {@link Genres#encode Genres.encode()}
    894          * to create a text that can be stored in this column. Use {@link Genres#decode
    895          * Genres.decode()} to get the canonical genre strings from the text stored in this column.
    896          * </p><p>
    897          * Type: TEXT
    898          * </p>
    899          * @see Genres
    900          */
    901         public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";
    902 
    903         /**
    904          * The short description of this TV program that is displayed to the user by default.
    905          * <p>
    906          * It is recommended to limit the length of the descriptions to 256 characters.
    907          * </p><p>
    908          * Type: TEXT
    909          * </p>
    910          */
    911         public static final String COLUMN_SHORT_DESCRIPTION = "short_description";
    912 
    913         /**
    914          * The detailed, lengthy description of this TV program that is displayed only when the user
    915          * wants to see more information.
    916          * <p>
    917          * TV input services should leave this field empty if they have no additional details beyond
    918          * {@link #COLUMN_SHORT_DESCRIPTION}.
    919          * </p><p>
    920          * Type: TEXT
    921          * </p>
    922          */
    923         public static final String COLUMN_LONG_DESCRIPTION = "long_description";
    924 
    925         /**
    926          * The width of the video for this TV program, in the unit of pixels.
    927          * <p>
    928          * Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video resolution
    929          * of the current TV program. Can be empty if it is not known initially or the program does
    930          * not convey any video such as the programs from type {@link Channels#SERVICE_TYPE_AUDIO}
    931          * channels.
    932          * </p><p>
    933          * Type: INTEGER
    934          * </p>
    935          */
    936         public static final String COLUMN_VIDEO_WIDTH = "video_width";
    937 
    938         /**
    939          * The height of the video for this TV program, in the unit of pixels.
    940          * <p>
    941          * Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video resolution
    942          * of the current TV program. Can be empty if it is not known initially or the program does
    943          * not convey any video such as the programs from type {@link Channels#SERVICE_TYPE_AUDIO}
    944          * channels.
    945          * </p><p>
    946          * Type: INTEGER
    947          * </p>
    948          */
    949         public static final String COLUMN_VIDEO_HEIGHT = "video_height";
    950 
    951         /**
    952          * The comma-separated audio languages of this TV program.
    953          * <p>
    954          * This is used to describe available audio languages included in the program. Use either
    955          * ISO 639-1 or 639-2/T codes.
    956          * </p><p>
    957          * Type: TEXT
    958          * </p>
    959          */
    960         public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
    961 
    962         /**
    963          * The comma-separated content ratings of this TV program.
    964          * <p>
    965          * This is used to describe the content rating(s) of this program. Each comma-separated
    966          * content rating sub-string should be generated by calling
    967          * {@link TvContentRating#flattenToString}. Note that in most cases the program content is
    968          * rated by a single rating system, thus resulting in a corresponding single sub-string that
    969          * does not require comma separation and multiple sub-strings appear only when the program
    970          * content is rated by two or more content rating systems. If any of those ratings is
    971          * specified as "blocked rating" in the user's parental control settings, the TV input
    972          * service should block the current content and wait for the signal that it is okay to
    973          * unblock.
    974          * </p><p>
    975          * Type: TEXT
    976          * </p>
    977          */
    978         public static final String COLUMN_CONTENT_RATING = "content_rating";
    979 
    980         /**
    981          * The URI for the poster art of this TV program.
    982          * <p>
    983          * Can be empty.
    984          * </p><p>
    985          * Type: TEXT
    986          * </p>
    987          */
    988         public static final String COLUMN_POSTER_ART_URI = "poster_art_uri";
    989 
    990         /**
    991          * The URI for the thumbnail of this TV program.
    992          * <p>
    993          * Can be empty.
    994          * </p><p>
    995          * Type: TEXT
    996          * </p>
    997          */
    998         public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
    999 
   1000         /**
   1001          * Internal data used by individual TV input services.
   1002          * <p>
   1003          * This is internal to the provider that inserted it, and should not be decoded by other
   1004          * apps.
   1005          * </p><p>
   1006          * Type: BLOB
   1007          * </p>
   1008          */
   1009         public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
   1010 
   1011         /**
   1012          * The version number of this row entry used by TV input services.
   1013          * <p>
   1014          * This is best used by sync adapters to identify the rows to update. The number can be
   1015          * defined by individual TV input services. One may assign the same value as
   1016          * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
   1017          * broadcast.
   1018          * </p><p>
   1019          * Type: INTEGER
   1020          * </p>
   1021          */
   1022         public static final String COLUMN_VERSION_NUMBER = "version_number";
   1023 
   1024         private Programs() {}
   1025 
   1026         /** Canonical genres for TV programs. */
   1027         public static final class Genres {
   1028             /** The genre for Family/Kids. */
   1029             public static final String FAMILY_KIDS = "FAMILY_KIDS";
   1030 
   1031             /** The genre for Sports. */
   1032             public static final String SPORTS = "SPORTS";
   1033 
   1034             /** The genre for Shopping. */
   1035             public static final String SHOPPING = "SHOPPING";
   1036 
   1037             /** The genre for Movies. */
   1038             public static final String MOVIES = "MOVIES";
   1039 
   1040             /** The genre for Comedy. */
   1041             public static final String COMEDY = "COMEDY";
   1042 
   1043             /** The genre for Travel. */
   1044             public static final String TRAVEL = "TRAVEL";
   1045 
   1046             /** The genre for Drama. */
   1047             public static final String DRAMA = "DRAMA";
   1048 
   1049             /** The genre for Education. */
   1050             public static final String EDUCATION = "EDUCATION";
   1051 
   1052             /** The genre for Animal/Wildlife. */
   1053             public static final String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE";
   1054 
   1055             /** The genre for News. */
   1056             public static final String NEWS = "NEWS";
   1057 
   1058             /** The genre for Gaming. */
   1059             public static final String GAMING = "GAMING";
   1060 
   1061             /** The genre for Arts. */
   1062             public static final String ARTS = "ARTS";
   1063 
   1064             /** The genre for Entertainment. */
   1065             public static final String ENTERTAINMENT = "ENTERTAINMENT";
   1066 
   1067             /** The genre for Life Style. */
   1068             public static final String LIFE_STYLE = "LIFE_STYLE";
   1069 
   1070             /** The genre for Music. */
   1071             public static final String MUSIC = "MUSIC";
   1072 
   1073             /** The genre for Premier. */
   1074             public static final String PREMIER = "PREMIER";
   1075 
   1076             /** The genre for Tech/Science. */
   1077             public static final String TECH_SCIENCE = "TECH_SCIENCE";
   1078 
   1079             private static final ArraySet<String> CANONICAL_GENRES = new ArraySet<String>();
   1080             static {
   1081                 CANONICAL_GENRES.add(FAMILY_KIDS);
   1082                 CANONICAL_GENRES.add(SPORTS);
   1083                 CANONICAL_GENRES.add(SHOPPING);
   1084                 CANONICAL_GENRES.add(MOVIES);
   1085                 CANONICAL_GENRES.add(COMEDY);
   1086                 CANONICAL_GENRES.add(TRAVEL);
   1087                 CANONICAL_GENRES.add(DRAMA);
   1088                 CANONICAL_GENRES.add(EDUCATION);
   1089                 CANONICAL_GENRES.add(ANIMAL_WILDLIFE);
   1090                 CANONICAL_GENRES.add(NEWS);
   1091                 CANONICAL_GENRES.add(GAMING);
   1092                 CANONICAL_GENRES.add(ARTS);
   1093                 CANONICAL_GENRES.add(ENTERTAINMENT);
   1094                 CANONICAL_GENRES.add(LIFE_STYLE);
   1095                 CANONICAL_GENRES.add(MUSIC);
   1096                 CANONICAL_GENRES.add(PREMIER);
   1097                 CANONICAL_GENRES.add(TECH_SCIENCE);
   1098             }
   1099 
   1100             private Genres() {}
   1101 
   1102             /**
   1103              * Encodes canonical genre strings to a text that can be put into the database.
   1104              *
   1105              * @param genres Canonical genre strings. Use the strings defined in this class.
   1106              * @return an encoded genre string that can be inserted into the
   1107              *         {@link #COLUMN_CANONICAL_GENRE} column.
   1108              */
   1109             public static String encode(String... genres) {
   1110                 StringBuilder sb = new StringBuilder();
   1111                 String separator = "";
   1112                 for (String genre : genres) {
   1113                     sb.append(separator).append(genre);
   1114                     separator = ",";
   1115                 }
   1116                 return sb.toString();
   1117             }
   1118 
   1119             /**
   1120              * Decodes the canonical genre strings from the text stored in the database.
   1121              *
   1122              * @param genres The encoded genre string retrieved from the
   1123              *            {@link #COLUMN_CANONICAL_GENRE} column.
   1124              * @return canonical genre strings.
   1125              */
   1126             public static String[] decode(String genres) {
   1127                 return genres.split("\\s*,\\s*");
   1128             }
   1129 
   1130             /**
   1131              * Check whether a given genre is canonical or not.
   1132              *
   1133              * @param genre The name of genre to be checked.
   1134              * @return {@code true} if the genre is canonical, otherwise {@code false}.
   1135              * @hide
   1136              */
   1137             @SystemApi
   1138             public static boolean isCanonical(String genre) {
   1139                 return CANONICAL_GENRES.contains(genre);
   1140             }
   1141         }
   1142     }
   1143 
   1144     /**
   1145      * Column definitions for the TV programs that the user watched. Applications do not have access
   1146      * to this table.
   1147      * @hide
   1148      */
   1149     @SystemApi
   1150     public static final class WatchedPrograms implements BaseTvColumns {
   1151 
   1152         /** The content:// style URI for this table. */
   1153         public static final Uri CONTENT_URI =
   1154                 Uri.parse("content://" + AUTHORITY + "/watched_program");
   1155 
   1156         /** The MIME type of a directory of watched programs. */
   1157         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watched_program";
   1158 
   1159         /** The MIME type of a single item in this table. */
   1160         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watched_program";
   1161 
   1162         /**
   1163          * The UTC time that the user started watching this TV program, in milliseconds since the
   1164          * epoch.
   1165          * <p>
   1166          * Type: INTEGER (long)
   1167          * </p>
   1168          */
   1169         public static final String COLUMN_WATCH_START_TIME_UTC_MILLIS =
   1170                 "watch_start_time_utc_millis";
   1171 
   1172         /**
   1173          * The UTC time that the user stopped watching this TV program, in milliseconds since the
   1174          * epoch.
   1175          * <p>
   1176          * Type: INTEGER (long)
   1177          * </p>
   1178          */
   1179         public static final String COLUMN_WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis";
   1180 
   1181         /**
   1182          * The ID of the TV channel that provides this TV program.
   1183          * <p>
   1184          * Type: INTEGER (long)
   1185          * </p>
   1186          */
   1187         public static final String COLUMN_CHANNEL_ID = "channel_id";
   1188 
   1189         /**
   1190          * The title of this TV program.
   1191          * <p>
   1192          * Type: TEXT
   1193          * </p>
   1194          */
   1195         public static final String COLUMN_TITLE = "title";
   1196 
   1197         /**
   1198          * The start time of this TV program, in milliseconds since the epoch.
   1199          * <p>
   1200          * Type: INTEGER (long)
   1201          * </p>
   1202          */
   1203         public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
   1204 
   1205         /**
   1206          * The end time of this TV program, in milliseconds since the epoch.
   1207          * <p>
   1208          * Type: INTEGER (long)
   1209          * </p>
   1210          */
   1211         public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
   1212 
   1213         /**
   1214          * The description of this TV program.
   1215          * <p>
   1216          * Type: TEXT
   1217          * </p>
   1218          */
   1219         public static final String COLUMN_DESCRIPTION = "description";
   1220 
   1221         /**
   1222          * Extra parameters given to {@link TvInputService.Session#tune(Uri, android.os.Bundle)
   1223          * TvInputService.Session.tune(Uri, android.os.Bundle)} when tuning to the channel that
   1224          * provides this TV program. (Used internally.)
   1225          * <p>
   1226          * This column contains an encoded string that represents comma-separated key-value pairs of
   1227          * the tune parameters. (Ex. "[key1]=[value1], [key2]=[value2]"). '%' is used as an escape
   1228          * character for '%', '=', and ','.
   1229          * </p><p>
   1230          * Type: TEXT
   1231          * </p>
   1232          */
   1233         public static final String COLUMN_INTERNAL_TUNE_PARAMS = "tune_params";
   1234 
   1235         /**
   1236          * The session token of this TV program. (Used internally.)
   1237          * <p>
   1238          * This contains a String representation of {@link IBinder} for
   1239          * {@link TvInputService.Session} that provides the current TV program. It is used
   1240          * internally to distinguish watched programs entries from different TV input sessions.
   1241          * </p><p>
   1242          * Type: TEXT
   1243          * </p>
   1244          */
   1245         public static final String COLUMN_INTERNAL_SESSION_TOKEN = "session_token";
   1246 
   1247         private WatchedPrograms() {}
   1248     }
   1249 }
   1250