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