TvContract.java revision bd23fa0ba1460a8d5194fd7c700030bf9c3f6fcb
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;
24
25import java.util.List;
26
27/**
28 * <p>
29 * The contract between the TV provider and applications. Contains definitions for the supported
30 * URIs and columns.
31 * </p>
32 * <h3>Overview</h3>
33 * <p>
34 * TvContract defines a basic database of TV content metadata such as channel and program
35 * information. The information is stored in {@link Channels} and {@link Programs} tables.
36 * </p>
37 * <ul>
38 *     <li>A row in the {@link Channels} table represents information about a TV channel. The data
39 *         format can vary greatly from standard to standard or according to service provider, thus
40 *         the columns here are mostly comprised of basic entities that are usually seen to users
41 *         regardless of standard such as channel number and name.</li>
42 *     <li>A row in the {@link Programs} table represents a set of data describing a TV program such
43 *         as program title and start time.</li>
44 * </ul>
45 */
46public final class TvContract {
47    /** The authority for the TV provider. */
48    public static final String AUTHORITY = "android.media.tv";
49
50    private static final String PATH_CHANNEL = "channel";
51    private static final String PATH_PROGRAM = "program";
52    private static final String PATH_INPUT = "input";
53
54    /**
55     * An optional query, update or delete URI parameter that allows the caller to specify start
56     * time (in milliseconds since the epoch) to filter programs.
57     *
58     * @hide
59     */
60    public static final String PARAM_START_TIME = "start_time";
61
62    /**
63     * An optional query, update or delete URI parameter that allows the caller to specify end time
64     * (in milliseconds since the epoch) to filter programs.
65     *
66     * @hide
67     */
68    public static final String PARAM_END_TIME = "end_time";
69
70    /**
71     * A query, update or delete URI parameter that allows the caller to operate on all or
72     * browsable-only channels. If set to "true", the rows that contain non-browsable channels are
73     * not affected.
74     *
75     * @hide
76     */
77    public static final String PARAM_BROWSABLE_ONLY = "browsable_only";
78
79    /**
80     * Builds a URI that points to a specific channel.
81     *
82     * @param channelId The ID of the channel to point to.
83     */
84    public static final Uri buildChannelUri(long channelId) {
85        return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId);
86    }
87
88    /**
89     * Builds a URI that points to all browsable channels from a given TV input.
90     *
91     * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
92     *            implements the given TV input.
93     */
94    public static final Uri buildChannelsUriForInput(ComponentName name) {
95        return buildChannelsUriForInput(name, true);
96    }
97
98    /**
99     * Builds a URI that points to all or browsable-only channels from a given TV input.
100     *
101     * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
102     *            implements the given TV input.
103     * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
104     *            to {@code false} the URI points to all channels regardless of whether they are
105     *            browsable or not.
106     */
107    public static final Uri buildChannelsUriForInput(ComponentName name, boolean browsableOnly) {
108        return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
109                .appendPath(PATH_INPUT).appendPath(name.getPackageName())
110                .appendPath(name.getClassName()).appendPath(PATH_CHANNEL)
111                .appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly)).build();
112    }
113
114    /**
115     * Builds a URI that points to a specific program.
116     *
117     * @param programId The ID of the program to point to.
118     */
119    public static final Uri buildProgramUri(long programId) {
120        return ContentUris.withAppendedId(Programs.CONTENT_URI, programId);
121    }
122
123    /**
124     * Builds a URI that points to all programs on a given channel.
125     *
126     * @param channelUri The URI of the channel to return programs for.
127     */
128    public static final Uri buildProgramsUriForChannel(Uri channelUri) {
129        if (!PATH_CHANNEL.equals(channelUri.getPathSegments().get(0))) {
130            throw new IllegalArgumentException("Not a channel: " + channelUri);
131        }
132        String channelId = String.valueOf(ContentUris.parseId(channelUri));
133        return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
134                .appendPath(PATH_CHANNEL).appendPath(channelId).appendPath(PATH_PROGRAM).build();
135    }
136
137    /**
138     * Builds a URI that points to programs on a specific channel whose schedules overlap with the
139     * given time frame.
140     *
141     * @param channelUri The URI of the channel to return programs for.
142     * @param startTime The start time used to filter programs. The returned programs should have
143     *            {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time.
144     * @param endTime The end time used to filter programs. The returned programs should have
145     *            {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time.
146     */
147    public static final Uri buildProgramsUriForChannel(Uri channelUri, long startTime,
148            long endTime) {
149        Uri uri = buildProgramsUriForChannel(channelUri);
150        return uri.buildUpon().appendQueryParameter(PARAM_START_TIME, String.valueOf(startTime))
151                .appendQueryParameter(PARAM_END_TIME, String.valueOf(endTime)).build();
152    }
153
154    /**
155     * Builds a URI that points to a specific program the user watched.
156     *
157     * @param watchedProgramId The ID of the watched program to point to.
158     * @hide
159     */
160    public static final Uri buildWatchedProgramUri(long watchedProgramId) {
161        return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId);
162    }
163
164    /**
165     * Extracts the {@link Channels#COLUMN_PACKAGE_NAME} from a given URI.
166     *
167     * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(ComponentName)} or
168     *            {@link #buildChannelsUriForInput(ComponentName, boolean)}.
169     * @hide
170     */
171    public static final String getPackageName(Uri channelsUri) {
172        final List<String> paths = channelsUri.getPathSegments();
173        if (paths.size() < 4) {
174            throw new IllegalArgumentException("Not channels: " + channelsUri);
175        }
176        if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(3))) {
177            throw new IllegalArgumentException("Not channels: " + channelsUri);
178        }
179        return paths.get(1);
180    }
181
182    /**
183     * Extracts the {@link Channels#COLUMN_SERVICE_NAME} from a given URI.
184     *
185     * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(ComponentName)} or
186     *            {@link #buildChannelsUriForInput(ComponentName, boolean)}.
187     * @hide
188     */
189    public static final String getServiceName(Uri channelsUri) {
190        final List<String> paths = channelsUri.getPathSegments();
191        if (paths.size() < 4) {
192            throw new IllegalArgumentException("Not channels: " + channelsUri);
193        }
194        if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(3))) {
195            throw new IllegalArgumentException("Not channels: " + channelsUri);
196        }
197        return paths.get(2);
198    }
199
200    /**
201     * Extracts the {@link Channels#_ID} from a given URI.
202     *
203     * @param programsUri A URI constructed by {@link #buildProgramsUriForChannel(Uri)} or
204     *            {@link #buildProgramsUriForChannel(Uri, long, long)}.
205     * @hide
206     */
207    public static final String getChannelId(Uri programsUri) {
208        final List<String> paths = programsUri.getPathSegments();
209        if (paths.size() < 3) {
210            throw new IllegalArgumentException("Not programs: " + programsUri);
211        }
212        if (!PATH_CHANNEL.equals(paths.get(0)) || !PATH_PROGRAM.equals(paths.get(2))) {
213            throw new IllegalArgumentException("Not programs: " + programsUri);
214        }
215        return paths.get(1);
216    }
217
218
219    private TvContract() {}
220
221    /**
222     * Common base for the tables of TV channels/programs.
223     */
224    public interface BaseTvColumns extends BaseColumns {
225        /**
226         * The name of the package that owns a row in each table.
227         * <p>
228         * The TV provider fills it in with the name of the package that provides the initial data
229         * of that row. If the package is later uninstalled, the rows it owns are automatically
230         * removed from the tables.
231         * </p><p>
232         * Type: TEXT
233         * </p>
234         */
235        public static final String COLUMN_PACKAGE_NAME = "package_name";
236    }
237
238    /** Column definitions for the TV channels table. */
239    public static final class Channels implements BaseTvColumns {
240
241        /** The content:// style URI for this table. */
242        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
243                + PATH_CHANNEL);
244
245        /** The MIME type of a directory of TV channels. */
246        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/channel";
247
248        /** The MIME type of a single TV channel. */
249        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
250
251        /** A generic channel type. */
252        public static final int TYPE_OTHER = 0x0;
253
254        /** The special channel type used for pass-through inputs such as HDMI. */
255        public static final int TYPE_PASSTHROUGH = 0x00010000;
256
257        /** The channel type for DVB-T (terrestrial). */
258        public static final int TYPE_DVB_T = 0x00020000;
259
260        /** The channel type for DVB-T2 (terrestrial). */
261        public static final int TYPE_DVB_T2 = 0x00020001;
262
263        /** The channel type for DVB-S (satellite). */
264        public static final int TYPE_DVB_S = 0x00020100;
265
266        /** The channel type for DVB-S2 (satellite). */
267        public static final int TYPE_DVB_S2 = 0x00020101;
268
269        /** The channel type for DVB-C (cable). */
270        public static final int TYPE_DVB_C = 0x00020200;
271
272        /** The channel type for DVB-C2 (cable). */
273        public static final int TYPE_DVB_C2 = 0x00020201;
274
275        /** The channel type for DVB-H (handheld). */
276        public static final int TYPE_DVB_H = 0x00020300;
277
278        /** The channel type for DVB-SH (satellite). */
279        public static final int TYPE_DVB_SH = 0x00020400;
280
281        /** The channel type for ATSC (terrestrial). */
282        public static final int TYPE_ATSC_T = 0x00030000;
283
284        /** The channel type for ATSC (cable). */
285        public static final int TYPE_ATSC_C = 0x00030200;
286
287        /** The channel type for ATSC-M/H (mobile/handheld). */
288        public static final int TYPE_ATSC_M_H = 0x00030200;
289
290        /** The channel type for ISDB-T (terrestrial). */
291        public static final int TYPE_ISDB_T = 0x00040000;
292
293        /** The channel type for ISDB-Tb (Brazil). */
294        public static final int TYPE_ISDB_TB = 0x00040100;
295
296        /** The channel type for ISDB-S (satellite). */
297        public static final int TYPE_ISDB_S = 0x00040200;
298
299        /** The channel type for ISDB-C (cable). */
300        public static final int TYPE_ISDB_C = 0x00040300;
301
302        /** The channel type for 1seg (handheld). */
303        public static final int TYPE_1SEG = 0x00040400;
304
305        /** The channel type for DTMB (terrestrial). */
306        public static final int TYPE_DTMB = 0x00050000;
307
308        /** The channel type for CMMB (handheld). */
309        public static final int TYPE_CMMB = 0x00050100;
310
311        /** The channel type for T-DMB (terrestrial). */
312        public static final int TYPE_T_DMB = 0x00060000;
313
314        /** The channel type for S-DMB (satellite). */
315        public static final int TYPE_S_DMB = 0x00060100;
316
317        /** A generic service type. */
318        public static final int SERVICE_TYPE_OTHER = 0x0;
319
320        /** The service type for regular TV channels that have both audio and video. */
321        public static final int SERVICE_TYPE_AUDIO_VIDEO = 0x1;
322
323        /** The service type for radio channels that have audio only. */
324        public static final int SERVICE_TYPE_AUDIO = 0x2;
325
326        /**
327         * The name of the {@link TvInputService} subclass that provides this TV channel. This
328         * should be a fully qualified class name (such as, "com.example.project.TvInputService").
329         * <p>
330         * This is a required field.
331         * </p><p>
332         * Type: TEXT
333         * </p>
334         */
335        public static final String COLUMN_SERVICE_NAME = "service_name";
336
337        /**
338         * The predefined type of this TV channel.
339         * <p>
340         * This is primarily used to indicate which broadcast standard (e.g. ATSC, DVB or ISDB) the
341         * current channel conforms to, with an exception being {@link #TYPE_PASSTHROUGH}, which is
342         * a special channel type used only by pass-through inputs such as HDMI. The value should
343         * match to one of the followings: {@link #TYPE_OTHER}, {@link #TYPE_PASSTHROUGH},
344         * {@link #TYPE_DVB_T}, {@link #TYPE_DVB_T2}, {@link #TYPE_DVB_S}, {@link #TYPE_DVB_S2},
345         * {@link #TYPE_DVB_C}, {@link #TYPE_DVB_C2}, {@link #TYPE_DVB_H}, {@link #TYPE_DVB_SH},
346         * {@link #TYPE_ATSC_T}, {@link #TYPE_ATSC_C}, {@link #TYPE_ATSC_M_H}, {@link #TYPE_ISDB_T},
347         * {@link #TYPE_ISDB_TB}, {@link #TYPE_ISDB_S}, {@link #TYPE_ISDB_C} {@link #TYPE_1SEG},
348         * {@link #TYPE_DTMB}, {@link #TYPE_CMMB}, {@link #TYPE_T_DMB}, {@link #TYPE_S_DMB}
349         * </p><p>
350         * This is a required field.
351         * </p><p>
352         * Type: INTEGER
353         * </p>
354         */
355        public static final String COLUMN_TYPE = "type";
356
357        /**
358         * The predefined service type of this TV channel.
359         * <p>
360         * This is primarily used to indicate whether the current channel is a regular TV channel or
361         * a radio-like channel. Use the same coding for {@code service_type} in the underlying
362         * broadcast standard if it is defined there (e.g. ATSC A/53, ETSI EN 300 468 and ARIB
363         * STD-B10). Otherwise use one of the followings: {@link #SERVICE_TYPE_OTHER},
364         * {@link #SERVICE_TYPE_AUDIO_VIDEO}, {@link #SERVICE_TYPE_AUDIO}
365         * </p><p>
366         * This is a required field.
367         * </p><p>
368         * Type: INTEGER
369         * </p>
370         */
371        public static final String COLUMN_SERVICE_TYPE = "service_type";
372
373        /**
374         * The original network ID of this TV channel.
375         * <p>
376         * This is used to identify the originating delivery system, if applicable. Use the same
377         * coding for {@code original_network_id} in the underlying broadcast standard if it is
378         * defined there (e.g. ETSI EN 300 468/TR 101 211 and ARIB STD-B10). If channels cannot be
379         * globally identified by 2-tuple {{@link #COLUMN_TRANSPORT_STREAM_ID},
380         * {@link #COLUMN_SERVICE_ID}}, one must carefully assign a value to this field to form a
381         * unique 3-tuple identification {{@link #COLUMN_ORIGINAL_NETWORK_ID},
382         * {@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}} for its channels.
383         * </p><p>
384         * This is a required field if the channel cannot be uniquely identified by a 2-tuple
385         * {{@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}}.
386         * </p><p>
387         * Type: INTEGER
388         * </p>
389         */
390        public static final String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
391
392        /**
393         * The transport stream ID of this channel.
394         * <p>
395         * This is used to identify the Transport Stream that contains the current channel from any
396         * other multiplex within a network, if applicable. Use the same coding for
397         * {@code transport_stream_id} defined in ISO/IEC 13818-1 if the channel is transmitted via
398         * the MPEG Transport Stream as is the case for many digital broadcast standards.
399         * </p><p>
400         * This is a required field if the current channel is transmitted via the MPEG Transport
401         * Stream.
402         * </p><p>
403         * Type: INTEGER
404         * </p>
405         */
406        public static final String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
407
408        /**
409         * The service ID of this channel.
410         * <p>
411         * This is used to identify the current service (roughly equivalent to channel) from any
412         * other service within the Transport Stream, if applicable. Use the same coding for
413         * {@code service_id} in the underlying broadcast standard if it is defined there (e.g. ETSI
414         * EN 300 468 and ARIB STD-B10) or {@code program_number} (which usually has the same value
415         * as {@code service_id}) in ISO/IEC 13818-1 if the channel is transmitted via the MPEG
416         * Transport Stream.
417         * </p><p>
418         * This is a required field if the current channel is transmitted via the MPEG Transport
419         * Stream.
420         * </p><p>
421         * Type: INTEGER
422         * </p>
423         */
424        public static final String COLUMN_SERVICE_ID = "service_id";
425
426        /**
427         * The channel number that is displayed to the user.
428         * <p>
429         * The format can vary depending on broadcast standard and product specification.
430         * </p><p>
431         * Type: TEXT
432         * </p>
433         */
434        public static final String COLUMN_DISPLAY_NUMBER = "display_number";
435
436        /**
437         * The channel name that is displayed to the user.
438         * <p>
439         * A call sign is a good candidate to use for this purpose but any name that helps the user
440         * recognize the current channel will be enough. Can also be empty depending on broadcast
441         * standard.
442         * </p><p>
443         * Type: TEXT
444         * </p>
445         */
446        public static final String COLUMN_DISPLAY_NAME = "display_name";
447
448        /**
449         * The description of this TV channel.
450         * <p>
451         * Can be empty initially.
452         * </p><p>
453         * Type: TEXT
454         * </p>
455         */
456        public static final String COLUMN_DESCRIPTION = "description";
457
458        /**
459         * The flag indicating whether this TV channel is browsable or not.
460         * <p>
461         * A value of 1 indicates the channel is included in the channel list that applications use
462         * to browse channels, a value of 0 indicates the channel is not included in the list. If
463         * not specified, this value is set to 1 (browsable) by default.
464         * </p><p>
465         * Type: INTEGER (boolean)
466         * </p>
467         */
468        public static final String COLUMN_BROWSABLE = "browsable";
469
470        /**
471         * The flag indicating whether this TV channel is searchable or not.
472         * <p>
473         * In some regions, it is not allowed to surface search results for a given channel without
474         * broadcaster's consent. This is used to impose such restriction. A value of 1 indicates
475         * the channel is searchable and can be included in search results, a value of 0 indicates
476         * the channel and its TV programs are hidden from search. If not specified, this value is
477         * set to 1 (searchable) by default.
478         * </p>
479         * <p>
480         * Type: INTEGER (boolean)
481         * </p>
482         */
483        public static final String COLUMN_SEARCHABLE = "searchable";
484
485        /**
486         * The flag indicating whether this TV channel is locked or not.
487         * <p>
488         * This is primarily used for alternative parental control to prevent unauthorized users
489         * from watching the current channel regardless of the content rating. A value of 1
490         * indicates the channel is locked and the user is required to enter passcode to unlock it
491         * in order to watch the current program from the channel, a value of 0 indicates the
492         * channel is not locked thus the user is not prompted to enter passcode If not specified,
493         * this value is set to 0 (not locked) by default.
494         * </p><p>
495         * Type: INTEGER (boolean)
496         * </p>
497         * @hide
498         */
499        public static final String COLUMN_LOCKED = "locked";
500
501        /**
502         * Internal data used by individual TV input services.
503         * <p>
504         * This is internal to the provider that inserted it, and should not be decoded by other
505         * apps.
506         * </p><p>
507         * Type: BLOB
508         * </p>
509         */
510        public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
511
512        /**
513         * The version number of this row entry used by TV input services.
514         * <p>
515         * This is best used by sync adapters to identify the rows to update. The number can be
516         * defined by individual TV input services. One may assign the same value as
517         * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are
518         * coming from a TV broadcast.
519         * </p><p>
520         * Type: INTEGER
521         * </p>
522         */
523        public static final String COLUMN_VERSION_NUMBER = "version_number";
524
525        private Channels() {}
526    }
527
528    /** Column definitions for the TV programs table. */
529    public static final class Programs implements BaseTvColumns {
530
531        /** The content:// style URI for this table. */
532        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
533                + PATH_PROGRAM);
534
535        /** The MIME type of a directory of TV programs. */
536        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/program";
537
538        /** The MIME type of a single TV program. */
539        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
540
541        /**
542         * The ID of the TV channel that contains this TV program.
543         * <p>
544         * This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
545         * </p><p>
546         * Type: INTEGER (long)
547         * </p>
548         */
549        public static final String COLUMN_CHANNEL_ID = "channel_id";
550
551        /**
552         * The title of this TV program.
553         * <p>
554         * Type: TEXT
555         * </p>
556         **/
557        public static final String COLUMN_TITLE = "title";
558
559        /**
560         * The start time of this TV program, in milliseconds since the epoch.
561         * <p>
562         * Type: INTEGER (long)
563         * </p>
564         */
565        public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
566
567        /**
568         * The end time of this TV program, in milliseconds since the epoch.
569         * <p>
570         * Type: INTEGER (long)
571         * </p>
572         */
573        public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
574
575        /**
576         * The comma-separated genre string of this TV program.
577         * <p>
578         * Use the same language appeared in the underlying broadcast standard, if applicable. (For
579         * example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
580         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty.
581         * </p><p>
582         * Type: TEXT
583         * </p>
584         */
585        public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";
586
587        /**
588         * The comma-separated canonical genre string of this TV program.
589         * <p>
590         * Canonical genres are defined in {@link Genres}. Use {@link Genres#encode Genres.encode()}
591         * to create a text that can be stored in this column. Use {@link Genres#decode
592         * Genres.decode()} to get the canonical genre strings from the text stored in this column.
593         * </p><p>
594         * Type: TEXT
595         * </p>
596         * @see Genres
597         */
598        public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";
599
600        /**
601         * The short description of this TV program that is displayed to the user by default.
602         * <p>
603         * It is recommended to limit the length of the descriptions to 256 characters.
604         * </p><p>
605         * Type: TEXT
606         * </p>
607         */
608        public static final String COLUMN_SHORT_DESCRIPTION = "short_description";
609
610        /**
611         * The detailed, lengthy description of this TV program that is displayed only when the user
612         * wants to see more information.
613         * <p>
614         * TV input services should leave this field empty if they have no additional details beyond
615         * {@link #COLUMN_SHORT_DESCRIPTION}.
616         * </p><p>
617         * Type: TEXT
618         * </p>
619         */
620        public static final String COLUMN_LONG_DESCRIPTION = "long_description";
621
622        /**
623         * The comma-separated audio languages of this TV program.
624         * <p>
625         * This is used to describe available audio languages included in the program. Use
626         * 3-character language code as specified by ISO 639-2.
627         * </p><p>
628         * Type: TEXT
629         * </p>
630         */
631        public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
632
633        /**
634         * Internal data used by individual TV input services.
635         * <p>
636         * This is internal to the provider that inserted it, and should not be decoded by other
637         * apps.
638         * </p><p>
639         * Type: BLOB
640         * </p>
641         */
642        public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
643
644        /**
645         * The version number of this row entry used by TV input services.
646         * <p>
647         * This is best used by sync adapters to identify the rows to update. The number can be
648         * defined by individual TV input services. One may assign the same value as
649         * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
650         * broadcast.
651         * </p><p>
652         * Type: INTEGER
653         * </p>
654         */
655        public static final String COLUMN_VERSION_NUMBER = "version_number";
656
657        private Programs() {}
658
659        /** Canonical genres for TV programs. */
660        public static final class Genres {
661            /** The genre for Family/Kids. */
662            public static final String FAMILY_KIDS = "Family/Kids";
663
664            /** The genre for Sports. */
665            public static final String SPORTS = "Sports";
666
667            /** The genre for Shopping. */
668            public static final String SHOPPING = "Shopping";
669
670            /** The genre for Movies. */
671            public static final String MOVIES = "Movies";
672
673            /** The genre for Comedy. */
674            public static final String COMEDY = "Comedy";
675
676            /** The genre for Travel. */
677            public static final String TRAVEL = "Travel";
678
679            /** The genre for Drama. */
680            public static final String DRAMA = "Drama";
681
682            /** The genre for Education. */
683            public static final String EDUCATION = "Education";
684
685            /** The genre for Animal/Wildlife. */
686            public static final String ANIMAL_WILDLIFE = "Animal/Wildlife";
687
688            /** The genre for News. */
689            public static final String NEWS = "News";
690
691            /** The genre for Gaming. */
692            public static final String GAMING = "Gaming";
693
694            private Genres() {}
695
696            /**
697             * Encodes canonical genre strings to a text that can be put into the database.
698             *
699             * @param genres Canonical genre strings. Use the strings defined in this class.
700             * @return an encoded genre string that can be inserted into the
701             *         {@link #COLUMN_CANONICAL_GENRE} column.
702             */
703            public static String encode(String... genres) {
704                StringBuilder sb = new StringBuilder();
705                String separator = "";
706                for (String genre : genres) {
707                    sb.append(separator).append(genre);
708                    separator = ",";
709                }
710                return sb.toString();
711            }
712
713            /**
714             * Decodes the canonical genre strings from the text stored in the database.
715             *
716             * @param genres The encoded genre string retrieved from the
717             *            {@link #COLUMN_CANONICAL_GENRE} column.
718             * @return canonical genre strings.
719             */
720            public static String[] decode(String genres) {
721                return genres.split("\\s*,\\s*");
722            }
723        }
724    }
725
726    /**
727     * Column definitions for the TV programs that the user watched. Applications do not have access
728     * to this table.
729     *
730     * @hide
731     */
732    public static final class WatchedPrograms implements BaseColumns {
733
734        /** The content:// style URI for this table. */
735        public static final Uri CONTENT_URI =
736                Uri.parse("content://" + AUTHORITY + "/watched_program");
737
738        /** The MIME type of a directory of watched programs. */
739        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watched_program";
740
741        /** The MIME type of a single item in this table. */
742        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watched_program";
743
744        /**
745         * The UTC time that the user started watching this TV program, in milliseconds since the
746         * epoch.
747         * <p>
748         * Type: INTEGER (long)
749         * </p>
750         */
751        public static final String COLUMN_WATCH_START_TIME_UTC_MILLIS =
752                "watch_start_time_utc_millis";
753
754        /**
755         * The UTC time that the user stopped watching this TV program, in milliseconds since the
756         * epoch.
757         * <p>
758         * Type: INTEGER (long)
759         * </p>
760         */
761        public static final String COLUMN_WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis";
762
763        /**
764         * The channel ID that contains this TV program.
765         * <p>
766         * Type: INTEGER (long)
767         * </p>
768         */
769        public static final String COLUMN_CHANNEL_ID = "channel_id";
770
771        /**
772         * The title of this TV program.
773         * <p>
774         * Type: TEXT
775         * </p>
776         */
777        public static final String COLUMN_TITLE = "title";
778
779        /**
780         * The start time of this TV program, in milliseconds since the epoch.
781         * <p>
782         * Type: INTEGER (long)
783         * </p>
784         */
785        public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
786
787        /**
788         * The end time of this TV program, in milliseconds since the epoch.
789         * <p>
790         * Type: INTEGER (long)
791         * </p>
792         */
793        public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
794
795        /**
796         * The description of this TV program.
797         * <p>
798         * Type: TEXT
799         * </p>
800         */
801        public static final String COLUMN_DESCRIPTION = "description";
802
803        private WatchedPrograms() {}
804    }
805}
806