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