1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.media.tv;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.annotation.SystemApi;
22import android.content.ComponentName;
23import android.content.ContentResolver;
24import android.content.ContentUris;
25import android.content.Intent;
26import android.net.Uri;
27import android.os.IBinder;
28import android.provider.BaseColumns;
29import android.text.TextUtils;
30import android.util.ArraySet;
31
32import java.util.ArrayList;
33import java.util.HashMap;
34import java.util.List;
35import java.util.Map;
36
37/**
38 * The contract between the TV provider and applications. Contains definitions for the supported
39 * URIs and columns.
40 * <h3>Overview</h3>
41 *
42 * <p>TvContract defines a basic database of TV content metadata such as channel and program
43 * information. The information is stored in {@link Channels} and {@link Programs} tables.
44 *
45 * <ul>
46 *     <li>A row in the {@link Channels} table represents information about a TV channel. The data
47 *         format can vary greatly from standard to standard or according to service provider, thus
48 *         the columns here are mostly comprised of basic entities that are usually seen to users
49 *         regardless of standard such as channel number and name.</li>
50 *     <li>A row in the {@link Programs} table represents a set of data describing a TV program such
51 *         as program title and start time.</li>
52 * </ul>
53 */
54public final class TvContract {
55    /** The authority for the TV provider. */
56    public static final String AUTHORITY = "android.media.tv";
57
58    /**
59     * Permission to read TV listings. This is required to read all the TV channel and program
60     * information available on the system.
61     * @hide
62     */
63    public static final String PERMISSION_READ_TV_LISTINGS = "android.permission.READ_TV_LISTINGS";
64
65    private static final String PATH_CHANNEL = "channel";
66    private static final String PATH_PROGRAM = "program";
67    private static final String PATH_RECORDED_PROGRAM = "recorded_program";
68    private static final String PATH_PASSTHROUGH = "passthrough";
69
70    /**
71     * An optional query, update or delete URI parameter that allows the caller to specify TV input
72     * ID to filter channels.
73     * @hide
74     */
75    public static final String PARAM_INPUT = "input";
76
77    /**
78     * An optional query, update or delete URI parameter that allows the caller to specify channel
79     * ID to filter programs.
80     * @hide
81     */
82    public static final String PARAM_CHANNEL = "channel";
83
84    /**
85     * An optional query, update or delete URI parameter that allows the caller to specify start
86     * time (in milliseconds since the epoch) to filter programs.
87     * @hide
88     */
89    public static final String PARAM_START_TIME = "start_time";
90
91    /**
92     * An optional query, update or delete URI parameter that allows the caller to specify end time
93     * (in milliseconds since the epoch) to filter programs.
94     * @hide
95     */
96    public static final String PARAM_END_TIME = "end_time";
97
98    /**
99     * A query, update or delete URI parameter that allows the caller to operate on all or
100     * browsable-only channels. If set to "true", the rows that contain non-browsable channels are
101     * not affected.
102     * @hide
103     */
104    public static final String PARAM_BROWSABLE_ONLY = "browsable_only";
105
106    /**
107     * A optional query, update or delete URI parameter that allows the caller to specify canonical
108     * genre to filter programs.
109     * @hide
110     */
111    public static final String PARAM_CANONICAL_GENRE = "canonical_genre";
112
113    /**
114     * Builds an ID that uniquely identifies a TV input service.
115     *
116     * @param name The {@link ComponentName} of the TV input service to build ID for.
117     * @return the ID for the given TV input service.
118     */
119    public static final String buildInputId(ComponentName name) {
120        return name.flattenToShortString();
121    }
122
123    /**
124     * Builds a URI that points to a specific channel.
125     *
126     * @param channelId The ID of the channel to point to.
127     */
128    public static final Uri buildChannelUri(long channelId) {
129        return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId);
130    }
131
132    /**
133     * Build a special channel URI intended to be used with pass-through inputs. (e.g. HDMI)
134     *
135     * @param inputId The ID of the pass-through input to build a channels URI for.
136     * @see TvInputInfo#isPassthroughInput()
137     */
138    public static final Uri buildChannelUriForPassthroughInput(String inputId) {
139        return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
140                .appendPath(PATH_PASSTHROUGH).appendPath(inputId).build();
141    }
142
143    /**
144     * Builds a URI that points to a channel logo. See {@link Channels.Logo}.
145     *
146     * @param channelId The ID of the channel whose logo is pointed to.
147     */
148    public static final Uri buildChannelLogoUri(long channelId) {
149        return buildChannelLogoUri(buildChannelUri(channelId));
150    }
151
152    /**
153     * Builds a URI that points to a channel logo. See {@link Channels.Logo}.
154     *
155     * @param channelUri The URI of the channel whose logo is pointed to.
156     */
157    public static final Uri buildChannelLogoUri(Uri channelUri) {
158        if (!isChannelUriForTunerInput(channelUri)) {
159            throw new IllegalArgumentException("Not a channel: " + channelUri);
160        }
161        return Uri.withAppendedPath(channelUri, Channels.Logo.CONTENT_DIRECTORY);
162    }
163
164    /**
165     * Builds a URI that points to all channels from a given TV input.
166     *
167     * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
168     *            URI for all the TV inputs.
169     */
170    public static final Uri buildChannelsUriForInput(@Nullable String inputId) {
171        return buildChannelsUriForInput(inputId, false);
172    }
173
174    /**
175     * Builds a URI that points to all or browsable-only channels from a given TV input.
176     *
177     * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
178     *            URI for all the TV inputs.
179     * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
180     *            to {@code false} the URI points to all channels regardless of whether they are
181     *            browsable or not.
182     * @hide
183     */
184    @SystemApi
185    public static final Uri buildChannelsUriForInput(@Nullable String inputId,
186            boolean browsableOnly) {
187        Uri.Builder builder = Channels.CONTENT_URI.buildUpon();
188        if (inputId != null) {
189            builder.appendQueryParameter(PARAM_INPUT, inputId);
190        }
191        return builder.appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly))
192                .build();
193    }
194
195    /**
196     * Builds a URI that points to all or browsable-only channels which have programs with the given
197     * genre from the given TV input.
198     *
199     * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
200     *            URI for all the TV inputs.
201     * @param genre {@link Programs.Genres} to search. If {@code null}, builds a URI for all genres.
202     * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
203     *            to {@code false} the URI points to all channels regardless of whether they are
204     *            browsable or not.
205     * @hide
206     */
207    @SystemApi
208    public static final Uri buildChannelsUriForInput(@Nullable String inputId,
209            @Nullable String genre, boolean browsableOnly) {
210        if (genre == null) {
211            return buildChannelsUriForInput(inputId, browsableOnly);
212        }
213        if (!Programs.Genres.isCanonical(genre)) {
214            throw new IllegalArgumentException("Not a canonical genre: '" + genre + "'");
215        }
216        return buildChannelsUriForInput(inputId, browsableOnly).buildUpon()
217                .appendQueryParameter(PARAM_CANONICAL_GENRE, genre).build();
218    }
219
220    /**
221     * Builds a URI that points to a specific program.
222     *
223     * @param programId The ID of the program to point to.
224     */
225    public static final Uri buildProgramUri(long programId) {
226        return ContentUris.withAppendedId(Programs.CONTENT_URI, programId);
227    }
228
229    /**
230     * Builds a URI that points to all programs on a given channel.
231     *
232     * @param channelId The ID of the channel to return programs for.
233     */
234    public static final Uri buildProgramsUriForChannel(long channelId) {
235        return Programs.CONTENT_URI.buildUpon()
236                .appendQueryParameter(PARAM_CHANNEL, String.valueOf(channelId)).build();
237    }
238
239    /**
240     * Builds a URI that points to all programs on a given channel.
241     *
242     * @param channelUri The URI of the channel to return programs for.
243     */
244    public static final Uri buildProgramsUriForChannel(Uri channelUri) {
245        if (!isChannelUriForTunerInput(channelUri)) {
246            throw new IllegalArgumentException("Not a channel: " + channelUri);
247        }
248        return buildProgramsUriForChannel(ContentUris.parseId(channelUri));
249    }
250
251    /**
252     * Builds a URI that points to programs on a specific channel whose schedules overlap with the
253     * given time frame.
254     *
255     * @param channelId The ID of the channel to return programs for.
256     * @param startTime The start time used to filter programs. The returned programs should have
257     *            {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time.
258     * @param endTime The end time used to filter programs. The returned programs should have
259     *            {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time.
260     */
261    public static final Uri buildProgramsUriForChannel(long channelId, long startTime,
262            long endTime) {
263        Uri uri = buildProgramsUriForChannel(channelId);
264        return uri.buildUpon().appendQueryParameter(PARAM_START_TIME, String.valueOf(startTime))
265                .appendQueryParameter(PARAM_END_TIME, String.valueOf(endTime)).build();
266    }
267
268    /**
269     * Builds a URI that points to programs on a specific channel whose schedules overlap with the
270     * given time frame.
271     *
272     * @param channelUri The URI of the channel to return programs for.
273     * @param startTime The start time used to filter programs. The returned programs should have
274     *            {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time.
275     * @param endTime The end time used to filter programs. The returned programs should have
276     *            {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time.
277     */
278    public static final Uri buildProgramsUriForChannel(Uri channelUri, long startTime,
279            long endTime) {
280        if (!isChannelUriForTunerInput(channelUri)) {
281            throw new IllegalArgumentException("Not a channel: " + channelUri);
282        }
283        return buildProgramsUriForChannel(ContentUris.parseId(channelUri), startTime, endTime);
284    }
285
286    /**
287     * Builds a URI that points to a specific recorded program.
288     *
289     * @param recordedProgramId The ID of the recorded program to point to.
290     */
291    public static final Uri buildRecordedProgramUri(long recordedProgramId) {
292        return ContentUris.withAppendedId(RecordedPrograms.CONTENT_URI, recordedProgramId);
293    }
294
295    /**
296     * Builds a URI that points to a specific program the user watched.
297     *
298     * @param watchedProgramId The ID of the watched program to point to.
299     * @hide
300     */
301    public static final Uri buildWatchedProgramUri(long watchedProgramId) {
302        return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId);
303    }
304
305    private static boolean isTvUri(Uri uri) {
306        return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())
307                && AUTHORITY.equals(uri.getAuthority());
308    }
309
310    private static boolean isTwoSegmentUriStartingWith(Uri uri, String pathSegment) {
311        List<String> pathSegments = uri.getPathSegments();
312        return pathSegments.size() == 2 && pathSegment.equals(pathSegments.get(0));
313    }
314
315    /**
316     * Returns {@code true}, if {@code uri} is a channel URI.
317     */
318    public static final boolean isChannelUri(Uri uri) {
319        return isChannelUriForTunerInput(uri) || isChannelUriForPassthroughInput(uri);
320    }
321
322    /**
323     * Returns {@code true}, if {@code uri} is a channel URI for a tuner input.
324     */
325    public static final boolean isChannelUriForTunerInput(Uri uri) {
326        return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_CHANNEL);
327    }
328
329    /**
330     * Returns {@code true}, if {@code uri} is a channel URI for a pass-through input.
331     */
332    public static final boolean isChannelUriForPassthroughInput(Uri uri) {
333        return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PASSTHROUGH);
334    }
335
336    /**
337     * Returns {@code true}, if {@code uri} is a program URI.
338     */
339    public static final boolean isProgramUri(Uri uri) {
340        return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM);
341    }
342
343
344    private TvContract() {}
345
346    /**
347     * Common base for the tables of TV channels/programs.
348     */
349    public interface BaseTvColumns extends BaseColumns {
350        /**
351         * The name of the package that owns the current row.
352         *
353         * <p>The TV provider fills in this column with the name of the package that provides the
354         * initial data of the row. If the package is later uninstalled, the rows it owns are
355         * automatically removed from the tables.
356         *
357         * <p>Type: TEXT
358         */
359        String COLUMN_PACKAGE_NAME = "package_name";
360    }
361
362    /** Column definitions for the TV channels table. */
363    public static final class Channels implements BaseTvColumns {
364
365        /** The content:// style URI for this table. */
366        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
367                + PATH_CHANNEL);
368
369        /** The MIME type of a directory of TV channels. */
370        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/channel";
371
372        /** The MIME type of a single TV channel. */
373        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
374
375        /**
376         * A generic channel type.
377         *
378         * Use this if the current channel is streaming-based or its broadcast system type does not
379         * fit under any other types. This is the default channel type.
380         *
381         * @see #COLUMN_TYPE
382         */
383        public static final String TYPE_OTHER = "TYPE_OTHER";
384
385        /**
386         * The channel type for NTSC.
387         *
388         * @see #COLUMN_TYPE
389         */
390        public static final String TYPE_NTSC = "TYPE_NTSC";
391
392        /**
393         * The channel type for PAL.
394         *
395         * @see #COLUMN_TYPE
396         */
397        public static final String TYPE_PAL = "TYPE_PAL";
398
399        /**
400         * The channel type for SECAM.
401         *
402         * @see #COLUMN_TYPE
403         */
404        public static final String TYPE_SECAM = "TYPE_SECAM";
405
406        /**
407         * The channel type for DVB-T (terrestrial).
408         *
409         * @see #COLUMN_TYPE
410         */
411        public static final String TYPE_DVB_T = "TYPE_DVB_T";
412
413        /**
414         * The channel type for DVB-T2 (terrestrial).
415         *
416         * @see #COLUMN_TYPE
417         */
418        public static final String TYPE_DVB_T2 = "TYPE_DVB_T2";
419
420        /**
421         * The channel type for DVB-S (satellite).
422         *
423         * @see #COLUMN_TYPE
424         */
425        public static final String TYPE_DVB_S = "TYPE_DVB_S";
426
427        /**
428         * The channel type for DVB-S2 (satellite).
429         *
430         * @see #COLUMN_TYPE
431         */
432        public static final String TYPE_DVB_S2 = "TYPE_DVB_S2";
433
434        /**
435         * The channel type for DVB-C (cable).
436         *
437         * @see #COLUMN_TYPE
438         */
439        public static final String TYPE_DVB_C = "TYPE_DVB_C";
440
441        /**
442         * The channel type for DVB-C2 (cable).
443         *
444         * @see #COLUMN_TYPE
445         */
446        public static final String TYPE_DVB_C2 = "TYPE_DVB_C2";
447
448        /**
449         * The channel type for DVB-H (handheld).
450         *
451         * @see #COLUMN_TYPE
452         */
453        public static final String TYPE_DVB_H = "TYPE_DVB_H";
454
455        /**
456         * The channel type for DVB-SH (satellite).
457         *
458         * @see #COLUMN_TYPE
459         */
460        public static final String TYPE_DVB_SH = "TYPE_DVB_SH";
461
462        /**
463         * The channel type for ATSC (terrestrial).
464         *
465         * @see #COLUMN_TYPE
466         */
467        public static final String TYPE_ATSC_T = "TYPE_ATSC_T";
468
469        /**
470         * The channel type for ATSC (cable).
471         *
472         * @see #COLUMN_TYPE
473         */
474        public static final String TYPE_ATSC_C = "TYPE_ATSC_C";
475
476        /**
477         * The channel type for ATSC-M/H (mobile/handheld).
478         *
479         * @see #COLUMN_TYPE
480         */
481        public static final String TYPE_ATSC_M_H = "TYPE_ATSC_M_H";
482
483        /**
484         * The channel type for ISDB-T (terrestrial).
485         *
486         * @see #COLUMN_TYPE
487         */
488        public static final String TYPE_ISDB_T = "TYPE_ISDB_T";
489
490        /**
491         * The channel type for ISDB-Tb (Brazil).
492         *
493         * @see #COLUMN_TYPE
494         */
495        public static final String TYPE_ISDB_TB = "TYPE_ISDB_TB";
496
497        /**
498         * The channel type for ISDB-S (satellite).
499         *
500         * @see #COLUMN_TYPE
501         */
502        public static final String TYPE_ISDB_S = "TYPE_ISDB_S";
503
504        /**
505         * The channel type for ISDB-C (cable).
506         *
507         * @see #COLUMN_TYPE
508         */
509        public static final String TYPE_ISDB_C = "TYPE_ISDB_C";
510
511        /**
512         * The channel type for 1seg (handheld).
513         *
514         * @see #COLUMN_TYPE
515         */
516        public static final String TYPE_1SEG = "TYPE_1SEG";
517
518        /**
519         * The channel type for DTMB (terrestrial).
520         *
521         * @see #COLUMN_TYPE
522         */
523        public static final String TYPE_DTMB = "TYPE_DTMB";
524
525        /**
526         * The channel type for CMMB (handheld).
527         *
528         * @see #COLUMN_TYPE
529         */
530        public static final String TYPE_CMMB = "TYPE_CMMB";
531
532        /**
533         * The channel type for T-DMB (terrestrial).
534         *
535         * @see #COLUMN_TYPE
536         */
537        public static final String TYPE_T_DMB = "TYPE_T_DMB";
538
539        /**
540         * The channel type for S-DMB (satellite).
541         *
542         * @see #COLUMN_TYPE
543         */
544        public static final String TYPE_S_DMB = "TYPE_S_DMB";
545
546        /** A generic service type. */
547        public static final String SERVICE_TYPE_OTHER = "SERVICE_TYPE_OTHER";
548
549        /** The service type for regular TV channels that have both audio and video. */
550        public static final String SERVICE_TYPE_AUDIO_VIDEO = "SERVICE_TYPE_AUDIO_VIDEO";
551
552        /** The service type for radio channels that have audio only. */
553        public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO";
554
555        /** The video format for 240p. */
556        public static final String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P";
557
558        /** The video format for 360p. */
559        public static final String VIDEO_FORMAT_360P = "VIDEO_FORMAT_360P";
560
561        /** The video format for 480i. */
562        public static final String VIDEO_FORMAT_480I = "VIDEO_FORMAT_480I";
563
564        /** The video format for 480p. */
565        public static final String VIDEO_FORMAT_480P = "VIDEO_FORMAT_480P";
566
567        /** The video format for 576i. */
568        public static final String VIDEO_FORMAT_576I = "VIDEO_FORMAT_576I";
569
570        /** The video format for 576p. */
571        public static final String VIDEO_FORMAT_576P = "VIDEO_FORMAT_576P";
572
573        /** The video format for 720p. */
574        public static final String VIDEO_FORMAT_720P = "VIDEO_FORMAT_720P";
575
576        /** The video format for 1080i. */
577        public static final String VIDEO_FORMAT_1080I = "VIDEO_FORMAT_1080I";
578
579        /** The video format for 1080p. */
580        public static final String VIDEO_FORMAT_1080P = "VIDEO_FORMAT_1080P";
581
582        /** The video format for 2160p. */
583        public static final String VIDEO_FORMAT_2160P = "VIDEO_FORMAT_2160P";
584
585        /** The video format for 4320p. */
586        public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P";
587
588        /** The video resolution for standard-definition. */
589        public static final String VIDEO_RESOLUTION_SD = "VIDEO_RESOLUTION_SD";
590
591        /** The video resolution for enhanced-definition. */
592        public static final String VIDEO_RESOLUTION_ED = "VIDEO_RESOLUTION_ED";
593
594        /** The video resolution for high-definition. */
595        public static final String VIDEO_RESOLUTION_HD = "VIDEO_RESOLUTION_HD";
596
597        /** The video resolution for full high-definition. */
598        public static final String VIDEO_RESOLUTION_FHD = "VIDEO_RESOLUTION_FHD";
599
600        /** The video resolution for ultra high-definition. */
601        public static final String VIDEO_RESOLUTION_UHD = "VIDEO_RESOLUTION_UHD";
602
603        private static final Map<String, String> VIDEO_FORMAT_TO_RESOLUTION_MAP = new HashMap<>();
604
605        static {
606            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480I, VIDEO_RESOLUTION_SD);
607            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480P, VIDEO_RESOLUTION_ED);
608            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576I, VIDEO_RESOLUTION_SD);
609            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576P, VIDEO_RESOLUTION_ED);
610            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_720P, VIDEO_RESOLUTION_HD);
611            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080I, VIDEO_RESOLUTION_HD);
612            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080P, VIDEO_RESOLUTION_FHD);
613            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_2160P, VIDEO_RESOLUTION_UHD);
614            VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_4320P, VIDEO_RESOLUTION_UHD);
615        }
616
617        /**
618         * Returns the video resolution (definition) for a given video format.
619         *
620         * @param videoFormat The video format defined in {@link Channels}.
621         * @return the corresponding video resolution string. {@code null} if the resolution string
622         *         is not defined for the given video format.
623         * @see #COLUMN_VIDEO_FORMAT
624         */
625        @Nullable
626        public static final String getVideoResolution(String videoFormat) {
627            return VIDEO_FORMAT_TO_RESOLUTION_MAP.get(videoFormat);
628        }
629
630        /**
631         * The ID of the TV input service that provides this TV channel.
632         *
633         * <p>Use {@link #buildInputId} to build the ID.
634         *
635         * <p>This is a required field.
636         *
637         * <p>Type: TEXT
638         */
639        public static final String COLUMN_INPUT_ID = "input_id";
640
641        /**
642         * The broadcast system type of this TV channel.
643         *
644         * <p>This is used to indicate the broadcast standard (e.g. ATSC, DVB or ISDB) the current
645         * channel conforms to. Use {@link #TYPE_OTHER} for streaming-based channels, which is the
646         * default channel type. The value should match to one of the followings:
647         * {@link #TYPE_1SEG},
648         * {@link #TYPE_ATSC_C},
649         * {@link #TYPE_ATSC_M_H},
650         * {@link #TYPE_ATSC_T},
651         * {@link #TYPE_CMMB},
652         * {@link #TYPE_DTMB},
653         * {@link #TYPE_DVB_C},
654         * {@link #TYPE_DVB_C2},
655         * {@link #TYPE_DVB_H},
656         * {@link #TYPE_DVB_S},
657         * {@link #TYPE_DVB_S2},
658         * {@link #TYPE_DVB_SH},
659         * {@link #TYPE_DVB_T},
660         * {@link #TYPE_DVB_T2},
661         * {@link #TYPE_ISDB_C},
662         * {@link #TYPE_ISDB_S},
663         * {@link #TYPE_ISDB_T},
664         * {@link #TYPE_ISDB_TB},
665         * {@link #TYPE_NTSC},
666         * {@link #TYPE_OTHER},
667         * {@link #TYPE_PAL},
668         * {@link #TYPE_SECAM},
669         * {@link #TYPE_S_DMB}, and
670         * {@link #TYPE_T_DMB}.
671         *
672         * <p>This is a required field.
673         *
674         * <p>Type: TEXT
675         */
676        public static final String COLUMN_TYPE = "type";
677
678        /**
679         * The predefined service type of this TV channel.
680         *
681         * <p>This is primarily used to indicate whether the current channel is a regular TV channel
682         * or a radio-like channel. Use the same coding for {@code service_type} in the underlying
683         * broadcast standard if it is defined there (e.g. ATSC A/53, ETSI EN 300 468 and ARIB
684         * STD-B10). Otherwise use one of the followings: {@link #SERVICE_TYPE_OTHER},
685         * {@link #SERVICE_TYPE_AUDIO_VIDEO}, {@link #SERVICE_TYPE_AUDIO}
686         *
687         * <p>This is a required field.
688         *
689         * <p>Type: TEXT
690         */
691        public static final String COLUMN_SERVICE_TYPE = "service_type";
692
693        /**
694         * The original network ID of this TV channel.
695         *
696         * <p>It is used to identify the originating delivery system, if applicable. Use the same
697         * coding for {@code original_network_id} for ETSI EN 300 468/TR 101 211 and ARIB STD-B10.
698         *
699         * <p>This is a required field only if the underlying broadcast standard defines the same
700         * name field. Otherwise, leave empty.
701         *
702         * <p>Type: INTEGER
703         */
704        public static final String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
705
706        /**
707         * The transport stream ID of this channel.
708         *
709         * <p>It is used to identify the Transport Stream that contains the current channel from any
710         * other multiplex within a network, if applicable. Use the same coding for
711         * {@code transport_stream_id} defined in ISO/IEC 13818-1 if the channel is transmitted via
712         * the MPEG Transport Stream.
713         *
714         * <p>This is a required field only if the current channel is transmitted via the MPEG
715         * Transport Stream. Leave empty otherwise.
716         *
717         * <p>Type: INTEGER
718         */
719        public static final String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
720
721        /**
722         * The service ID of this channel.
723         *
724         * <p>It is used to identify the current service, or channel from any other services within
725         * a given Transport Stream, if applicable. Use the same coding for {@code service_id} in
726         * ETSI EN 300 468 and ARIB STD-B10 or {@code program_number} in ISO/IEC 13818-1.
727         *
728         * <p>This is a required field only if the underlying broadcast standard defines the same
729         * name field, or the current channel is transmitted via the MPEG Transport Stream. Leave
730         * empty otherwise.
731         *
732         * <p>Type: INTEGER
733         */
734        public static final String COLUMN_SERVICE_ID = "service_id";
735
736        /**
737         * The channel number that is displayed to the user.
738         *
739         * <p>The format can vary depending on broadcast standard and product specification.
740         *
741         * <p>Type: TEXT
742         */
743        public static final String COLUMN_DISPLAY_NUMBER = "display_number";
744
745        /**
746         * The channel name that is displayed to the user.
747         *
748         * <p>A call sign is a good candidate to use for this purpose but any name that helps the
749         * user recognize the current channel will be enough. Can also be empty depending on
750         * broadcast standard.
751         *
752         * <p> Type: TEXT
753         */
754        public static final String COLUMN_DISPLAY_NAME = "display_name";
755
756        /**
757         * The network affiliation for this TV channel.
758         *
759         * <p>This is used to identify a channel that is commonly called by its network affiliation
760         * instead of the display name. Examples include ABC for the channel KGO-HD, FOX for the
761         * channel KTVU-HD and NBC for the channel KNTV-HD. Can be empty if not applicable.
762         *
763         * <p>Type: TEXT
764         */
765        public static final String COLUMN_NETWORK_AFFILIATION = "network_affiliation";
766
767        /**
768         * The description of this TV channel.
769         *
770         * <p>Can be empty initially.
771         *
772         * <p>Type: TEXT
773         */
774        public static final String COLUMN_DESCRIPTION = "description";
775
776        /**
777         * The typical video format for programs from this TV channel.
778         *
779         * <p>This is primarily used to filter out channels based on video format by applications.
780         * The value should match one of the followings: {@link #VIDEO_FORMAT_240P},
781         * {@link #VIDEO_FORMAT_360P}, {@link #VIDEO_FORMAT_480I}, {@link #VIDEO_FORMAT_480P},
782         * {@link #VIDEO_FORMAT_576I}, {@link #VIDEO_FORMAT_576P}, {@link #VIDEO_FORMAT_720P},
783         * {@link #VIDEO_FORMAT_1080I}, {@link #VIDEO_FORMAT_1080P}, {@link #VIDEO_FORMAT_2160P},
784         * {@link #VIDEO_FORMAT_4320P}. Note that the actual video resolution of each program from a
785         * given channel can vary thus one should use {@link Programs#COLUMN_VIDEO_WIDTH} and
786         * {@link Programs#COLUMN_VIDEO_HEIGHT} to get more accurate video resolution.
787         *
788         * <p>Type: TEXT
789         *
790         * @see #getVideoResolution
791         */
792        public static final String COLUMN_VIDEO_FORMAT = "video_format";
793
794        /**
795         * The flag indicating whether this TV channel is browsable or not.
796         *
797         * <p>A value of 1 indicates the channel is included in the channel list that applications
798         * use to browse channels, a value of 0 indicates the channel is not included in the list.
799         * If not specified, this value is set to 0 (not browsable) by default.
800         *
801         * <p>Type: INTEGER (boolean)
802         * @hide
803         */
804        @SystemApi
805        public static final String COLUMN_BROWSABLE = "browsable";
806
807        /**
808         * The flag indicating whether this TV channel is searchable or not.
809         *
810         * <p>The columns of searchable channels can be read by other applications that have proper
811         * permission. Care must be taken not to open sensitive data.
812         *
813         * <p>A value of 1 indicates that the channel is searchable and its columns can be read by
814         * other applications, a value of 0 indicates that the channel is hidden and its columns can
815         * be read only by the package that owns the channel and the system. If not specified, this
816         * value is set to 1 (searchable) by default.
817         *
818         * <p>Type: INTEGER (boolean)
819         */
820        public static final String COLUMN_SEARCHABLE = "searchable";
821
822        /**
823         * The flag indicating whether this TV channel is locked or not.
824         *
825         * <p>This is primarily used for alternative parental control to prevent unauthorized users
826         * from watching the current channel regardless of the content rating. A value of 1
827         * indicates the channel is locked and the user is required to enter passcode to unlock it
828         * in order to watch the current program from the channel, a value of 0 indicates the
829         * channel is not locked thus the user is not prompted to enter passcode If not specified,
830         * this value is set to 0 (not locked) by default.
831         *
832         * <p>Type: INTEGER (boolean)
833         * @hide
834         */
835        @SystemApi
836        public static final String COLUMN_LOCKED = "locked";
837
838        /**
839         * The URI for the app badge icon of the app link template for this channel.
840         *
841         * <p>This small icon is overlaid at the bottom of the poster art specified by
842         * {@link #COLUMN_APP_LINK_POSTER_ART_URI}. The data in the column must be a URI in one of
843         * the following formats:
844         *
845         * <ul>
846         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
847         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
848         * </li>
849         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
850         * </ul>
851         *
852         * <p>The app-linking allows channel input sources to provide activity links from their live
853         * channel programming to another activity. This enables content providers to increase user
854         * engagement by offering the viewer other content or actions.
855         *
856         * <p>Type: TEXT
857         * @see #COLUMN_APP_LINK_COLOR
858         * @see #COLUMN_APP_LINK_INTENT_URI
859         * @see #COLUMN_APP_LINK_POSTER_ART_URI
860         * @see #COLUMN_APP_LINK_TEXT
861         */
862        public static final String COLUMN_APP_LINK_ICON_URI = "app_link_icon_uri";
863
864        /**
865         * The URI for the poster art used as the background of the app link template for this
866         * channel.
867         *
868         * <p>The data in the column must be a URL, or a URI in one of the following formats:
869         *
870         * <ul>
871         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
872         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
873         * </li>
874         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
875         * </ul>
876         *
877         * <p>The app-linking allows channel input sources to provide activity links from their live
878         * channel programming to another activity. This enables content providers to increase user
879         * engagement by offering the viewer other content or actions.
880         *
881         * <p>Type: TEXT
882         * @see #COLUMN_APP_LINK_COLOR
883         * @see #COLUMN_APP_LINK_ICON_URI
884         * @see #COLUMN_APP_LINK_INTENT_URI
885         * @see #COLUMN_APP_LINK_TEXT
886         */
887        public static final String COLUMN_APP_LINK_POSTER_ART_URI = "app_link_poster_art_uri";
888
889        /**
890         * The link text of the app link template for this channel.
891         *
892         * <p>This provides a short description of the action that happens when the corresponding
893         * app link is clicked.
894         *
895         * <p>The app-linking allows channel input sources to provide activity links from their live
896         * channel programming to another activity. This enables content providers to increase user
897         * engagement by offering the viewer other content or actions.
898         *
899         * <p>Type: TEXT
900         * @see #COLUMN_APP_LINK_COLOR
901         * @see #COLUMN_APP_LINK_ICON_URI
902         * @see #COLUMN_APP_LINK_INTENT_URI
903         * @see #COLUMN_APP_LINK_POSTER_ART_URI
904         */
905        public static final String COLUMN_APP_LINK_TEXT = "app_link_text";
906
907        /**
908         * The accent color of the app link template for this channel. This is primarily used for
909         * the background color of the text box in the template.
910         *
911         * <p>The app-linking allows channel input sources to provide activity links from their live
912         * channel programming to another activity. This enables content providers to increase user
913         * engagement by offering the viewer other content or actions.
914         *
915         * <p>Type: INTEGER (color value)
916         * @see #COLUMN_APP_LINK_ICON_URI
917         * @see #COLUMN_APP_LINK_INTENT_URI
918         * @see #COLUMN_APP_LINK_POSTER_ART_URI
919         * @see #COLUMN_APP_LINK_TEXT
920         */
921        public static final String COLUMN_APP_LINK_COLOR = "app_link_color";
922
923        /**
924         * The intent URI of the app link for this channel.
925         *
926         * <p>The URI is created using {@link Intent#toUri} with {@link Intent#URI_INTENT_SCHEME}
927         * and converted back to the original intent with {@link Intent#parseUri}. The intent is
928         * launched when the user clicks the corresponding app link for the current channel.
929         *
930         * <p>The app-linking allows channel input sources to provide activity links from their live
931         * channel programming to another activity. This enables content providers to increase user
932         * engagement by offering the viewer other content or actions.
933         *
934         * <p>Type: TEXT
935         * @see #COLUMN_APP_LINK_COLOR
936         * @see #COLUMN_APP_LINK_ICON_URI
937         * @see #COLUMN_APP_LINK_POSTER_ART_URI
938         * @see #COLUMN_APP_LINK_TEXT
939         */
940        public static final String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
941
942        /**
943         * Internal data used by individual TV input services.
944         *
945         * <p>This is internal to the provider that inserted it, and should not be decoded by other
946         * apps.
947         *
948         * <p>Type: BLOB
949         */
950        public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
951
952        /**
953         * Internal integer flag used by individual TV input services.
954         *
955         * <p>This is internal to the provider that inserted it, and should not be decoded by other
956         * apps.
957         *
958         * <p>Type: INTEGER
959         */
960        public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
961
962        /**
963         * Internal integer flag used by individual TV input services.
964         *
965         * <p>This is internal to the provider that inserted it, and should not be decoded by other
966         * apps.
967         *
968         * <p>Type: INTEGER
969         */
970        public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
971
972        /**
973         * Internal integer flag used by individual TV input services.
974         *
975         * <p>This is internal to the provider that inserted it, and should not be decoded by other
976         * apps.
977         *
978         * <p>Type: INTEGER
979         */
980        public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
981
982        /**
983         * Internal integer flag used by individual TV input services.
984         *
985         * <p>This is internal to the provider that inserted it, and should not be decoded by other
986         * apps.
987         *
988         * <p>Type: INTEGER
989         */
990        public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
991
992        /**
993         * The version number of this row entry used by TV input services.
994         *
995         * <p>This is best used by sync adapters to identify the rows to update. The number can be
996         * defined by individual TV input services. One may assign the same value as
997         * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are
998         * coming from a TV broadcast.
999         *
1000         * <p>Type: INTEGER
1001         */
1002        public static final String COLUMN_VERSION_NUMBER = "version_number";
1003
1004        private Channels() {}
1005
1006        /**
1007         * A sub-directory of a single TV channel that represents its primary logo.
1008         *
1009         * <p>To access this directory, append {@link Channels.Logo#CONTENT_DIRECTORY} to the raw
1010         * channel URI.  The resulting URI represents an image file, and should be interacted
1011         * using ContentResolver.openAssetFileDescriptor.
1012         *
1013         * <p>Note that this sub-directory also supports opening the logo as an asset file in write
1014         * mode.  Callers can create or replace the primary logo associated with this channel by
1015         * opening the asset file and writing the full-size photo contents into it. (Make sure there
1016         * is no padding around the logo image.) When the file is closed, the image will be parsed,
1017         * sized down if necessary, and stored.
1018         *
1019         * <p>Usage example:
1020         * <pre>
1021         * public void writeChannelLogo(long channelId, byte[] logo) {
1022         *     Uri channelLogoUri = TvContract.buildChannelLogoUri(channelId);
1023         *     try {
1024         *         AssetFileDescriptor fd =
1025         *             getContentResolver().openAssetFileDescriptor(channelLogoUri, "rw");
1026         *         OutputStream os = fd.createOutputStream();
1027         *         os.write(logo);
1028         *         os.close();
1029         *         fd.close();
1030         *     } catch (IOException e) {
1031         *         // Handle error cases.
1032         *     }
1033         * }
1034         * </pre>
1035         */
1036        public static final class Logo {
1037
1038            /**
1039             * The directory twig for this sub-table.
1040             */
1041            public static final String CONTENT_DIRECTORY = "logo";
1042
1043            private Logo() {}
1044        }
1045    }
1046
1047    /**
1048     * Column definitions for the TV programs table.
1049     *
1050     * <p>By default, the query results will be sorted by
1051     * {@link Programs#COLUMN_START_TIME_UTC_MILLIS} in ascending order.
1052     */
1053    public static final class Programs implements BaseTvColumns {
1054
1055        /** The content:// style URI for this table. */
1056        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
1057                + PATH_PROGRAM);
1058
1059        /** The MIME type of a directory of TV programs. */
1060        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/program";
1061
1062        /** The MIME type of a single TV program. */
1063        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
1064
1065        /**
1066         * The ID of the TV channel that provides this TV program.
1067         *
1068         * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
1069         *
1070         * <p>This is a required field.
1071         *
1072         * <p>Type: INTEGER (long)
1073         */
1074        public static final String COLUMN_CHANNEL_ID = "channel_id";
1075
1076        /**
1077         * The title of this TV program.
1078         *
1079         * <p>If this program is an episodic TV show, it is recommended that the title is the series
1080         * title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or
1081         * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_SEASON_DISPLAY_NUMBER},
1082         * {@link #COLUMN_EPISODE_DISPLAY_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
1083         *
1084         * <p>Type: TEXT
1085         */
1086        public static final String COLUMN_TITLE = "title";
1087
1088        /**
1089         * The season number of this TV program for episodic TV shows.
1090         *
1091         * <p>Can be empty.
1092         *
1093         * <p>Type: INTEGER
1094         *
1095         * @deprecated Use {@link #COLUMN_SEASON_DISPLAY_NUMBER} instead.
1096         */
1097        @Deprecated
1098        public static final String COLUMN_SEASON_NUMBER = "season_number";
1099
1100        /**
1101         * The season display number of this TV program for episodic TV shows.
1102         *
1103         * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value
1104         * does not necessarily be numeric. (e.g. 12B)
1105         *
1106         * <p>Can be empty.
1107         *
1108         * <p>Type: TEXT
1109         */
1110        public static final String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
1111
1112        /**
1113         * The title of the season for this TV program for episodic TV shows.
1114         *
1115         * <p>This is an optional field supplied only when the season has a special title
1116         * (e.g. The Final Season). If provided, the applications should display it instead of
1117         * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, and should display it without alterations.
1118         * (e.g. for "The Final Season", displayed string should be "The Final Season", not
1119         * "Season The Final Season"). When displaying multiple programs, the order should be based
1120         * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists.
1121         *
1122         * <p>Can be empty.
1123         *
1124         * <p>Type: TEXT
1125         */
1126        public static final String COLUMN_SEASON_TITLE = "season_title";
1127
1128        /**
1129         * The episode number of this TV program for episodic TV shows.
1130         *
1131         * <p>Can be empty.
1132         *
1133         * <p>Type: INTEGER
1134         *
1135         * @deprecated Use {@link #COLUMN_EPISODE_DISPLAY_NUMBER} instead.
1136         */
1137        @Deprecated
1138        public static final String COLUMN_EPISODE_NUMBER = "episode_number";
1139
1140        /**
1141         * The episode display number of this TV program for episodic TV shows.
1142         *
1143         * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value
1144         * does not necessarily be numeric. (e.g. 12B)
1145         *
1146         * <p>Can be empty.
1147         *
1148         * <p>Type: TEXT
1149         */
1150        public static final String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
1151
1152        /**
1153         * The episode title of this TV program for episodic TV shows.
1154         *
1155         * <p>Can be empty.
1156         *
1157         * <p>Type: TEXT
1158         */
1159        public static final String COLUMN_EPISODE_TITLE = "episode_title";
1160
1161        /**
1162         * The start time of this TV program, in milliseconds since the epoch.
1163         *
1164         * <p>The value should be equal to or larger than {@link #COLUMN_END_TIME_UTC_MILLIS} of the
1165         * previous program in the same channel. In practice, start time will usually be the end
1166         * time of the previous program.
1167         *
1168         * <p>Type: INTEGER (long)
1169         */
1170        public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
1171
1172        /**
1173         * The end time of this TV program, in milliseconds since the epoch.
1174         *
1175         * <p>The value should be equal to or less than {@link #COLUMN_START_TIME_UTC_MILLIS} of the
1176         * next program in the same channel. In practice, end time will usually be the start time of
1177         * the next program.
1178         *
1179         * <p>Type: INTEGER (long)
1180         */
1181        public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
1182
1183        /**
1184         * The comma-separated genre string of this TV program.
1185         *
1186         * <p>Use the same language appeared in the underlying broadcast standard, if applicable.
1187         * (For example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
1188         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty. Use
1189         * {@link Genres#encode} to create a text that can be stored in this column. Use
1190         * {@link Genres#decode} to get the broadcast genre strings from the text stored in the
1191         * column.
1192         *
1193         * <p>Type: TEXT
1194         * @see Genres#encode
1195         * @see Genres#decode
1196         */
1197        public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";
1198
1199        /**
1200         * The comma-separated canonical genre string of this TV program.
1201         *
1202         * <p>Canonical genres are defined in {@link Genres}. Use {@link Genres#encode} to create a
1203         * text that can be stored in this column. Use {@link Genres#decode} to get the canonical
1204         * genre strings from the text stored in the column.
1205         *
1206         * <p>Type: TEXT
1207         * @see Genres
1208         * @see Genres#encode
1209         * @see Genres#decode
1210         */
1211        public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";
1212
1213        /**
1214         * The short description of this TV program that is displayed to the user by default.
1215         *
1216         * <p>It is recommended to limit the length of the descriptions to 256 characters.
1217         *
1218         * <p>Type: TEXT
1219         */
1220        public static final String COLUMN_SHORT_DESCRIPTION = "short_description";
1221
1222        /**
1223         * The detailed, lengthy description of this TV program that is displayed only when the user
1224         * wants to see more information.
1225         *
1226         * <p>TV input services should leave this field empty if they have no additional details
1227         * beyond {@link #COLUMN_SHORT_DESCRIPTION}.
1228         *
1229         * <p>Type: TEXT
1230         */
1231        public static final String COLUMN_LONG_DESCRIPTION = "long_description";
1232
1233        /**
1234         * The width of the video for this TV program, in the unit of pixels.
1235         *
1236         * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video
1237         * resolution of the current TV program. Can be empty if it is not known initially or the
1238         * program does not convey any video such as the programs from type
1239         * {@link Channels#SERVICE_TYPE_AUDIO} channels.
1240         *
1241         * <p>Type: INTEGER
1242         */
1243        public static final String COLUMN_VIDEO_WIDTH = "video_width";
1244
1245        /**
1246         * The height of the video for this TV program, in the unit of pixels.
1247         *
1248         * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video
1249         * resolution of the current TV program. Can be empty if it is not known initially or the
1250         * program does not convey any video such as the programs from type
1251         * {@link Channels#SERVICE_TYPE_AUDIO} channels.
1252         *
1253         * <p>Type: INTEGER
1254         */
1255        public static final String COLUMN_VIDEO_HEIGHT = "video_height";
1256
1257        /**
1258         * The comma-separated audio languages of this TV program.
1259         *
1260         * <p>This is used to describe available audio languages included in the program. Use either
1261         * ISO 639-1 or 639-2/T codes.
1262         *
1263         * <p>Type: TEXT
1264         */
1265        public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
1266
1267        /**
1268         * The comma-separated content ratings of this TV program.
1269         *
1270         * <p>This is used to describe the content rating(s) of this program. Each comma-separated
1271         * content rating sub-string should be generated by calling
1272         * {@link TvContentRating#flattenToString}. Note that in most cases the program content is
1273         * rated by a single rating system, thus resulting in a corresponding single sub-string that
1274         * does not require comma separation and multiple sub-strings appear only when the program
1275         * content is rated by two or more content rating systems. If any of those ratings is
1276         * specified as "blocked rating" in the user's parental control settings, the TV input
1277         * service should block the current content and wait for the signal that it is okay to
1278         * unblock.
1279         *
1280         * <p>Type: TEXT
1281         */
1282        public static final String COLUMN_CONTENT_RATING = "content_rating";
1283
1284        /**
1285         * The URI for the poster art of this TV program.
1286         *
1287         * <p>The data in the column must be a URL, or a URI in one of the following formats:
1288         *
1289         * <ul>
1290         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
1291         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
1292         * </li>
1293         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
1294         * </ul>
1295         *
1296         * <p>Can be empty.
1297         *
1298         * <p>Type: TEXT
1299         */
1300        public static final String COLUMN_POSTER_ART_URI = "poster_art_uri";
1301
1302        /**
1303         * The URI for the thumbnail of this TV program.
1304         *
1305         * <p>The system can generate a thumbnail from the poster art if this column is not
1306         * specified. Thus it is not necessary for TV input services to include a thumbnail if it is
1307         * just a scaled image of the poster art.
1308         *
1309         * <p>The data in the column must be a URL, or a URI in one of the following formats:
1310         *
1311         * <ul>
1312         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
1313         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
1314         * </li>
1315         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
1316         * </ul>
1317         *
1318         * <p>Can be empty.
1319         *
1320         * <p>Type: TEXT
1321         */
1322        public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
1323
1324        /**
1325         * The flag indicating whether this TV program is searchable or not.
1326         *
1327         * <p>The columns of searchable programs can be read by other applications that have proper
1328         * permission. Care must be taken not to open sensitive data.
1329         *
1330         * <p>A value of 1 indicates that the program is searchable and its columns can be read by
1331         * other applications, a value of 0 indicates that the program is hidden and its columns can
1332         * be read only by the package that owns the program and the system. If not specified, this
1333         * value is set to 1 (searchable) by default.
1334         *
1335         * <p>Type: INTEGER (boolean)
1336         */
1337        public static final String COLUMN_SEARCHABLE = "searchable";
1338
1339        /**
1340         * The flag indicating whether recording of this program is prohibited.
1341         *
1342         * <p>A value of 1 indicates that recording of this program is prohibited and application
1343         * will not schedule any recording for this program. A value of 0 indicates that the
1344         * recording is not prohibited. If not specified, this value is set to 0 (not prohibited) by
1345         * default.
1346         *
1347         * <p>Type: INTEGER (boolean)
1348         */
1349        public static final String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
1350
1351        /**
1352         * Internal data used by individual TV input services.
1353         *
1354         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1355         * apps.
1356         *
1357         * <p>Type: BLOB
1358         */
1359        public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
1360
1361        /**
1362         * Internal integer flag used by individual TV input services.
1363         *
1364         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1365         * apps.
1366         *
1367         * <p>Type: INTEGER
1368         */
1369        public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
1370
1371        /**
1372         * Internal integer flag used by individual TV input services.
1373         *
1374         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1375         * apps.
1376         *
1377         * <p>Type: INTEGER
1378         */
1379        public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
1380
1381        /**
1382         * Internal integer flag used by individual TV input services.
1383         *
1384         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1385         * apps.
1386         *
1387         * <p>Type: INTEGER
1388         */
1389        public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
1390
1391        /**
1392         * Internal integer flag used by individual TV input services.
1393         *
1394         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1395         * apps.
1396         *
1397         * <p>Type: INTEGER
1398         */
1399        public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
1400
1401        /**
1402         * The version number of this row entry used by TV input services.
1403         *
1404         * <p>This is best used by sync adapters to identify the rows to update. The number can be
1405         * defined by individual TV input services. One may assign the same value as
1406         * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
1407         * broadcast.
1408         *
1409         * <p>Type: INTEGER
1410         */
1411        public static final String COLUMN_VERSION_NUMBER = "version_number";
1412
1413        private Programs() {}
1414
1415        /** Canonical genres for TV programs. */
1416        public static final class Genres {
1417            /** The genre for Family/Kids. */
1418            public static final String FAMILY_KIDS = "FAMILY_KIDS";
1419
1420            /** The genre for Sports. */
1421            public static final String SPORTS = "SPORTS";
1422
1423            /** The genre for Shopping. */
1424            public static final String SHOPPING = "SHOPPING";
1425
1426            /** The genre for Movies. */
1427            public static final String MOVIES = "MOVIES";
1428
1429            /** The genre for Comedy. */
1430            public static final String COMEDY = "COMEDY";
1431
1432            /** The genre for Travel. */
1433            public static final String TRAVEL = "TRAVEL";
1434
1435            /** The genre for Drama. */
1436            public static final String DRAMA = "DRAMA";
1437
1438            /** The genre for Education. */
1439            public static final String EDUCATION = "EDUCATION";
1440
1441            /** The genre for Animal/Wildlife. */
1442            public static final String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE";
1443
1444            /** The genre for News. */
1445            public static final String NEWS = "NEWS";
1446
1447            /** The genre for Gaming. */
1448            public static final String GAMING = "GAMING";
1449
1450            /** The genre for Arts. */
1451            public static final String ARTS = "ARTS";
1452
1453            /** The genre for Entertainment. */
1454            public static final String ENTERTAINMENT = "ENTERTAINMENT";
1455
1456            /** The genre for Life Style. */
1457            public static final String LIFE_STYLE = "LIFE_STYLE";
1458
1459            /** The genre for Music. */
1460            public static final String MUSIC = "MUSIC";
1461
1462            /** The genre for Premier. */
1463            public static final String PREMIER = "PREMIER";
1464
1465            /** The genre for Tech/Science. */
1466            public static final String TECH_SCIENCE = "TECH_SCIENCE";
1467
1468            private static final ArraySet<String> CANONICAL_GENRES = new ArraySet<>();
1469            static {
1470                CANONICAL_GENRES.add(FAMILY_KIDS);
1471                CANONICAL_GENRES.add(SPORTS);
1472                CANONICAL_GENRES.add(SHOPPING);
1473                CANONICAL_GENRES.add(MOVIES);
1474                CANONICAL_GENRES.add(COMEDY);
1475                CANONICAL_GENRES.add(TRAVEL);
1476                CANONICAL_GENRES.add(DRAMA);
1477                CANONICAL_GENRES.add(EDUCATION);
1478                CANONICAL_GENRES.add(ANIMAL_WILDLIFE);
1479                CANONICAL_GENRES.add(NEWS);
1480                CANONICAL_GENRES.add(GAMING);
1481                CANONICAL_GENRES.add(ARTS);
1482                CANONICAL_GENRES.add(ENTERTAINMENT);
1483                CANONICAL_GENRES.add(LIFE_STYLE);
1484                CANONICAL_GENRES.add(MUSIC);
1485                CANONICAL_GENRES.add(PREMIER);
1486                CANONICAL_GENRES.add(TECH_SCIENCE);
1487            }
1488
1489            private static final char DOUBLE_QUOTE = '"';
1490            private static final char COMMA = ',';
1491            private static final String DELIMITER = ",";
1492
1493            private static final String[] EMPTY_STRING_ARRAY = new String[0];
1494
1495            private Genres() {}
1496
1497            /**
1498             * Encodes genre strings to a text that can be put into the database.
1499             *
1500             * @param genres Genre strings.
1501             * @return an encoded genre string that can be inserted into the
1502             *         {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
1503             */
1504            public static String encode(@NonNull String... genres) {
1505                if (genres == null) {
1506                    // MNC and before will throw a NPE.
1507                    return null;
1508                }
1509                StringBuilder sb = new StringBuilder();
1510                String separator = "";
1511                for (String genre : genres) {
1512                    sb.append(separator).append(encodeToCsv(genre));
1513                    separator = DELIMITER;
1514                }
1515                return sb.toString();
1516            }
1517
1518            private static String encodeToCsv(String genre) {
1519                StringBuilder sb = new StringBuilder();
1520                int length = genre.length();
1521                for (int i = 0; i < length; ++i) {
1522                    char c = genre.charAt(i);
1523                    switch (c) {
1524                        case DOUBLE_QUOTE:
1525                            sb.append(DOUBLE_QUOTE);
1526                            break;
1527                        case COMMA:
1528                            sb.append(DOUBLE_QUOTE);
1529                            break;
1530                    }
1531                    sb.append(c);
1532                }
1533                return sb.toString();
1534            }
1535
1536            /**
1537             * Decodes the genre strings from the text stored in the database.
1538             *
1539             * @param genres The encoded genre string retrieved from the
1540             *            {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
1541             * @return genre strings.
1542             */
1543            public static String[] decode(@NonNull String genres) {
1544                if (TextUtils.isEmpty(genres)) {
1545                    // MNC and before will throw a NPE for {@code null} genres.
1546                    return EMPTY_STRING_ARRAY;
1547                }
1548                if (genres.indexOf(COMMA) == -1 && genres.indexOf(DOUBLE_QUOTE) == -1) {
1549                    return new String[] {genres.trim()};
1550                }
1551                StringBuilder sb = new StringBuilder();
1552                List<String> results = new ArrayList<>();
1553                int length = genres.length();
1554                boolean escape = false;
1555                for (int i = 0; i < length; ++i) {
1556                    char c = genres.charAt(i);
1557                    switch (c) {
1558                        case DOUBLE_QUOTE:
1559                            if (!escape) {
1560                                escape = true;
1561                                continue;
1562                            }
1563                            break;
1564                        case COMMA:
1565                            if (!escape) {
1566                                String string = sb.toString().trim();
1567                                if (string.length() > 0) {
1568                                    results.add(string);
1569                                }
1570                                sb = new StringBuilder();
1571                                continue;
1572                            }
1573                            break;
1574                    }
1575                    sb.append(c);
1576                    escape = false;
1577                }
1578                String string = sb.toString().trim();
1579                if (string.length() > 0) {
1580                    results.add(string);
1581                }
1582                return results.toArray(new String[results.size()]);
1583            }
1584
1585            /**
1586             * Returns whether a given text is a canonical genre defined in {@link Genres}.
1587             *
1588             * @param genre The name of genre to be checked.
1589             * @return {@code true} if the genre is canonical, otherwise {@code false}.
1590             */
1591            public static boolean isCanonical(String genre) {
1592                return CANONICAL_GENRES.contains(genre);
1593            }
1594        }
1595    }
1596
1597    /**
1598     * Column definitions for the recorded TV programs table.
1599     *
1600     * <p>By default, the query results will be sorted by {@link #COLUMN_START_TIME_UTC_MILLIS} in
1601     * ascending order.
1602     */
1603    public static final class RecordedPrograms implements BaseTvColumns {
1604
1605        /** The content:// style URI for this table. */
1606        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
1607                + PATH_RECORDED_PROGRAM);
1608
1609        /** The MIME type of a directory of recorded TV programs. */
1610        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
1611
1612        /** The MIME type of a single recorded TV program. */
1613        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
1614
1615        /**
1616         * The ID of the TV input service that is associated with this recorded program.
1617         *
1618         * <p>Use {@link #buildInputId} to build the ID.
1619         *
1620         * <p>This is a required field.
1621         *
1622         * <p>Type: TEXT
1623         */
1624        public static final String COLUMN_INPUT_ID = "input_id";
1625
1626        /**
1627         * The ID of the TV channel that provided this recorded TV program.
1628         *
1629         * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
1630         *
1631         * <p>This is a required field.
1632         *
1633         * <p>Type: INTEGER (long)
1634         * @see Programs#COLUMN_CHANNEL_ID
1635         */
1636        public static final String COLUMN_CHANNEL_ID = Programs.COLUMN_CHANNEL_ID;
1637
1638        /**
1639         * The title of this recorded TV program.
1640         *
1641         * <p>If this recorded program is an episodic TV show, it is recommended that the title is
1642         * the series title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or
1643         * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_EPISODE_DISPLAY_NUMBER},
1644         * and {@link #COLUMN_EPISODE_TITLE}) are filled in.
1645         *
1646         * <p>Type: TEXT
1647         * @see Programs#COLUMN_TITLE
1648         */
1649        public static final String COLUMN_TITLE = Programs.COLUMN_TITLE;
1650
1651        /**
1652         * The season display number of this recorded TV program for episodic TV shows.
1653         *
1654         * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value
1655         * does not necessarily be numeric. (e.g. 12B)
1656         *
1657         * <p>Can be empty.
1658         *
1659         * <p>Type: TEXT
1660         */
1661        public static final String COLUMN_SEASON_DISPLAY_NUMBER =
1662                Programs.COLUMN_SEASON_DISPLAY_NUMBER;
1663
1664        /**
1665         * The title of the season for this recorded TV program for episodic TV shows.
1666         *
1667         * <p>This is an optional field supplied only when the season has a special title
1668         * (e.g. The Final Season). If provided, the applications should display it instead of
1669         * {@link #COLUMN_SEASON_DISPLAY_NUMBER} without alterations.
1670         * (e.g. for "The Final Season", displayed string should be "The Final Season", not
1671         * "Season The Final Season"). When displaying multiple programs, the order should be based
1672         * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists.
1673         *
1674         * <p>Can be empty.
1675         *
1676         * <p>Type: TEXT
1677         */
1678        public static final String COLUMN_SEASON_TITLE = Programs.COLUMN_SEASON_TITLE;
1679
1680        /**
1681         * The episode display number of this recorded TV program for episodic TV shows.
1682         *
1683         * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value
1684         * does not necessarily be numeric. (e.g. 12B)
1685         *
1686         * <p>Can be empty.
1687         *
1688         * <p>Type: TEXT
1689         */
1690        public static final String COLUMN_EPISODE_DISPLAY_NUMBER =
1691                Programs.COLUMN_EPISODE_DISPLAY_NUMBER;
1692
1693        /**
1694         * The episode title of this recorded TV program for episodic TV shows.
1695         *
1696         * <p>Can be empty.
1697         *
1698         * <p>Type: TEXT
1699         * @see Programs#COLUMN_EPISODE_TITLE
1700         */
1701        public static final String COLUMN_EPISODE_TITLE = Programs.COLUMN_EPISODE_TITLE;
1702
1703        /**
1704         * The start time of the original TV program, in milliseconds since the epoch.
1705         *
1706         * <p>Type: INTEGER (long)
1707         * @see Programs#COLUMN_START_TIME_UTC_MILLIS
1708         */
1709        public static final String COLUMN_START_TIME_UTC_MILLIS =
1710                Programs.COLUMN_START_TIME_UTC_MILLIS;
1711
1712        /**
1713         * The end time of the original TV program, in milliseconds since the epoch.
1714         *
1715         * <p>Type: INTEGER (long)
1716         * @see Programs#COLUMN_END_TIME_UTC_MILLIS
1717         */
1718        public static final String COLUMN_END_TIME_UTC_MILLIS = Programs.COLUMN_END_TIME_UTC_MILLIS;
1719
1720        /**
1721         * The comma-separated genre string of this recorded TV program.
1722         *
1723         * <p>Use the same language appeared in the underlying broadcast standard, if applicable.
1724         * (For example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
1725         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty. Use
1726         * {@link Genres#encode Genres.encode()} to create a text that can be stored in this column.
1727         * Use {@link Genres#decode Genres.decode()} to get the broadcast genre strings from the
1728         * text stored in the column.
1729         *
1730         * <p>Type: TEXT
1731         * @see Programs#COLUMN_BROADCAST_GENRE
1732         */
1733        public static final String COLUMN_BROADCAST_GENRE = Programs.COLUMN_BROADCAST_GENRE;
1734
1735        /**
1736         * The comma-separated canonical genre string of this recorded TV program.
1737         *
1738         * <p>Canonical genres are defined in {@link Programs.Genres}. Use
1739         * {@link Programs.Genres#encode Genres.encode()} to create a text that can be stored in
1740         * this column. Use {@link Programs.Genres#decode Genres.decode()} to get the canonical
1741         * genre strings from the text stored in the column.
1742         *
1743         * <p>Type: TEXT
1744         * @see Programs#COLUMN_CANONICAL_GENRE
1745         * @see Programs.Genres
1746         */
1747        public static final String COLUMN_CANONICAL_GENRE = Programs.COLUMN_CANONICAL_GENRE;
1748
1749        /**
1750         * The short description of this recorded TV program that is displayed to the user by
1751         * default.
1752         *
1753         * <p>It is recommended to limit the length of the descriptions to 256 characters.
1754         *
1755         * <p>Type: TEXT
1756         * @see Programs#COLUMN_SHORT_DESCRIPTION
1757         */
1758        public static final String COLUMN_SHORT_DESCRIPTION = Programs.COLUMN_SHORT_DESCRIPTION;
1759
1760        /**
1761         * The detailed, lengthy description of this recorded TV program that is displayed only when
1762         * the user wants to see more information.
1763         *
1764         * <p>TV input services should leave this field empty if they have no additional details
1765         * beyond {@link #COLUMN_SHORT_DESCRIPTION}.
1766         *
1767         * <p>Type: TEXT
1768         * @see Programs#COLUMN_LONG_DESCRIPTION
1769         */
1770        public static final String COLUMN_LONG_DESCRIPTION = Programs.COLUMN_LONG_DESCRIPTION;
1771
1772        /**
1773         * The width of the video for this recorded TV program, in the unit of pixels.
1774         *
1775         * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video
1776         * resolution of the current recorded TV program. Can be empty if it is not known or the
1777         * recorded program does not convey any video.
1778         *
1779         * <p>Type: INTEGER
1780         * @see Programs#COLUMN_VIDEO_WIDTH
1781         */
1782        public static final String COLUMN_VIDEO_WIDTH = Programs.COLUMN_VIDEO_WIDTH;
1783
1784        /**
1785         * The height of the video for this recorded TV program, in the unit of pixels.
1786         *
1787         * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video
1788         * resolution of the current recorded TV program. Can be empty if it is not known or the
1789         * recorded program does not convey any video.
1790         *
1791         * <p>Type: INTEGER
1792         * @see Programs#COLUMN_VIDEO_HEIGHT
1793         */
1794        public static final String COLUMN_VIDEO_HEIGHT = Programs.COLUMN_VIDEO_HEIGHT;
1795
1796        /**
1797         * The comma-separated audio languages of this recorded TV program.
1798         *
1799         * <p>This is used to describe available audio languages included in the recorded program.
1800         * Use either ISO 639-1 or 639-2/T codes.
1801         *
1802         * <p>Type: TEXT
1803         * @see Programs#COLUMN_AUDIO_LANGUAGE
1804         */
1805        public static final String COLUMN_AUDIO_LANGUAGE = Programs.COLUMN_AUDIO_LANGUAGE;
1806
1807        /**
1808         * The comma-separated content ratings of this recorded TV program.
1809         *
1810         * <p>This is used to describe the content rating(s) of this recorded program. Each
1811         * comma-separated content rating sub-string should be generated by calling
1812         * {@link TvContentRating#flattenToString}. Note that in most cases the recorded program
1813         * content is rated by a single rating system, thus resulting in a corresponding single
1814         * sub-string that does not require comma separation and multiple sub-strings appear only
1815         * when the recorded program content is rated by two or more content rating systems. If any
1816         * of those ratings is specified as "blocked rating" in the user's parental control
1817         * settings, the TV input service should block the current content and wait for the signal
1818         * that it is okay to unblock.
1819         *
1820         * <p>Type: TEXT
1821         * @see Programs#COLUMN_CONTENT_RATING
1822         */
1823        public static final String COLUMN_CONTENT_RATING = Programs.COLUMN_CONTENT_RATING;
1824
1825        /**
1826         * The URI for the poster art of this recorded TV program.
1827         *
1828         * <p>The data in the column must be a URL, or a URI in one of the following formats:
1829         *
1830         * <ul>
1831         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
1832         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
1833         * </li>
1834         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
1835         * </ul>
1836         *
1837         * <p>Can be empty.
1838         *
1839         * <p>Type: TEXT
1840         * @see Programs#COLUMN_POSTER_ART_URI
1841         */
1842        public static final String COLUMN_POSTER_ART_URI = Programs.COLUMN_POSTER_ART_URI;
1843
1844        /**
1845         * The URI for the thumbnail of this recorded TV program.
1846         *
1847         * <p>The system can generate a thumbnail from the poster art if this column is not
1848         * specified. Thus it is not necessary for TV input services to include a thumbnail if it is
1849         * just a scaled image of the poster art.
1850         *
1851         * <p>The data in the column must be a URL, or a URI in one of the following formats:
1852         *
1853         * <ul>
1854         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
1855         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
1856         * </li>
1857         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
1858         * </ul>
1859         *
1860         * <p>Can be empty.
1861         *
1862         * <p>Type: TEXT
1863         * @see Programs#COLUMN_THUMBNAIL_URI
1864         */
1865        public static final String COLUMN_THUMBNAIL_URI = Programs.COLUMN_THUMBNAIL_URI;
1866
1867        /**
1868         * The flag indicating whether this recorded TV program is searchable or not.
1869         *
1870         * <p>The columns of searchable recorded programs can be read by other applications that
1871         * have proper permission. Care must be taken not to open sensitive data.
1872         *
1873         * <p>A value of 1 indicates that the recorded program is searchable and its columns can be
1874         * read by other applications, a value of 0 indicates that the recorded program is hidden
1875         * and its columns can be read only by the package that owns the recorded program and the
1876         * system. If not specified, this value is set to 1 (searchable) by default.
1877         *
1878         * <p>Type: INTEGER (boolean)
1879         * @see Programs#COLUMN_SEARCHABLE
1880         */
1881        public static final String COLUMN_SEARCHABLE = Programs.COLUMN_SEARCHABLE;
1882
1883        /**
1884         * The URI of the recording data for this recorded program.
1885         *
1886         * <p>Together with {@link #COLUMN_RECORDING_DATA_BYTES}, applications can use this
1887         * information to manage recording storage. The URI should indicate a file or directory with
1888         * the scheme {@link android.content.ContentResolver#SCHEME_FILE}.
1889         *
1890         * <p>Type: TEXT
1891         * @see #COLUMN_RECORDING_DATA_BYTES
1892         */
1893        public static final String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
1894
1895        /**
1896         * The data size (in bytes) for this recorded program.
1897         *
1898         * <p>Together with {@link #COLUMN_RECORDING_DATA_URI}, applications can use this
1899         * information to manage recording storage.
1900         *
1901         * <p>Type: INTEGER (long)
1902         * @see #COLUMN_RECORDING_DATA_URI
1903         */
1904        public static final String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
1905
1906        /**
1907         * The duration (in milliseconds) of this recorded program.
1908         *
1909         * <p>The actual duration of the recorded program can differ from the one calculated by
1910         * {@link #COLUMN_END_TIME_UTC_MILLIS} - {@link #COLUMN_START_TIME_UTC_MILLIS} as program
1911         * recording can be interrupted in the middle for some reason, resulting in a partially
1912         * recorded program, which is still playable.
1913         *
1914         * <p>Type: INTEGER
1915         */
1916        public static final String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
1917
1918        /**
1919         * The expiration time for this recorded program, in milliseconds since the epoch.
1920         *
1921         * <p>Recorded TV programs do not expire by default unless explicitly requested by the user
1922         * or the user allows applications to delete them in order to free up disk space for future
1923         * recording. However, some TV content can have expiration date set by the content provider
1924         * when recorded. This field is used to indicate such a restriction.
1925         *
1926         * <p>Can be empty.
1927         *
1928         * <p>Type: INTEGER (long)
1929         */
1930        public static final String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS =
1931                "recording_expire_time_utc_millis";
1932
1933
1934        /**
1935         * Internal data used by individual TV input services.
1936         *
1937         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1938         * apps.
1939         *
1940         * <p>Type: BLOB
1941         * @see Programs#COLUMN_INTERNAL_PROVIDER_DATA
1942         */
1943        public static final String COLUMN_INTERNAL_PROVIDER_DATA =
1944                Programs.COLUMN_INTERNAL_PROVIDER_DATA;
1945
1946        /**
1947         * Internal integer flag used by individual TV input services.
1948         *
1949         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1950         * apps.
1951         *
1952         * <p>Type: INTEGER
1953         * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG1
1954         */
1955        public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 =
1956                Programs.COLUMN_INTERNAL_PROVIDER_FLAG1;
1957
1958        /**
1959         * Internal integer flag used by individual TV input services.
1960         *
1961         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1962         * apps.
1963         *
1964         * <p>Type: INTEGER
1965         * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG2
1966         */
1967        public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 =
1968                Programs.COLUMN_INTERNAL_PROVIDER_FLAG2;
1969
1970        /**
1971         * Internal integer flag used by individual TV input services.
1972         *
1973         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1974         * apps.
1975         *
1976         * <p>Type: INTEGER
1977         * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG3
1978         */
1979        public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 =
1980                Programs.COLUMN_INTERNAL_PROVIDER_FLAG3;
1981
1982        /**
1983         * Internal integer flag used by individual TV input services.
1984         *
1985         * <p>This is internal to the provider that inserted it, and should not be decoded by other
1986         * apps.
1987         *
1988         * <p>Type: INTEGER
1989         * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG4
1990         */
1991        public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 =
1992                Programs.COLUMN_INTERNAL_PROVIDER_FLAG4;
1993
1994        /**
1995         * The version number of this row entry used by TV input services.
1996         *
1997         * <p>This is best used by sync adapters to identify the rows to update. The number can be
1998         * defined by individual TV input services. One may assign the same value as
1999         * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
2000         * broadcast.
2001         *
2002         * <p>Type: INTEGER
2003         * @see Programs#COLUMN_VERSION_NUMBER
2004         */
2005        public static final String COLUMN_VERSION_NUMBER = Programs.COLUMN_VERSION_NUMBER;
2006
2007        private RecordedPrograms() {}
2008    }
2009
2010    /**
2011     * Column definitions for the TV programs that the user watched. Applications do not have access
2012     * to this table.
2013     *
2014     * <p>By default, the query results will be sorted by
2015     * {@link WatchedPrograms#COLUMN_WATCH_START_TIME_UTC_MILLIS} in descending order.
2016     * @hide
2017     */
2018    @SystemApi
2019    public static final class WatchedPrograms implements BaseTvColumns {
2020
2021        /** The content:// style URI for this table. */
2022        public static final Uri CONTENT_URI =
2023                Uri.parse("content://" + AUTHORITY + "/watched_program");
2024
2025        /** The MIME type of a directory of watched programs. */
2026        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watched_program";
2027
2028        /** The MIME type of a single item in this table. */
2029        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watched_program";
2030
2031        /**
2032         * The UTC time that the user started watching this TV program, in milliseconds since the
2033         * epoch.
2034         *
2035         * <p>Type: INTEGER (long)
2036         */
2037        public static final String COLUMN_WATCH_START_TIME_UTC_MILLIS =
2038                "watch_start_time_utc_millis";
2039
2040        /**
2041         * The UTC time that the user stopped watching this TV program, in milliseconds since the
2042         * epoch.
2043         *
2044         * <p>Type: INTEGER (long)
2045         */
2046        public static final String COLUMN_WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis";
2047
2048        /**
2049         * The ID of the TV channel that provides this TV program.
2050         *
2051         * <p>This is a required field.
2052         *
2053         * <p>Type: INTEGER (long)
2054         */
2055        public static final String COLUMN_CHANNEL_ID = "channel_id";
2056
2057        /**
2058         * The title of this TV program.
2059         *
2060         * <p>Type: TEXT
2061         */
2062        public static final String COLUMN_TITLE = "title";
2063
2064        /**
2065         * The start time of this TV program, in milliseconds since the epoch.
2066         *
2067         * <p>Type: INTEGER (long)
2068         */
2069        public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
2070
2071        /**
2072         * The end time of this TV program, in milliseconds since the epoch.
2073         *
2074         * <p>Type: INTEGER (long)
2075         */
2076        public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
2077
2078        /**
2079         * The description of this TV program.
2080         *
2081         * <p>Type: TEXT
2082         */
2083        public static final String COLUMN_DESCRIPTION = "description";
2084
2085        /**
2086         * Extra parameters given to {@link TvInputService.Session#tune(Uri, android.os.Bundle)
2087         * TvInputService.Session.tune(Uri, android.os.Bundle)} when tuning to the channel that
2088         * provides this TV program. (Used internally.)
2089         *
2090         * <p>This column contains an encoded string that represents comma-separated key-value pairs of
2091         * the tune parameters. (Ex. "[key1]=[value1], [key2]=[value2]"). '%' is used as an escape
2092         * character for '%', '=', and ','.
2093         *
2094         * <p>Type: TEXT
2095         */
2096        public static final String COLUMN_INTERNAL_TUNE_PARAMS = "tune_params";
2097
2098        /**
2099         * The session token of this TV program. (Used internally.)
2100         *
2101         * <p>This contains a String representation of {@link IBinder} for
2102         * {@link TvInputService.Session} that provides the current TV program. It is used
2103         * internally to distinguish watched programs entries from different TV input sessions.
2104         *
2105         * <p>Type: TEXT
2106         */
2107        public static final String COLUMN_INTERNAL_SESSION_TOKEN = "session_token";
2108
2109        private WatchedPrograms() {}
2110    }
2111}
2112