• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.media.tv;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.content.ComponentName;
23 import android.content.ContentResolver;
24 import android.content.ContentUris;
25 import android.content.Intent;
26 import android.net.Uri;
27 import android.os.IBinder;
28 import android.provider.BaseColumns;
29 import android.text.TextUtils;
30 import android.util.ArraySet;
31 
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.List;
35 import 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  */
54 public 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      */
buildInputId(ComponentName name)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      */
buildChannelUri(long channelId)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      */
buildChannelUriForPassthroughInput(String inputId)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      */
buildChannelLogoUri(long channelId)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      */
buildChannelLogoUri(Uri channelUri)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      */
buildChannelsUriForInput(@ullable String inputId)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
buildChannelsUriForInput(@ullable String inputId, boolean browsableOnly)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
buildChannelsUriForInput(@ullable String inputId, @Nullable String genre, boolean browsableOnly)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      */
buildProgramUri(long programId)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      */
buildProgramsUriForChannel(long channelId)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      */
buildProgramsUriForChannel(Uri channelUri)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      */
buildProgramsUriForChannel(long channelId, long startTime, long endTime)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      */
buildProgramsUriForChannel(Uri channelUri, long startTime, long endTime)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      */
buildRecordedProgramUri(long recordedProgramId)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      */
buildWatchedProgramUri(long watchedProgramId)301     public static final Uri buildWatchedProgramUri(long watchedProgramId) {
302         return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId);
303     }
304 
isTvUri(Uri uri)305     private static boolean isTvUri(Uri uri) {
306         return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())
307                 && AUTHORITY.equals(uri.getAuthority());
308     }
309 
isTwoSegmentUriStartingWith(Uri uri, String pathSegment)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      */
isChannelUri(Uri uri)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      */
isChannelUriForTunerInput(Uri uri)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      */
isChannelUriForPassthroughInput(Uri uri)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      */
isProgramUri(Uri uri)339     public static final boolean isProgramUri(Uri uri) {
340         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM);
341     }
342 
343 
TvContract()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 {
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480I, VIDEO_RESOLUTION_SD)606             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480I, VIDEO_RESOLUTION_SD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480P, VIDEO_RESOLUTION_ED)607             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480P, VIDEO_RESOLUTION_ED);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576I, VIDEO_RESOLUTION_SD)608             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576I, VIDEO_RESOLUTION_SD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576P, VIDEO_RESOLUTION_ED)609             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576P, VIDEO_RESOLUTION_ED);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_720P, VIDEO_RESOLUTION_HD)610             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_720P, VIDEO_RESOLUTION_HD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080I, VIDEO_RESOLUTION_HD)611             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080I, VIDEO_RESOLUTION_HD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080P, VIDEO_RESOLUTION_FHD)612             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080P, VIDEO_RESOLUTION_FHD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_2160P, VIDEO_RESOLUTION_UHD)613             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_2160P, VIDEO_RESOLUTION_UHD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_4320P, 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
getVideoResolution(String videoFormat)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 
Channels()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 
Logo()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 
Programs()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 
Genres()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              */
encode(@onNull String... genres)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 
encodeToCsv(String genre)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              */
decode(@onNull String genres)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              */
isCanonical(String genre)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 
RecordedPrograms()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 
WatchedPrograms()2109         private WatchedPrograms() {}
2110     }
2111 }
2112