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