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.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SdkConstant;
23 import android.annotation.SdkConstant.SdkConstantType;
24 import android.annotation.StringDef;
25 import android.annotation.SystemApi;
26 import android.app.Activity;
27 import android.content.ComponentName;
28 import android.content.ContentResolver;
29 import android.content.ContentUris;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.net.Uri;
33 import android.os.Bundle;
34 import android.os.IBinder;
35 import android.provider.BaseColumns;
36 import android.text.TextUtils;
37 import android.util.ArraySet;
38 
39 import java.lang.annotation.Retention;
40 import java.lang.annotation.RetentionPolicy;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45 
46 /**
47  * The contract between the TV provider and applications. Contains definitions for the supported
48  * URIs and columns.
49  * <h3>Overview</h3>
50  *
51  * <p>TvContract defines a basic database of TV content metadata such as channel and program
52  * information. The information is stored in {@link Channels} and {@link Programs} tables.
53  *
54  * <ul>
55  *     <li>A row in the {@link Channels} table represents information about a TV channel. The data
56  *         format can vary greatly from standard to standard or according to service provider, thus
57  *         the columns here are mostly comprised of basic entities that are usually seen to users
58  *         regardless of standard such as channel number and name.</li>
59  *     <li>A row in the {@link Programs} table represents a set of data describing a TV program such
60  *         as program title and start time.</li>
61  * </ul>
62  */
63 public final class TvContract {
64     /** The authority for the TV provider. */
65     public static final String AUTHORITY = "android.media.tv";
66 
67     /**
68      * Permission to read TV listings. This is required to read all the TV channel and program
69      * information available on the system.
70      * @hide
71      */
72     public static final String PERMISSION_READ_TV_LISTINGS = "android.permission.READ_TV_LISTINGS";
73 
74     private static final String PATH_CHANNEL = "channel";
75     private static final String PATH_PROGRAM = "program";
76     private static final String PATH_RECORDED_PROGRAM = "recorded_program";
77     private static final String PATH_PREVIEW_PROGRAM = "preview_program";
78     private static final String PATH_WATCH_NEXT_PROGRAM = "watch_next_program";
79     private static final String PATH_PASSTHROUGH = "passthrough";
80 
81     /**
82      * Broadcast Action: sent when an application requests the system to make the given channel
83      * browsable.  The operation is performed in the background without user interaction. This
84      * is only relevant to channels with {@link Channels#TYPE_PREVIEW} type.
85      *
86      * <p>The intent must contain the following bundle parameters:
87      * <ul>
88      *     <li>{@link #EXTRA_CHANNEL_ID}: ID for the {@link Channels#TYPE_PREVIEW} channel as a long
89      *     integer.</li>
90      *     <li>{@link #EXTRA_PACKAGE_NAME}: the package name of the requesting application.</li>
91      * </ul>
92      * @hide
93      */
94     @SystemApi
95     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
96     public static final String ACTION_CHANNEL_BROWSABLE_REQUESTED =
97             "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED";
98 
99     /**
100      * Activity Action: sent by an application telling the system to make the given channel
101      * browsable with user interaction. The system may show UI to ask user to approve the channel.
102      * This is only relevant to channels with {@link Channels#TYPE_PREVIEW} type. Use
103      * {@link Activity#startActivityForResult} to get the result of the request.
104      *
105      * <p>The intent must contain the following bundle parameters:
106      * <ul>
107      *     <li>{@link #EXTRA_CHANNEL_ID}: ID for the {@link Channels#TYPE_PREVIEW} channel as a long
108      *     integer.</li>
109      * </ul>
110      */
111     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
112     public static final String ACTION_REQUEST_CHANNEL_BROWSABLE =
113             "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
114 
115     /**
116      * Broadcast Action: sent by the system to tell the target TV input that one of its preview
117      * program's browsable state is disabled, i.e., it will no longer be shown to users, which, for
118      * example, might be a result of users' interaction with UI. The input is expected to delete the
119      * preview program from the content provider.
120      *
121      * <p>The intent must contain the following bundle parameter:
122      * <ul>
123      *     <li>{@link #EXTRA_PREVIEW_PROGRAM_ID}: the disabled preview program ID.</li>
124      * </ul>
125      */
126     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
127     public static final String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED =
128             "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
129 
130     /**
131      * Broadcast Action: sent by the system to tell the target TV input that one of its "watch next"
132      * program's browsable state is disabled, i.e., it will no longer be shown to users, which, for
133      * example, might be a result of users' interaction with UI. The input is expected to delete the
134      * "watch next" program from the content provider.
135      *
136      * <p>The intent must contain the following bundle parameter:
137      * <ul>
138      *     <li>{@link #EXTRA_WATCH_NEXT_PROGRAM_ID}: the disabled "watch next" program ID.</li>
139      * </ul>
140      */
141     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
142     public static final String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED =
143             "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
144 
145     /**
146      * Broadcast Action: sent by the system to tell the target TV input that one of its existing
147      * preview programs is added to the watch next programs table by user.
148      *
149      * <p>The intent must contain the following bundle parameters:
150      * <ul>
151      *     <li>{@link #EXTRA_PREVIEW_PROGRAM_ID}: the ID of the existing preview program.</li>
152      *     <li>{@link #EXTRA_WATCH_NEXT_PROGRAM_ID}: the ID of the new watch next program.</li>
153      * </ul>
154      */
155     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
156     public static final String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT =
157             "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
158 
159     /**
160      * Broadcast Action: sent to the target TV input after it is first installed to notify the input
161      * to initialize its channels and programs to the system content provider.
162      *
163      * <p>Note that this intent is sent only on devices with
164      * {@link android.content.pm.PackageManager#FEATURE_LEANBACK} enabled. Besides that, in order
165      * to receive this intent, the target TV input must:
166      * <ul>
167      *     <li>Declare a broadcast receiver for this intent in its
168      *         <code>AndroidManifest.xml</code>.</li>
169      *     <li>Declare appropriate permissions to write channel and program data in its
170      *         <code>AndroidManifest.xml</code>.</li>
171      * </ul>
172      */
173     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
174     public static final String ACTION_INITIALIZE_PROGRAMS =
175             "android.media.tv.action.INITIALIZE_PROGRAMS";
176 
177     /**
178      * The key for a bundle parameter containing a channel ID as a long integer
179      */
180     public static final String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
181 
182     /**
183      * The key for a bundle parameter containing a package name as a string.
184      * @hide
185      */
186     @SystemApi
187     public static final String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
188 
189     /** The key for a bundle parameter containing a program ID as a long integer. */
190     public static final String EXTRA_PREVIEW_PROGRAM_ID =
191             "android.media.tv.extra.PREVIEW_PROGRAM_ID";
192 
193     /** The key for a bundle parameter containing a watch next program ID as a long integer. */
194     public static final String EXTRA_WATCH_NEXT_PROGRAM_ID =
195             "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
196 
197     /**
198      * The key for a bundle parameter containing the result code of a method call as an integer.
199      *
200      * @see #RESULT_OK
201      * @see #RESULT_ERROR_IO
202      * @see #RESULT_ERROR_INVALID_ARGUMENT
203      * @hide
204      */
205     @SystemApi
206     public static final String EXTRA_RESULT_CODE = "android.media.tv.extra.RESULT_CODE";
207 
208     /**
209      * The result code for a successful execution without error.
210      * @hide
211      */
212     @SystemApi
213     public static final int RESULT_OK = 0;
214 
215     /**
216      * The result code for a failure from I/O operation.
217      * @hide
218      */
219     @SystemApi
220     public static final int RESULT_ERROR_IO = 1;
221 
222     /**
223      * The result code for a failure from invalid argument.
224      * @hide
225      */
226     @SystemApi
227     public static final int RESULT_ERROR_INVALID_ARGUMENT = 2;
228 
229     /**
230      * The method name to get existing columns in the given table of the specified content provider.
231      *
232      * <p>The method caller must provide the following parameter:
233      * <ul>
234      *     <li>{@code arg}: The content URI of the target table as a {@link String}.</li>
235      * </ul>
236 
237      * <p>On success, the returned {@link android.os.Bundle} will include existing column names
238      * with the key {@link #EXTRA_EXISTING_COLUMN_NAMES}. Otherwise, the return value will be {@code null}.
239      *
240      * @see ContentResolver#call(Uri, String, String, Bundle)
241      * @see #EXTRA_EXISTING_COLUMN_NAMES
242      * @hide
243      */
244     @SystemApi
245     public static final String METHOD_GET_COLUMNS = "get_columns";
246 
247     /**
248      * The method name to add a new column in the given table of the specified content provider.
249      *
250      * <p>The method caller must provide the following parameter:
251      * <ul>
252      *     <li>{@code arg}: The content URI of the target table as a {@link String}.</li>
253      *     <li>{@code extra}: Name, data type, and default value of the new column in a Bundle:
254      *         <ul>
255      *             <li>{@link #EXTRA_COLUMN_NAME} the column name as a {@link String}.</li>
256      *             <li>{@link #EXTRA_DATA_TYPE} the data type as a {@link String}.</li>
257      *             <li>{@link #EXTRA_DEFAULT_VALUE} the default value as a {@link String}.
258      *                 (optional)</li>
259      *         </ul>
260      *     </li>
261      * </ul>
262      *
263      * <p>On success, the returned {@link android.os.Bundle} will include current colum names after
264      * the addition operation with the key {@link #EXTRA_EXISTING_COLUMN_NAMES}. Otherwise, the
265      * return value will be {@code null}.
266      *
267      * @see ContentResolver#call(Uri, String, String, Bundle)
268      * @see #EXTRA_COLUMN_NAME
269      * @see #EXTRA_DATA_TYPE
270      * @see #EXTRA_DEFAULT_VALUE
271      * @see #EXTRA_EXISTING_COLUMN_NAMES
272      * @hide
273      */
274     @SystemApi
275     public static final String METHOD_ADD_COLUMN = "add_column";
276 
277     /**
278      * The method name to get all the blocked packages. When a package is blocked, all the data for
279      * preview programs/channels and watch next programs belonging to this package in the content
280      * provider will be cleared. Once a package is blocked, {@link SecurityException} will be thrown
281      * for all the requests to preview programs/channels and watch next programs via
282      * {@link android.content.ContentProvider} from it.
283      *
284      * <p>The returned {@link android.os.Bundle} will include all the blocked package names with the
285      * key {@link #EXTRA_BLOCKED_PACKAGES}.
286      *
287      * @see ContentResolver#call(Uri, String, String, Bundle)
288      * @see #EXTRA_BLOCKED_PACKAGES
289      * @see #METHOD_BLOCK_PACKAGE
290      * @see #METHOD_UNBLOCK_PACKAGE
291      * @hide
292      */
293     @SystemApi
294     public static final String METHOD_GET_BLOCKED_PACKAGES = "get_blocked_packages";
295 
296     /**
297      * The method name to block the access from the given package. When a package is blocked, all
298      * the data for preview programs/channels and watch next programs belonging to this package in
299      * the content provider will be cleared. Once a package is blocked, {@link SecurityException}
300      * will be thrown for all the requests to preview programs/channels and watch next programs via
301      * {@link android.content.ContentProvider} from it.
302      *
303      * <p>The method caller must provide the following parameter:
304      * <ul>
305      *     <li>{@code arg}: The package name to be added as blocked package {@link String}.</li>
306      * </ul>
307      *
308      * <p>The returned {@link android.os.Bundle} will include an integer code denoting whether the
309      * execution is successful or not with the key {@link #EXTRA_RESULT_CODE}. If {@code arg} is
310      * empty, the result code will be {@link #RESULT_ERROR_INVALID_ARGUMENT}. If success, the result
311      * code will be {@link #RESULT_OK}. Otherwise, the result code will be {@link #RESULT_ERROR_IO}.
312      *
313      * @see ContentResolver#call(Uri, String, String, Bundle)
314      * @see #EXTRA_RESULT_CODE
315      * @see #METHOD_GET_BLOCKED_PACKAGES
316      * @see #METHOD_UNBLOCK_PACKAGE
317      * @hide
318      */
319     @SystemApi
320     public static final String METHOD_BLOCK_PACKAGE = "block_package";
321 
322     /**
323      * The method name to unblock the access from the given package. When a package is blocked, all
324      * the data for preview programs/channels and watch next programs belonging to this package in
325      * the content provider will be cleared. Once a package is blocked, {@link SecurityException}
326      * will be thrown for all the requests to preview programs/channels and watch next programs via
327      * {@link android.content.ContentProvider} from it.
328      *
329      * <p>The method caller must provide the following parameter:
330      * <ul>
331      *     <li>{@code arg}: The package name to be removed from blocked list as a {@link String}.
332      *     </li>
333      * </ul>
334      *
335      * <p>The returned {@link android.os.Bundle} will include an integer code denoting whether the
336      * execution is successful or not with the key {@link #EXTRA_RESULT_CODE}. If {@code arg} is
337      * empty, the result code will be {@link #RESULT_ERROR_INVALID_ARGUMENT}. If success, the result
338      * code will be {@link #RESULT_OK}. Otherwise, the result code will be {@link #RESULT_ERROR_IO}.
339      *
340      * @see ContentResolver#call(Uri, String, String, Bundle)
341      * @see #EXTRA_RESULT_CODE
342      * @see #METHOD_GET_BLOCKED_PACKAGES
343      * @see #METHOD_BLOCK_PACKAGE
344      * @hide
345      */
346     @SystemApi
347     public static final String METHOD_UNBLOCK_PACKAGE = "unblock_package";
348 
349     /**
350      * The key for a returned {@link Bundle} value containing existing column names in the given
351      * table as an {@link ArrayList} of {@link String}.
352      *
353      * @see #METHOD_GET_COLUMNS
354      * @see #METHOD_ADD_COLUMN
355      * @hide
356      */
357     @SystemApi
358     public static final String EXTRA_EXISTING_COLUMN_NAMES =
359             "android.media.tv.extra.EXISTING_COLUMN_NAMES";
360 
361     /**
362      * The key for a {@link Bundle} parameter containing the new column name to be added in the
363      * given table as a non-empty {@link CharSequence}.
364      *
365      * @see #METHOD_ADD_COLUMN
366      * @hide
367      */
368     @SystemApi
369     public static final String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
370 
371     /**
372      * The key for a {@link Bundle} parameter containing the data type of the new column to be added
373      * in the given table as a non-empty {@link CharSequence}, which should be one of the following
374      * values: {@code "TEXT"}, {@code "INTEGER"}, {@code "REAL"}, or {@code "BLOB"}.
375      *
376      * @see #METHOD_ADD_COLUMN
377      * @hide
378      */
379     @SystemApi
380     public static final String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
381 
382     /**
383      * The key for a {@link Bundle} parameter containing the default value of the new column to be
384      * added in the given table as a {@link CharSequence}, which represents a valid default value
385      * according to the data type provided with {@link #EXTRA_DATA_TYPE}.
386      *
387      * @see #METHOD_ADD_COLUMN
388      * @hide
389      */
390     @SystemApi
391     public static final String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
392 
393     /**
394      * The key for a returned {@link Bundle} value containing all the blocked package names as an
395      * {@link ArrayList} of {@link String}.
396      *
397      * @see #METHOD_GET_BLOCKED_PACKAGES
398      * @hide
399      */
400     @SystemApi
401     public static final String EXTRA_BLOCKED_PACKAGES = "android.media.tv.extra.BLOCKED_PACKAGES";
402 
403     /**
404      * An optional query, update or delete URI parameter that allows the caller to specify TV input
405      * ID to filter channels.
406      * @hide
407      */
408     public static final String PARAM_INPUT = "input";
409 
410     /**
411      * An optional query, update or delete URI parameter that allows the caller to specify channel
412      * ID to filter programs.
413      * @hide
414      */
415     public static final String PARAM_CHANNEL = "channel";
416 
417     /**
418      * An optional query, update or delete URI parameter that allows the caller to specify start
419      * time (in milliseconds since the epoch) to filter programs.
420      * @hide
421      */
422     public static final String PARAM_START_TIME = "start_time";
423 
424     /**
425      * An optional query, update or delete URI parameter that allows the caller to specify end time
426      * (in milliseconds since the epoch) to filter programs.
427      * @hide
428      */
429     public static final String PARAM_END_TIME = "end_time";
430 
431     /**
432      * A query, update or delete URI parameter that allows the caller to operate on all or
433      * browsable-only channels. If set to "true", the rows that contain non-browsable channels are
434      * not affected.
435      * @hide
436      */
437     public static final String PARAM_BROWSABLE_ONLY = "browsable_only";
438 
439     /**
440      * An optional query, update or delete URI parameter that allows the caller to specify canonical
441      * genre to filter programs.
442      * @hide
443      */
444     public static final String PARAM_CANONICAL_GENRE = "canonical_genre";
445 
446     /**
447      * A query, update or delete URI parameter that allows the caller to operate only on preview or
448      * non-preview channels. If set to "true", the operation affects the rows for preview channels
449      * only. If set to "false", the operation affects the rows for non-preview channels only.
450      * @hide
451      */
452     public static final String PARAM_PREVIEW = "preview";
453 
454     /**
455      * An optional query, update or delete URI parameter that allows the caller to specify package
456      * name to filter channels.
457      * @hide
458      */
459     public static final String PARAM_PACKAGE = "package";
460 
461     /**
462      * Builds an ID that uniquely identifies a TV input service.
463      *
464      * @param name The {@link ComponentName} of the TV input service to build ID for.
465      * @return the ID for the given TV input service.
466      */
buildInputId(ComponentName name)467     public static String buildInputId(ComponentName name) {
468         return name.flattenToShortString();
469     }
470 
471     /**
472      * Builds a URI that points to a specific channel.
473      *
474      * @param channelId The ID of the channel to point to.
475      */
buildChannelUri(long channelId)476     public static Uri buildChannelUri(long channelId) {
477         return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId);
478     }
479 
480     /**
481      * Build a special channel URI intended to be used with pass-through inputs. (e.g. HDMI)
482      *
483      * @param inputId The ID of the pass-through input to build a channels URI for.
484      * @see TvInputInfo#isPassthroughInput()
485      */
buildChannelUriForPassthroughInput(String inputId)486     public static Uri buildChannelUriForPassthroughInput(String inputId) {
487         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
488                 .appendPath(PATH_PASSTHROUGH).appendPath(inputId).build();
489     }
490 
491     /**
492      * Builds a URI that points to a channel logo. See {@link Channels.Logo}.
493      *
494      * @param channelId The ID of the channel whose logo is pointed to.
495      */
buildChannelLogoUri(long channelId)496     public static Uri buildChannelLogoUri(long channelId) {
497         return buildChannelLogoUri(buildChannelUri(channelId));
498     }
499 
500     /**
501      * Builds a URI that points to a channel logo. See {@link Channels.Logo}.
502      *
503      * @param channelUri The URI of the channel whose logo is pointed to.
504      */
buildChannelLogoUri(Uri channelUri)505     public static Uri buildChannelLogoUri(Uri channelUri) {
506         if (!isChannelUriForTunerInput(channelUri)) {
507             throw new IllegalArgumentException("Not a channel: " + channelUri);
508         }
509         return Uri.withAppendedPath(channelUri, Channels.Logo.CONTENT_DIRECTORY);
510     }
511 
512     /**
513      * Builds a URI that points to all channels from a given TV input.
514      *
515      * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
516      *            URI for all the TV inputs.
517      */
buildChannelsUriForInput(@ullable String inputId)518     public static Uri buildChannelsUriForInput(@Nullable String inputId) {
519         return buildChannelsUriForInput(inputId, false);
520     }
521 
522     /**
523      * Builds a URI that points to all or browsable-only channels from a given TV input.
524      *
525      * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
526      *            URI for all the TV inputs.
527      * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
528      *            to {@code false} the URI points to all channels regardless of whether they are
529      *            browsable or not.
530      * @hide
531      */
532     @SystemApi
buildChannelsUriForInput(@ullable String inputId, boolean browsableOnly)533     public static Uri buildChannelsUriForInput(@Nullable String inputId,
534             boolean browsableOnly) {
535         Uri.Builder builder = Channels.CONTENT_URI.buildUpon();
536         if (inputId != null) {
537             builder.appendQueryParameter(PARAM_INPUT, inputId);
538         }
539         return builder.appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly))
540                 .build();
541     }
542 
543     /**
544      * Builds a URI that points to all or browsable-only channels which have programs with the given
545      * genre from the given TV input.
546      *
547      * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
548      *            URI for all the TV inputs.
549      * @param genre {@link Programs.Genres} to search. If {@code null}, builds a URI for all genres.
550      * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
551      *            to {@code false} the URI points to all channels regardless of whether they are
552      *            browsable or not.
553      * @hide
554      */
555     @SystemApi
buildChannelsUriForInput(@ullable String inputId, @Nullable String genre, boolean browsableOnly)556     public static Uri buildChannelsUriForInput(@Nullable String inputId,
557             @Nullable String genre, boolean browsableOnly) {
558         if (genre == null) {
559             return buildChannelsUriForInput(inputId, browsableOnly);
560         }
561         if (!Programs.Genres.isCanonical(genre)) {
562             throw new IllegalArgumentException("Not a canonical genre: '" + genre + "'");
563         }
564         return buildChannelsUriForInput(inputId, browsableOnly).buildUpon()
565                 .appendQueryParameter(PARAM_CANONICAL_GENRE, genre).build();
566     }
567 
568     /**
569      * Builds a URI that points to a specific program.
570      *
571      * @param programId The ID of the program to point to.
572      */
buildProgramUri(long programId)573     public static Uri buildProgramUri(long programId) {
574         return ContentUris.withAppendedId(Programs.CONTENT_URI, programId);
575     }
576 
577     /**
578      * Builds a URI that points to all programs on a given channel.
579      *
580      * @param channelId The ID of the channel to return programs for.
581      */
buildProgramsUriForChannel(long channelId)582     public static Uri buildProgramsUriForChannel(long channelId) {
583         return Programs.CONTENT_URI.buildUpon()
584                 .appendQueryParameter(PARAM_CHANNEL, String.valueOf(channelId)).build();
585     }
586 
587     /**
588      * Builds a URI that points to all programs on a given channel.
589      *
590      * @param channelUri The URI of the channel to return programs for.
591      */
buildProgramsUriForChannel(Uri channelUri)592     public static Uri buildProgramsUriForChannel(Uri channelUri) {
593         if (!isChannelUriForTunerInput(channelUri)) {
594             throw new IllegalArgumentException("Not a channel: " + channelUri);
595         }
596         return buildProgramsUriForChannel(ContentUris.parseId(channelUri));
597     }
598 
599     /**
600      * Builds a URI that points to programs on a specific channel whose schedules overlap with the
601      * given time frame.
602      *
603      * @param channelId The ID of the channel to return programs for.
604      * @param startTime The start time used to filter programs. The returned programs will have a
605      *            {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than or equal to
606                   {@code startTime}.
607      * @param endTime The end time used to filter programs. The returned programs will have
608      *            {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than or equal to
609      *            {@code endTime}.
610      */
buildProgramsUriForChannel(long channelId, long startTime, long endTime)611     public static Uri buildProgramsUriForChannel(long channelId, long startTime,
612             long endTime) {
613         Uri uri = buildProgramsUriForChannel(channelId);
614         return uri.buildUpon().appendQueryParameter(PARAM_START_TIME, String.valueOf(startTime))
615                 .appendQueryParameter(PARAM_END_TIME, String.valueOf(endTime)).build();
616     }
617 
618     /**
619      * Builds a URI that points to programs on a specific channel whose schedules overlap with the
620      * given time frame.
621      *
622      * @param channelUri The URI of the channel to return programs for.
623      * @param startTime The start time used to filter programs. The returned programs should have
624      *            {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time.
625      * @param endTime The end time used to filter programs. The returned programs should have
626      *            {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time.
627      */
buildProgramsUriForChannel(Uri channelUri, long startTime, long endTime)628     public static Uri buildProgramsUriForChannel(Uri channelUri, long startTime,
629             long endTime) {
630         if (!isChannelUriForTunerInput(channelUri)) {
631             throw new IllegalArgumentException("Not a channel: " + channelUri);
632         }
633         return buildProgramsUriForChannel(ContentUris.parseId(channelUri), startTime, endTime);
634     }
635 
636     /**
637      * Builds a URI that points to a specific recorded program.
638      *
639      * @param recordedProgramId The ID of the recorded program to point to.
640      */
buildRecordedProgramUri(long recordedProgramId)641     public static Uri buildRecordedProgramUri(long recordedProgramId) {
642         return ContentUris.withAppendedId(RecordedPrograms.CONTENT_URI, recordedProgramId);
643     }
644 
645     /**
646      * Builds a URI that points to a specific preview program.
647      *
648      * @param previewProgramId The ID of the preview program to point to.
649      */
buildPreviewProgramUri(long previewProgramId)650     public static Uri buildPreviewProgramUri(long previewProgramId) {
651         return ContentUris.withAppendedId(PreviewPrograms.CONTENT_URI, previewProgramId);
652     }
653 
654     /**
655      * Builds a URI that points to all preview programs on a given channel.
656      *
657      * @param channelId The ID of the channel to return preview programs for.
658      */
buildPreviewProgramsUriForChannel(long channelId)659     public static Uri buildPreviewProgramsUriForChannel(long channelId) {
660         return PreviewPrograms.CONTENT_URI.buildUpon()
661                 .appendQueryParameter(PARAM_CHANNEL, String.valueOf(channelId)).build();
662     }
663 
664     /**
665      * Builds a URI that points to all preview programs on a given channel.
666      *
667      * @param channelUri The URI of the channel to return preview programs for.
668      */
buildPreviewProgramsUriForChannel(Uri channelUri)669     public static Uri buildPreviewProgramsUriForChannel(Uri channelUri) {
670         if (!isChannelUriForTunerInput(channelUri)) {
671             throw new IllegalArgumentException("Not a channel: " + channelUri);
672         }
673         return buildPreviewProgramsUriForChannel(ContentUris.parseId(channelUri));
674     }
675 
676     /**
677      * Builds a URI that points to a specific watch next program.
678      *
679      * @param watchNextProgramId The ID of the watch next program to point to.
680      */
buildWatchNextProgramUri(long watchNextProgramId)681     public static Uri buildWatchNextProgramUri(long watchNextProgramId) {
682         return ContentUris.withAppendedId(WatchNextPrograms.CONTENT_URI, watchNextProgramId);
683     }
684 
685     /**
686      * Builds a URI that points to a specific program the user watched.
687      *
688      * @param watchedProgramId The ID of the watched program to point to.
689      * @hide
690      */
buildWatchedProgramUri(long watchedProgramId)691     public static Uri buildWatchedProgramUri(long watchedProgramId) {
692         return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId);
693     }
694 
isTvUri(Uri uri)695     private static boolean isTvUri(Uri uri) {
696         return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())
697                 && AUTHORITY.equals(uri.getAuthority());
698     }
699 
isTwoSegmentUriStartingWith(Uri uri, String pathSegment)700     private static boolean isTwoSegmentUriStartingWith(Uri uri, String pathSegment) {
701         List<String> pathSegments = uri.getPathSegments();
702         return pathSegments.size() == 2 && pathSegment.equals(pathSegments.get(0));
703     }
704 
705     /**
706      * @return {@code true} if {@code uri} is a channel URI.
707      */
isChannelUri(@onNull Uri uri)708     public static boolean isChannelUri(@NonNull Uri uri) {
709         return isChannelUriForTunerInput(uri) || isChannelUriForPassthroughInput(uri);
710     }
711 
712     /**
713      * @return {@code true} if {@code uri} is a channel URI for a tuner input.
714      */
isChannelUriForTunerInput(@onNull Uri uri)715     public static boolean isChannelUriForTunerInput(@NonNull Uri uri) {
716         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_CHANNEL);
717     }
718 
719     /**
720      * @return {@code true} if {@code uri} is a channel URI for a pass-through input.
721      */
isChannelUriForPassthroughInput(@onNull Uri uri)722     public static boolean isChannelUriForPassthroughInput(@NonNull Uri uri) {
723         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PASSTHROUGH);
724     }
725 
726     /**
727      * @return {@code true} if {@code uri} is a program URI.
728      */
isProgramUri(@onNull Uri uri)729     public static boolean isProgramUri(@NonNull Uri uri) {
730         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM);
731     }
732 
733     /**
734      * @return {@code true} if {@code uri} is a recorded program URI.
735      */
isRecordedProgramUri(@onNull Uri uri)736     public static boolean isRecordedProgramUri(@NonNull Uri uri) {
737         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_RECORDED_PROGRAM);
738     }
739 
740     /**
741      * Requests to make a channel browsable.
742      *
743      * <p>Once called, the system will review the request and make the channel browsable based on
744      * its policy. The first request from a package is guaranteed to be approved. This is only
745      * relevant to channels with {@link Channels#TYPE_PREVIEW} type.
746      *
747      * @param context The context for accessing content provider.
748      * @param channelId The channel ID to be browsable.
749      * @see Channels#COLUMN_BROWSABLE
750      */
requestChannelBrowsable(Context context, long channelId)751     public static void requestChannelBrowsable(Context context, long channelId) {
752         TvInputManager manager = (TvInputManager) context.getSystemService(
753             Context.TV_INPUT_SERVICE);
754         if (manager != null) {
755             manager.requestChannelBrowsable(buildChannelUri(channelId));
756         }
757     }
758 
TvContract()759     private TvContract() {}
760 
761     /**
762      * Common base for the tables of TV channels/programs.
763      */
764     public interface BaseTvColumns extends BaseColumns {
765         /**
766          * The name of the package that owns the current row.
767          *
768          * <p>The TV provider fills in this column with the name of the package that provides the
769          * initial data of the row. If the package is later uninstalled, the rows it owns are
770          * automatically removed from the tables.
771          *
772          * <p>Type: TEXT
773          */
774         String COLUMN_PACKAGE_NAME = "package_name";
775     }
776 
777     /**
778      * Common columns for the tables of TV programs.
779      * @hide
780      */
781     interface ProgramColumns {
782         /** @hide */
783         @IntDef({
784                 REVIEW_RATING_STYLE_STARS,
785                 REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
786                 REVIEW_RATING_STYLE_PERCENTAGE,
787         })
788         @Retention(RetentionPolicy.SOURCE)
789         @interface ReviewRatingStyle {}
790 
791         /**
792          * The review rating style for five star rating.
793          *
794          * @see #COLUMN_REVIEW_RATING_STYLE
795          */
796         int REVIEW_RATING_STYLE_STARS = 0;
797 
798         /**
799          * The review rating style for thumbs-up and thumbs-down rating.
800          *
801          * @see #COLUMN_REVIEW_RATING_STYLE
802          */
803         int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1;
804 
805         /**
806          * The review rating style for 0 to 100 point system.
807          *
808          * @see #COLUMN_REVIEW_RATING_STYLE
809          */
810         int REVIEW_RATING_STYLE_PERCENTAGE = 2;
811 
812         /**
813          * The title of this TV program.
814          *
815          * <p>If this program is an episodic TV show, it is recommended that the title is the series
816          * title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or
817          * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_SEASON_DISPLAY_NUMBER},
818          * {@link #COLUMN_EPISODE_DISPLAY_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
819          *
820          * <p>Type: TEXT
821          */
822         String COLUMN_TITLE = "title";
823 
824         /**
825          * The season display number of this TV program for episodic TV shows.
826          *
827          * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value
828          * does not necessarily be numeric. (e.g. 12B)
829          *
830          * <p>Can be empty.
831          *
832          * <p>Type: TEXT
833          */
834         String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
835 
836         /**
837          * The title of the season for this TV program for episodic TV shows.
838          *
839          * <p>This is an optional field supplied only when the season has a special title
840          * (e.g. The Final Season). If provided, the applications should display it instead of
841          * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, and should display it without alterations.
842          * (e.g. for "The Final Season", displayed string should be "The Final Season", not
843          * "Season The Final Season"). When displaying multiple programs, the order should be based
844          * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists.
845          *
846          * <p>Can be empty.
847          *
848          * <p>Type: TEXT
849          */
850         String COLUMN_SEASON_TITLE = "season_title";
851 
852         /**
853          * The episode display number of this TV program for episodic TV shows.
854          *
855          * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value
856          * does not necessarily be numeric. (e.g. 12B)
857          *
858          * <p>Can be empty.
859          *
860          * <p>Type: TEXT
861          */
862         String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
863 
864         /**
865          * The episode title of this TV program for episodic TV shows.
866          *
867          * <p>Can be empty.
868          *
869          * <p>Type: TEXT
870          */
871         String COLUMN_EPISODE_TITLE = "episode_title";
872 
873         /**
874          * The comma-separated canonical genre string of this TV program.
875          *
876          * <p>Canonical genres are defined in {@link Genres}. Use {@link Genres#encode} to create a
877          * text that can be stored in this column. Use {@link Genres#decode} to get the canonical
878          * genre strings from the text stored in the column.
879          *
880          * <p>Type: TEXT
881          * @see Genres
882          * @see Genres#encode
883          * @see Genres#decode
884          */
885         String COLUMN_CANONICAL_GENRE = "canonical_genre";
886 
887         /**
888          * The short description of this TV program that is displayed to the user by default.
889          *
890          * <p>It is recommended to limit the length of the descriptions to 256 characters.
891          *
892          * <p>Type: TEXT
893          */
894         String COLUMN_SHORT_DESCRIPTION = "short_description";
895 
896         /**
897          * The detailed, lengthy description of this TV program that is displayed only when the user
898          * wants to see more information.
899          *
900          * <p>TV input services should leave this field empty if they have no additional details
901          * beyond {@link #COLUMN_SHORT_DESCRIPTION}.
902          *
903          * <p>Type: TEXT
904          */
905         String COLUMN_LONG_DESCRIPTION = "long_description";
906 
907         /**
908          * The width of the video for this TV program, in the unit of pixels.
909          *
910          * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video
911          * resolution of the current TV program. Can be empty if it is not known initially or the
912          * program does not convey any video such as the programs from type
913          * {@link Channels#SERVICE_TYPE_AUDIO} channels.
914          *
915          * <p>Type: INTEGER
916          */
917         String COLUMN_VIDEO_WIDTH = "video_width";
918 
919         /**
920          * The height of the video for this TV program, in the unit of pixels.
921          *
922          * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video
923          * resolution of the current TV program. Can be empty if it is not known initially or the
924          * program does not convey any video such as the programs from type
925          * {@link Channels#SERVICE_TYPE_AUDIO} channels.
926          *
927          * <p>Type: INTEGER
928          */
929         String COLUMN_VIDEO_HEIGHT = "video_height";
930 
931         /**
932          * The comma-separated audio languages of this TV program.
933          *
934          * <p>This is used to describe available audio languages included in the program. Use either
935          * ISO 639-1 or 639-2/T codes.
936          *
937          * <p>Type: TEXT
938          */
939         String COLUMN_AUDIO_LANGUAGE = "audio_language";
940 
941         /**
942          * The comma-separated content ratings of this TV program.
943          *
944          * <p>This is used to describe the content rating(s) of this program. Each comma-separated
945          * content rating sub-string should be generated by calling
946          * {@link TvContentRating#flattenToString}. Note that in most cases the program content is
947          * rated by a single rating system, thus resulting in a corresponding single sub-string that
948          * does not require comma separation and multiple sub-strings appear only when the program
949          * content is rated by two or more content rating systems. If any of those ratings is
950          * specified as "blocked rating" in the user's parental control settings, the TV input
951          * service should block the current content and wait for the signal that it is okay to
952          * unblock.
953          *
954          * <p>Type: TEXT
955          */
956         String COLUMN_CONTENT_RATING = "content_rating";
957 
958         /**
959          * The URI for the poster art of this TV program.
960          *
961          * <p>The data in the column must be a URL, or a URI in one of the following formats:
962          *
963          * <ul>
964          * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
965          * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
966          * </li>
967          * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
968          * </ul>
969          *
970          * <p>Can be empty.
971          *
972          * <p>Type: TEXT
973          */
974         String COLUMN_POSTER_ART_URI = "poster_art_uri";
975 
976         /**
977          * The URI for the thumbnail of this TV program.
978          *
979          * <p>The system can generate a thumbnail from the poster art if this column is not
980          * specified. Thus it is not necessary for TV input services to include a thumbnail if it is
981          * just a scaled image of the poster art.
982          *
983          * <p>The data in the column must be a URL, or a URI in one of the following formats:
984          *
985          * <ul>
986          * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
987          * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
988          * </li>
989          * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
990          * </ul>
991          *
992          * <p>Can be empty.
993          *
994          * <p>Type: TEXT
995          */
996         String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
997 
998         /**
999          * The flag indicating whether this TV program is searchable or not.
1000          *
1001          * <p>The columns of searchable programs can be read by other applications that have proper
1002          * permission. Care must be taken not to open sensitive data.
1003          *
1004          * <p>A value of 1 indicates that the program is searchable and its columns can be read by
1005          * other applications, a value of 0 indicates that the program is hidden and its columns can
1006          * be read only by the package that owns the program and the system. If not specified, this
1007          * value is set to 1 (searchable) by default.
1008          *
1009          * <p>Type: INTEGER (boolean)
1010          */
1011         String COLUMN_SEARCHABLE = "searchable";
1012 
1013         /**
1014          * Internal data used by individual TV input services.
1015          *
1016          * <p>This is internal to the provider that inserted it, and should not be decoded by other
1017          * apps.
1018          *
1019          * <p>Type: BLOB
1020          */
1021         String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
1022 
1023         /**
1024          * Internal integer flag used by individual TV input services.
1025          *
1026          * <p>This is internal to the provider that inserted it, and should not be decoded by other
1027          * apps.
1028          *
1029          * <p>Type: INTEGER
1030          */
1031         String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
1032 
1033         /**
1034          * Internal integer flag used by individual TV input services.
1035          *
1036          * <p>This is internal to the provider that inserted it, and should not be decoded by other
1037          * apps.
1038          *
1039          * <p>Type: INTEGER
1040          */
1041         String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
1042 
1043         /**
1044          * Internal integer flag used by individual TV input services.
1045          *
1046          * <p>This is internal to the provider that inserted it, and should not be decoded by other
1047          * apps.
1048          *
1049          * <p>Type: INTEGER
1050          */
1051         String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
1052 
1053         /**
1054          * Internal integer flag used by individual TV input services.
1055          *
1056          * <p>This is internal to the provider that inserted it, and should not be decoded by other
1057          * apps.
1058          *
1059          * <p>Type: INTEGER
1060          */
1061         String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
1062 
1063         /**
1064          * The version number of this row entry used by TV input services.
1065          *
1066          * <p>This is best used by sync adapters to identify the rows to update. The number can be
1067          * defined by individual TV input services. One may assign the same value as
1068          * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
1069          * broadcast.
1070          *
1071          * <p>Type: INTEGER
1072          */
1073         String COLUMN_VERSION_NUMBER = "version_number";
1074 
1075         /**
1076          * The review rating score style used for {@link #COLUMN_REVIEW_RATING}.
1077          *
1078          * <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
1079          * {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
1080          *
1081          * <p>Type: INTEGER
1082          * @see #COLUMN_REVIEW_RATING
1083          */
1084         String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
1085 
1086         /**
1087          * The review rating score for this program.
1088          *
1089          * <p>The format of the value is dependent on {@link #COLUMN_REVIEW_RATING_STYLE}. If the
1090          * style is {@link #REVIEW_RATING_STYLE_STARS}, the value should be a real number between
1091          * 0.0 and 5.0. (e.g. "4.5") If the style is {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN},
1092          * the value should be two integers, one for thumbs-up count and the other for thumbs-down
1093          * count, with a comma between them. (e.g. "200,40") If the style is
1094          * {@link #REVIEW_RATING_STYLE_PERCENTAGE}, the value shoule be a real number between 0 and
1095          * 100. (e.g. "99.9")
1096          *
1097          * <p>Type: TEXT
1098          * @see #COLUMN_REVIEW_RATING_STYLE
1099          */
1100         String COLUMN_REVIEW_RATING = "review_rating";
1101 
1102         /**
1103          * The series ID of this TV program for episodic TV shows.
1104          *
1105          * <p>This is used to indicate the series ID. Programs in the same series share a series ID.
1106          *
1107          * <p>Can be empty.
1108          *
1109          * <p>Type: TEXT
1110          */
1111         String COLUMN_SERIES_ID = "series_id";
1112 
1113         /**
1114          * The split ID of this TV program for multi-part content, as a URI.
1115          *
1116          * <p>A content may consist of multiple programs within the same channel or over several
1117          * channels. For example, a film might be divided into two parts interrupted by a news in
1118          * the middle or a longer sport event might be split into several parts over several
1119          * channels. The split ID is used to identify all the programs in the same multi-part
1120          * content. Suitable URIs include
1121          * <ul>
1122          * <li>{@code crid://<CRIDauthority>/<data>#<IMI>} from ETSI TS 102 323
1123          * </ul>
1124          *
1125          * <p>Can be empty.
1126          *
1127          * <p>Type: TEXT
1128          */
1129         String COLUMN_SPLIT_ID = "split_id";
1130     }
1131 
1132     /**
1133      * Common columns for the tables of preview programs.
1134      * @hide
1135      */
1136     interface PreviewProgramColumns {
1137 
1138         /** @hide */
1139         @IntDef({
1140                 TYPE_MOVIE,
1141                 TYPE_TV_SERIES,
1142                 TYPE_TV_SEASON,
1143                 TYPE_TV_EPISODE,
1144                 TYPE_CLIP,
1145                 TYPE_EVENT,
1146                 TYPE_CHANNEL,
1147                 TYPE_TRACK,
1148                 TYPE_ALBUM,
1149                 TYPE_ARTIST,
1150                 TYPE_PLAYLIST,
1151                 TYPE_STATION,
1152         })
1153         @Retention(RetentionPolicy.SOURCE)
1154         public @interface Type {}
1155 
1156         /**
1157          * The program type for movie.
1158          *
1159          * @see #COLUMN_TYPE
1160          */
1161         int TYPE_MOVIE = 0;
1162 
1163         /**
1164          * The program type for TV series.
1165          *
1166          * @see #COLUMN_TYPE
1167          */
1168         int TYPE_TV_SERIES = 1;
1169 
1170         /**
1171          * The program type for TV season.
1172          *
1173          * @see #COLUMN_TYPE
1174          */
1175         int TYPE_TV_SEASON = 2;
1176 
1177         /**
1178          * The program type for TV episode.
1179          *
1180          * @see #COLUMN_TYPE
1181          */
1182         int TYPE_TV_EPISODE = 3;
1183 
1184         /**
1185          * The program type for clip.
1186          *
1187          * @see #COLUMN_TYPE
1188          */
1189         int TYPE_CLIP = 4;
1190 
1191         /**
1192          * The program type for event.
1193          *
1194          * @see #COLUMN_TYPE
1195          */
1196         int TYPE_EVENT = 5;
1197 
1198         /**
1199          * The program type for channel.
1200          *
1201          * @see #COLUMN_TYPE
1202          */
1203         int TYPE_CHANNEL = 6;
1204 
1205         /**
1206          * The program type for track.
1207          *
1208          * @see #COLUMN_TYPE
1209          */
1210         int TYPE_TRACK = 7;
1211 
1212         /**
1213          * The program type for album.
1214          *
1215          * @see #COLUMN_TYPE
1216          */
1217         int TYPE_ALBUM = 8;
1218 
1219         /**
1220          * The program type for artist.
1221          *
1222          * @see #COLUMN_TYPE
1223          */
1224         int TYPE_ARTIST = 9;
1225 
1226         /**
1227          * The program type for playlist.
1228          *
1229          * @see #COLUMN_TYPE
1230          */
1231         int TYPE_PLAYLIST = 10;
1232 
1233         /**
1234          * The program type for station.
1235          *
1236          * @see #COLUMN_TYPE
1237          */
1238         int TYPE_STATION = 11;
1239 
1240         /** @hide */
1241         @IntDef({
1242                 ASPECT_RATIO_16_9,
1243                 ASPECT_RATIO_3_2,
1244                 ASPECT_RATIO_1_1,
1245                 ASPECT_RATIO_2_3,
1246                 ASPECT_RATIO_4_3,
1247         })
1248         @Retention(RetentionPolicy.SOURCE)
1249         public @interface AspectRatio {}
1250 
1251         /**
1252          * The aspect ratio for 16:9.
1253          *
1254          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
1255          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
1256          */
1257         int ASPECT_RATIO_16_9 = 0;
1258 
1259         /**
1260          * The aspect ratio for 3:2.
1261          *
1262          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
1263          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
1264          */
1265         int ASPECT_RATIO_3_2 = 1;
1266 
1267         /**
1268          * The aspect ratio for 4:3.
1269          *
1270          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
1271          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
1272          */
1273         int ASPECT_RATIO_4_3 = 2;
1274 
1275         /**
1276          * The aspect ratio for 1:1.
1277          *
1278          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
1279          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
1280          */
1281         int ASPECT_RATIO_1_1 = 3;
1282 
1283         /**
1284          * The aspect ratio for 2:3.
1285          *
1286          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
1287          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
1288          */
1289         int ASPECT_RATIO_2_3 = 4;
1290 
1291         /** @hide */
1292         @IntDef({
1293                 AVAILABILITY_AVAILABLE,
1294                 AVAILABILITY_FREE_WITH_SUBSCRIPTION,
1295                 AVAILABILITY_PAID_CONTENT,
1296         })
1297         @Retention(RetentionPolicy.SOURCE)
1298         public @interface Availability {}
1299 
1300         /**
1301          * The availability for "available to this user".
1302          *
1303          * @see #COLUMN_AVAILABILITY
1304          */
1305         int AVAILABILITY_AVAILABLE = 0;
1306 
1307         /**
1308          * The availability for "free with subscription".
1309          *
1310          * @see #COLUMN_AVAILABILITY
1311          */
1312         int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1;
1313 
1314         /**
1315          * The availability for "paid content, either to-own or rental
1316          * (user has not purchased/rented).
1317          *
1318          * @see #COLUMN_AVAILABILITY
1319          */
1320         int AVAILABILITY_PAID_CONTENT = 2;
1321 
1322         /** @hide */
1323         @IntDef({
1324                 INTERACTION_TYPE_VIEWS,
1325                 INTERACTION_TYPE_LISTENS,
1326                 INTERACTION_TYPE_FOLLOWERS,
1327                 INTERACTION_TYPE_FANS,
1328                 INTERACTION_TYPE_LIKES,
1329                 INTERACTION_TYPE_THUMBS,
1330                 INTERACTION_TYPE_VIEWERS,
1331         })
1332         @Retention(RetentionPolicy.SOURCE)
1333         public @interface InteractionType {}
1334 
1335         /**
1336          * The interaction type for "views".
1337          *
1338          * @see #COLUMN_INTERACTION_TYPE
1339          */
1340         int INTERACTION_TYPE_VIEWS = 0;
1341 
1342         /**
1343          * The interaction type for "listens".
1344          *
1345          * @see #COLUMN_INTERACTION_TYPE
1346          */
1347         int INTERACTION_TYPE_LISTENS = 1;
1348 
1349         /**
1350          * The interaction type for "followers".
1351          *
1352          * @see #COLUMN_INTERACTION_TYPE
1353          */
1354         int INTERACTION_TYPE_FOLLOWERS = 2;
1355 
1356         /**
1357          * The interaction type for "fans".
1358          *
1359          * @see #COLUMN_INTERACTION_TYPE
1360          */
1361         int INTERACTION_TYPE_FANS = 3;
1362 
1363         /**
1364          * The interaction type for "likes".
1365          *
1366          * @see #COLUMN_INTERACTION_TYPE
1367          */
1368         int INTERACTION_TYPE_LIKES = 4;
1369 
1370         /**
1371          * The interaction type for "thumbs".
1372          *
1373          * @see #COLUMN_INTERACTION_TYPE
1374          */
1375         int INTERACTION_TYPE_THUMBS = 5;
1376 
1377         /**
1378          * The interaction type for "viewers".
1379          *
1380          * @see #COLUMN_INTERACTION_TYPE
1381          */
1382         int INTERACTION_TYPE_VIEWERS = 6;
1383 
1384         /**
1385          * The type of this program content.
1386          *
1387          * <p>The value should match one of the followings:
1388          * {@link #TYPE_MOVIE},
1389          * {@link #TYPE_TV_SERIES},
1390          * {@link #TYPE_TV_SEASON},
1391          * {@link #TYPE_TV_EPISODE},
1392          * {@link #TYPE_CLIP},
1393          * {@link #TYPE_EVENT},
1394          * {@link #TYPE_CHANNEL},
1395          * {@link #TYPE_TRACK},
1396          * {@link #TYPE_ALBUM},
1397          * {@link #TYPE_ARTIST},
1398          * {@link #TYPE_PLAYLIST}, and
1399          * {@link #TYPE_STATION}.
1400          *
1401          * <p>This is a required field if the program is from a {@link Channels#TYPE_PREVIEW}
1402          * channel.
1403          *
1404          * <p>Type: INTEGER
1405          */
1406         String COLUMN_TYPE = "type";
1407 
1408         /**
1409          * The aspect ratio of the poster art for this TV program.
1410          *
1411          * <p>The value should match one of the followings:
1412          * {@link #ASPECT_RATIO_16_9},
1413          * {@link #ASPECT_RATIO_3_2},
1414          * {@link #ASPECT_RATIO_4_3},
1415          * {@link #ASPECT_RATIO_1_1}, and
1416          * {@link #ASPECT_RATIO_2_3}.
1417          *
1418          * <p>Type: INTEGER
1419          */
1420         String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
1421 
1422         /**
1423          * The aspect ratio of the thumbnail for this TV program.
1424          *
1425          * <p>The value should match one of the followings:
1426          * {@link #ASPECT_RATIO_16_9},
1427          * {@link #ASPECT_RATIO_3_2},
1428          * {@link #ASPECT_RATIO_4_3},
1429          * {@link #ASPECT_RATIO_1_1}, and
1430          * {@link #ASPECT_RATIO_2_3}.
1431          *
1432          * <p>Type: INTEGER
1433          */
1434         String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
1435 
1436         /**
1437          * The URI for the logo of this TV program.
1438          *
1439          * <p>This is a small badge shown on top of the poster art or thumbnail representing the
1440          * source of the content.
1441          *
1442          * <p>The data in the column must be a URL, or a URI in one of the following formats:
1443          *
1444          * <ul>
1445          * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
1446          * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
1447          * </li>
1448          * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
1449          * </ul>
1450          *
1451          * <p>Can be empty.
1452          *
1453          * <p>Type: TEXT
1454          */
1455         String COLUMN_LOGO_URI = "logo_uri";
1456 
1457         /**
1458          * The availability of this TV program.
1459          *
1460          * <p>The value should match one of the followings:
1461          * {@link #AVAILABILITY_AVAILABLE},
1462          * {@link #AVAILABILITY_FREE_WITH_SUBSCRIPTION}, and
1463          * {@link #AVAILABILITY_PAID_CONTENT}.
1464          *
1465          * <p>Type: INTEGER
1466          */
1467         String COLUMN_AVAILABILITY = "availability";
1468 
1469         /**
1470          * The starting price of this TV program.
1471          *
1472          * <p>This indicates the lowest regular acquisition cost of the content. It is only used
1473          * if the availability of the program is {@link #AVAILABILITY_PAID_CONTENT}.
1474          *
1475          * <p>Type: TEXT
1476          * @see #COLUMN_OFFER_PRICE
1477          */
1478         String COLUMN_STARTING_PRICE = "starting_price";
1479 
1480         /**
1481          * The offer price of this TV program.
1482          *
1483          * <p>This is the promotional cost of the content. It is only used if the availability of
1484          * the program is {@link #AVAILABILITY_PAID_CONTENT}.
1485          *
1486          * <p>Type: TEXT
1487          * @see #COLUMN_STARTING_PRICE
1488          */
1489         String COLUMN_OFFER_PRICE = "offer_price";
1490 
1491         /**
1492          * The release date of this TV program.
1493          *
1494          * <p>The value should be in one of the following formats:
1495          * "yyyy", "yyyy-MM-dd", and "yyyy-MM-ddTHH:mm:ssZ" (UTC in ISO 8601).
1496          *
1497          * <p>Type: TEXT
1498          */
1499         String COLUMN_RELEASE_DATE = "release_date";
1500 
1501         /**
1502          * The count of the items included in this TV program.
1503          *
1504          * <p>This is only relevant if the program represents a collection of items such as series,
1505          * episodes, or music tracks.
1506          *
1507          * <p>Type: INTEGER
1508          */
1509         String COLUMN_ITEM_COUNT = "item_count";
1510 
1511         /**
1512          * The flag indicating whether this TV program is live or not.
1513          *
1514          * <p>A value of 1 indicates that the content is airing and should be consumed now, a value
1515          * of 0 indicates that the content is off the air and does not need to be consumed at the
1516          * present time. If not specified, the value is set to 0 (not live) by default.
1517          *
1518          * <p>Type: INTEGER (boolean)
1519          */
1520         String COLUMN_LIVE = "live";
1521 
1522         /**
1523          * The internal ID used by individual TV input services.
1524          *
1525          * <p>This is internal to the provider that inserted it, and should not be decoded by other
1526          * apps.
1527          *
1528          * <p>Can be empty.
1529          *
1530          * <p>Type: TEXT
1531          */
1532         String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
1533 
1534         /**
1535          * The URI for the preview video.
1536          *
1537          * <p>The data in the column must be a URL, or a URI in one of the following formats:
1538          *
1539          * <ul>
1540          * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
1541          * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
1542          * </li>
1543          * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
1544          * </ul>
1545          *
1546          * <p>Can be empty.
1547          *
1548          * <p>Type: TEXT
1549          */
1550         String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
1551 
1552         /**
1553          * The last playback position (in milliseconds) of the original content of this preview
1554          * program.
1555          *
1556          * <p>Can be empty.
1557          *
1558          * <p>Type: INTEGER
1559          */
1560         String COLUMN_LAST_PLAYBACK_POSITION_MILLIS =
1561                 "last_playback_position_millis";
1562 
1563         /**
1564          * The duration (in milliseconds) of the original content of this preview program.
1565          *
1566          * <p>Can be empty.
1567          *
1568          * <p>Type: INTEGER
1569          */
1570         String COLUMN_DURATION_MILLIS = "duration_millis";
1571 
1572         /**
1573          * The intent URI which is launched when the preview program is selected.
1574          *
1575          * <p>The URI is created using {@link Intent#toUri} with {@link Intent#URI_INTENT_SCHEME}
1576          * and converted back to the original intent with {@link Intent#parseUri}. The intent is
1577          * launched when the user selects the preview program item.
1578          *
1579          * <p>Can be empty.
1580          *
1581          * <p>Type: TEXT
1582          */
1583         String COLUMN_INTENT_URI = "intent_uri";
1584 
1585         /**
1586          * The flag indicating whether this program is transient or not.
1587          *
1588          * <p>A value of 1 indicates that the channel will be automatically removed by the system on
1589          * reboot, and a value of 0 indicates that the channel is persistent across reboot. If not
1590          * specified, this value is set to 0 (not transient) by default.
1591          *
1592          * <p>Type: INTEGER (boolean)
1593          * @see Channels#COLUMN_TRANSIENT
1594          */
1595         String COLUMN_TRANSIENT = "transient";
1596 
1597         /**
1598          * The type of interaction for this TV program.
1599          *
1600          * <p> The value should match one of the followings:
1601          * {@link #INTERACTION_TYPE_VIEWS},
1602          * {@link #INTERACTION_TYPE_LISTENS},
1603          * {@link #INTERACTION_TYPE_FOLLOWERS},
1604          * {@link #INTERACTION_TYPE_FANS},
1605          * {@link #INTERACTION_TYPE_LIKES},
1606          * {@link #INTERACTION_TYPE_THUMBS}, and
1607          * {@link #INTERACTION_TYPE_VIEWERS}.
1608          *
1609          * <p>Type: INTEGER
1610          * @see #COLUMN_INTERACTION_COUNT
1611          */
1612         String COLUMN_INTERACTION_TYPE = "interaction_type";
1613 
1614         /**
1615          * The interaction count for this program.
1616          *
1617          * <p>This indicates the number of times interaction has happened.
1618          *
1619          * <p>Type: INTEGER (long)
1620          * @see #COLUMN_INTERACTION_TYPE
1621          */
1622         String COLUMN_INTERACTION_COUNT = "interaction_count";
1623 
1624         /**
1625          * The author or artist of this content.
1626          *
1627          * <p>Type: TEXT
1628          */
1629         String COLUMN_AUTHOR = "author";
1630 
1631         /**
1632          * The flag indicating whether this TV program is browsable or not.
1633          *
1634          * <p>This column can only be set by applications having proper system permission. For
1635          * other applications, this is a read-only column.
1636          *
1637          * <p>A value of 1 indicates that the program is browsable and can be shown to users in
1638          * the UI. A value of 0 indicates that the program should be hidden from users and the
1639          * application who changes this value to 0 should send
1640          * {@link #ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED} to the owner of the program
1641          * to notify this change.
1642          *
1643          * <p>This value is set to 1 (browsable) by default.
1644          *
1645          * <p>Type: INTEGER (boolean)
1646          */
1647         String COLUMN_BROWSABLE = "browsable";
1648 
1649         /**
1650          * The content ID of this TV program.
1651          *
1652          * <p>A public ID of the content which allows the application to apply the same operation to
1653          * all the program copies in different channels.
1654          *
1655          * <p>Can be empty.
1656          *
1657          * <p>Type: TEXT
1658          */
1659         String COLUMN_CONTENT_ID = "content_id";
1660 
1661     }
1662 
1663     /** Column definitions for the TV channels table. */
1664     public static final class Channels implements BaseTvColumns {
1665 
1666         /**
1667          * The content:// style URI for this table.
1668          *
1669          * <p>SQL selection is not supported for {@link ContentResolver#query},
1670          * {@link ContentResolver#update} and {@link ContentResolver#delete} operations.
1671          */
1672         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
1673                 + PATH_CHANNEL);
1674 
1675         /** The MIME type of a directory of TV channels. */
1676         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/channel";
1677 
1678         /** The MIME type of a single TV channel. */
1679         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
1680 
1681         /** @hide */
1682         @StringDef(prefix = { "TYPE_" }, value = {
1683                 TYPE_OTHER,
1684                 TYPE_NTSC,
1685                 TYPE_PAL,
1686                 TYPE_SECAM,
1687                 TYPE_DVB_T,
1688                 TYPE_DVB_T2,
1689                 TYPE_DVB_S,
1690                 TYPE_DVB_S2,
1691                 TYPE_DVB_C,
1692                 TYPE_DVB_C2,
1693                 TYPE_DVB_H,
1694                 TYPE_DVB_SH,
1695                 TYPE_ATSC_T,
1696                 TYPE_ATSC_C,
1697                 TYPE_ATSC_M_H,
1698                 TYPE_ATSC3_T,
1699                 TYPE_ISDB_T,
1700                 TYPE_ISDB_TB,
1701                 TYPE_ISDB_S,
1702                 TYPE_ISDB_S3,
1703                 TYPE_ISDB_C,
1704                 TYPE_1SEG,
1705                 TYPE_DTMB,
1706                 TYPE_CMMB,
1707                 TYPE_T_DMB,
1708                 TYPE_S_DMB,
1709                 TYPE_PREVIEW,
1710         })
1711         @Retention(RetentionPolicy.SOURCE)
1712         public @interface Type {}
1713 
1714         /**
1715          * A generic channel type.
1716          *
1717          * Use this if the current channel is streaming-based or its broadcast system type does not
1718          * fit under any other types. This is the default channel type.
1719          *
1720          * @see #COLUMN_TYPE
1721          */
1722         public static final String TYPE_OTHER = "TYPE_OTHER";
1723 
1724         /**
1725          * The channel type for NTSC.
1726          *
1727          * @see #COLUMN_TYPE
1728          */
1729         public static final String TYPE_NTSC = "TYPE_NTSC";
1730 
1731         /**
1732          * The channel type for PAL.
1733          *
1734          * @see #COLUMN_TYPE
1735          */
1736         public static final String TYPE_PAL = "TYPE_PAL";
1737 
1738         /**
1739          * The channel type for SECAM.
1740          *
1741          * @see #COLUMN_TYPE
1742          */
1743         public static final String TYPE_SECAM = "TYPE_SECAM";
1744 
1745         /**
1746          * The channel type for DVB-T (terrestrial).
1747          *
1748          * @see #COLUMN_TYPE
1749          */
1750         public static final String TYPE_DVB_T = "TYPE_DVB_T";
1751 
1752         /**
1753          * The channel type for DVB-T2 (terrestrial).
1754          *
1755          * @see #COLUMN_TYPE
1756          */
1757         public static final String TYPE_DVB_T2 = "TYPE_DVB_T2";
1758 
1759         /**
1760          * The channel type for DVB-S (satellite).
1761          *
1762          * @see #COLUMN_TYPE
1763          */
1764         public static final String TYPE_DVB_S = "TYPE_DVB_S";
1765 
1766         /**
1767          * The channel type for DVB-S2 (satellite).
1768          *
1769          * @see #COLUMN_TYPE
1770          */
1771         public static final String TYPE_DVB_S2 = "TYPE_DVB_S2";
1772 
1773         /**
1774          * The channel type for DVB-C (cable).
1775          *
1776          * @see #COLUMN_TYPE
1777          */
1778         public static final String TYPE_DVB_C = "TYPE_DVB_C";
1779 
1780         /**
1781          * The channel type for DVB-C2 (cable).
1782          *
1783          * @see #COLUMN_TYPE
1784          */
1785         public static final String TYPE_DVB_C2 = "TYPE_DVB_C2";
1786 
1787         /**
1788          * The channel type for DVB-H (handheld).
1789          *
1790          * @see #COLUMN_TYPE
1791          */
1792         public static final String TYPE_DVB_H = "TYPE_DVB_H";
1793 
1794         /**
1795          * The channel type for DVB-SH (satellite).
1796          *
1797          * @see #COLUMN_TYPE
1798          */
1799         public static final String TYPE_DVB_SH = "TYPE_DVB_SH";
1800 
1801         /**
1802          * The channel type for ATSC (terrestrial).
1803          *
1804          * @see #COLUMN_TYPE
1805          */
1806         public static final String TYPE_ATSC_T = "TYPE_ATSC_T";
1807 
1808         /**
1809          * The channel type for ATSC (cable).
1810          *
1811          * @see #COLUMN_TYPE
1812          */
1813         public static final String TYPE_ATSC_C = "TYPE_ATSC_C";
1814 
1815         /**
1816          * The channel type for ATSC-M/H (mobile/handheld).
1817          *
1818          * @see #COLUMN_TYPE
1819          */
1820         public static final String TYPE_ATSC_M_H = "TYPE_ATSC_M_H";
1821 
1822         /**
1823          * The channel type for ATSC3.0 (terrestrial).
1824          *
1825          * @see #COLUMN_TYPE
1826          */
1827         public static final String TYPE_ATSC3_T = "TYPE_ATSC3_T";
1828 
1829         /**
1830          * The channel type for ISDB-T (terrestrial).
1831          *
1832          * @see #COLUMN_TYPE
1833          */
1834         public static final String TYPE_ISDB_T = "TYPE_ISDB_T";
1835 
1836         /**
1837          * The channel type for ISDB-Tb (Brazil).
1838          *
1839          * @see #COLUMN_TYPE
1840          */
1841         public static final String TYPE_ISDB_TB = "TYPE_ISDB_TB";
1842 
1843         /**
1844          * The channel type for ISDB-S (satellite).
1845          *
1846          * @see #COLUMN_TYPE
1847          */
1848         public static final String TYPE_ISDB_S = "TYPE_ISDB_S";
1849 
1850         /**
1851          * The channel type for ISDB-S3 (satellite).
1852          *
1853          * @see #COLUMN_TYPE
1854          */
1855         public static final String TYPE_ISDB_S3 = "TYPE_ISDB_S3";
1856 
1857         /**
1858          * The channel type for ISDB-C (cable).
1859          *
1860          * @see #COLUMN_TYPE
1861          */
1862         public static final String TYPE_ISDB_C = "TYPE_ISDB_C";
1863 
1864         /**
1865          * The channel type for 1seg (handheld).
1866          *
1867          * @see #COLUMN_TYPE
1868          */
1869         public static final String TYPE_1SEG = "TYPE_1SEG";
1870 
1871         /**
1872          * The channel type for DTMB (terrestrial).
1873          *
1874          * @see #COLUMN_TYPE
1875          */
1876         public static final String TYPE_DTMB = "TYPE_DTMB";
1877 
1878         /**
1879          * The channel type for CMMB (handheld).
1880          *
1881          * @see #COLUMN_TYPE
1882          */
1883         public static final String TYPE_CMMB = "TYPE_CMMB";
1884 
1885         /**
1886          * The channel type for T-DMB (terrestrial).
1887          *
1888          * @see #COLUMN_TYPE
1889          */
1890         public static final String TYPE_T_DMB = "TYPE_T_DMB";
1891 
1892         /**
1893          * The channel type for S-DMB (satellite).
1894          *
1895          * @see #COLUMN_TYPE
1896          */
1897         public static final String TYPE_S_DMB = "TYPE_S_DMB";
1898 
1899         /**
1900          * The channel type for preview videos.
1901          *
1902          * <P>Unlike other broadcast TV channel types, the programs in the preview channel usually
1903          * are promotional videos. The UI may treat the preview channels differently from the other
1904          * broadcast channels.
1905          *
1906          * @see #COLUMN_TYPE
1907          */
1908         public static final String TYPE_PREVIEW = "TYPE_PREVIEW";
1909 
1910         /** @hide */
1911         @StringDef(prefix = { "SERVICE_TYPE_" }, value = {
1912                 SERVICE_TYPE_OTHER,
1913                 SERVICE_TYPE_AUDIO_VIDEO,
1914                 SERVICE_TYPE_AUDIO,
1915         })
1916         @Retention(RetentionPolicy.SOURCE)
1917         public @interface ServiceType {}
1918 
1919         /** A generic service type. */
1920         public static final String SERVICE_TYPE_OTHER = "SERVICE_TYPE_OTHER";
1921 
1922         /** The service type for regular TV channels that have both audio and video. */
1923         public static final String SERVICE_TYPE_AUDIO_VIDEO = "SERVICE_TYPE_AUDIO_VIDEO";
1924 
1925         /** The service type for radio channels that have audio only. */
1926         public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO";
1927 
1928         /** @hide */
1929         @StringDef(prefix = { "VIDEO_FORMAT_" }, value = {
1930                 VIDEO_FORMAT_240P,
1931                 VIDEO_FORMAT_360P,
1932                 VIDEO_FORMAT_480I,
1933                 VIDEO_FORMAT_576I,
1934                 VIDEO_FORMAT_576P,
1935                 VIDEO_FORMAT_720P,
1936                 VIDEO_FORMAT_1080I,
1937                 VIDEO_FORMAT_1080P,
1938                 VIDEO_FORMAT_2160P,
1939                 VIDEO_FORMAT_4320P,
1940         })
1941         @Retention(RetentionPolicy.SOURCE)
1942         public @interface VideoFormat {}
1943 
1944         /** The video format for 240p. */
1945         public static final String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P";
1946 
1947         /** The video format for 360p. */
1948         public static final String VIDEO_FORMAT_360P = "VIDEO_FORMAT_360P";
1949 
1950         /** The video format for 480i. */
1951         public static final String VIDEO_FORMAT_480I = "VIDEO_FORMAT_480I";
1952 
1953         /** The video format for 480p. */
1954         public static final String VIDEO_FORMAT_480P = "VIDEO_FORMAT_480P";
1955 
1956         /** The video format for 576i. */
1957         public static final String VIDEO_FORMAT_576I = "VIDEO_FORMAT_576I";
1958 
1959         /** The video format for 576p. */
1960         public static final String VIDEO_FORMAT_576P = "VIDEO_FORMAT_576P";
1961 
1962         /** The video format for 720p. */
1963         public static final String VIDEO_FORMAT_720P = "VIDEO_FORMAT_720P";
1964 
1965         /** The video format for 1080i. */
1966         public static final String VIDEO_FORMAT_1080I = "VIDEO_FORMAT_1080I";
1967 
1968         /** The video format for 1080p. */
1969         public static final String VIDEO_FORMAT_1080P = "VIDEO_FORMAT_1080P";
1970 
1971         /** The video format for 2160p. */
1972         public static final String VIDEO_FORMAT_2160P = "VIDEO_FORMAT_2160P";
1973 
1974         /** The video format for 4320p. */
1975         public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P";
1976 
1977         /** @hide */
1978         @StringDef(prefix = { "VIDEO_RESOLUTION_" }, value = {
1979                 VIDEO_RESOLUTION_SD,
1980                 VIDEO_RESOLUTION_ED,
1981                 VIDEO_RESOLUTION_HD,
1982                 VIDEO_RESOLUTION_FHD,
1983                 VIDEO_RESOLUTION_UHD,
1984         })
1985         @Retention(RetentionPolicy.SOURCE)
1986         public @interface VideoResolution {}
1987 
1988         /** The video resolution for standard-definition. */
1989         public static final String VIDEO_RESOLUTION_SD = "VIDEO_RESOLUTION_SD";
1990 
1991         /** The video resolution for enhanced-definition. */
1992         public static final String VIDEO_RESOLUTION_ED = "VIDEO_RESOLUTION_ED";
1993 
1994         /** The video resolution for high-definition. */
1995         public static final String VIDEO_RESOLUTION_HD = "VIDEO_RESOLUTION_HD";
1996 
1997         /** The video resolution for full high-definition. */
1998         public static final String VIDEO_RESOLUTION_FHD = "VIDEO_RESOLUTION_FHD";
1999 
2000         /** The video resolution for ultra high-definition. */
2001         public static final String VIDEO_RESOLUTION_UHD = "VIDEO_RESOLUTION_UHD";
2002 
2003         private static final Map<String, String> VIDEO_FORMAT_TO_RESOLUTION_MAP = new HashMap<>();
2004 
2005         static {
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480I, VIDEO_RESOLUTION_SD)2006             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480I, VIDEO_RESOLUTION_SD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480P, VIDEO_RESOLUTION_ED)2007             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480P, VIDEO_RESOLUTION_ED);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576I, VIDEO_RESOLUTION_SD)2008             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576I, VIDEO_RESOLUTION_SD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576P, VIDEO_RESOLUTION_ED)2009             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576P, VIDEO_RESOLUTION_ED);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_720P, VIDEO_RESOLUTION_HD)2010             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_720P, VIDEO_RESOLUTION_HD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080I, VIDEO_RESOLUTION_HD)2011             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080I, VIDEO_RESOLUTION_HD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080P, VIDEO_RESOLUTION_FHD)2012             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080P, VIDEO_RESOLUTION_FHD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_2160P, VIDEO_RESOLUTION_UHD)2013             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_2160P, VIDEO_RESOLUTION_UHD);
VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_4320P, VIDEO_RESOLUTION_UHD)2014             VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_4320P, VIDEO_RESOLUTION_UHD);
2015         }
2016 
2017         /**
2018          * Returns the video resolution (definition) for a given video format.
2019          *
2020          * @param videoFormat The video format defined in {@link Channels}.
2021          * @return the corresponding video resolution string. {@code null} if the resolution string
2022          *         is not defined for the given video format.
2023          * @see #COLUMN_VIDEO_FORMAT
2024          */
2025         @Nullable
getVideoResolution(@ideoFormat String videoFormat)2026         public static final String getVideoResolution(@VideoFormat String videoFormat) {
2027             return VIDEO_FORMAT_TO_RESOLUTION_MAP.get(videoFormat);
2028         }
2029 
2030         /**
2031          * The ID of the TV input service that provides this TV channel.
2032          *
2033          * <p>Use {@link #buildInputId} to build the ID.
2034          *
2035          * <p>This is a required field.
2036          *
2037          * <p>Type: TEXT
2038          */
2039         public static final String COLUMN_INPUT_ID = "input_id";
2040 
2041         /**
2042          * The broadcast system type of this TV channel.
2043          *
2044          * <p>This is used to indicate the broadcast standard (e.g. ATSC, DVB or ISDB) the current
2045          * channel conforms to. Use {@link #TYPE_OTHER} for streaming-based channels, which is the
2046          * default channel type. The value should match one of the followings:
2047          * {@link #TYPE_1SEG},
2048          * {@link #TYPE_ATSC_C},
2049          * {@link #TYPE_ATSC_M_H},
2050          * {@link #TYPE_ATSC_T},
2051          * {@link #TYPE_ATSC3_T},
2052          * {@link #TYPE_CMMB},
2053          * {@link #TYPE_DTMB},
2054          * {@link #TYPE_DVB_C},
2055          * {@link #TYPE_DVB_C2},
2056          * {@link #TYPE_DVB_H},
2057          * {@link #TYPE_DVB_S},
2058          * {@link #TYPE_DVB_S2},
2059          * {@link #TYPE_DVB_SH},
2060          * {@link #TYPE_DVB_T},
2061          * {@link #TYPE_DVB_T2},
2062          * {@link #TYPE_ISDB_C},
2063          * {@link #TYPE_ISDB_S},
2064          * {@link #TYPE_ISDB_S3},
2065          * {@link #TYPE_ISDB_T},
2066          * {@link #TYPE_ISDB_TB},
2067          * {@link #TYPE_NTSC},
2068          * {@link #TYPE_OTHER},
2069          * {@link #TYPE_PAL},
2070          * {@link #TYPE_SECAM},
2071          * {@link #TYPE_S_DMB},
2072          * {@link #TYPE_T_DMB}, and
2073          * {@link #TYPE_PREVIEW}.
2074          *
2075          * <p>This value cannot be changed once it's set. Trying to modify it will make the update
2076          * fail.
2077          *
2078          * <p>This is a required field.
2079          *
2080          * <p>Type: TEXT
2081          */
2082         public static final String COLUMN_TYPE = "type";
2083 
2084         /**
2085          * The predefined service type of this TV channel.
2086          *
2087          * <p>This is primarily used to indicate whether the current channel is a regular TV channel
2088          * or a radio-like channel. Use the same coding for {@code service_type} in the underlying
2089          * broadcast standard if it is defined there (e.g. ATSC A/53, ETSI EN 300 468 and ARIB
2090          * STD-B10). Otherwise use one of the followings: {@link #SERVICE_TYPE_OTHER},
2091          * {@link #SERVICE_TYPE_AUDIO_VIDEO}, {@link #SERVICE_TYPE_AUDIO}
2092          *
2093          * <p>This is a required field.
2094          *
2095          * <p>Type: TEXT
2096          */
2097         public static final String COLUMN_SERVICE_TYPE = "service_type";
2098 
2099         /**
2100          * The original network ID of this TV channel.
2101          *
2102          * <p>It is used to identify the originating delivery system, if applicable. Use the same
2103          * coding for {@code original_network_id} for ETSI EN 300 468/TR 101 211 and ARIB STD-B10.
2104          *
2105          * <p>This is a required field only if the underlying broadcast standard defines the same
2106          * name field. Otherwise, leave empty.
2107          *
2108          * <p>Type: INTEGER
2109          */
2110         public static final String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
2111 
2112         /**
2113          * The transport stream ID of this channel.
2114          *
2115          * <p>It is used to identify the Transport Stream that contains the current channel from any
2116          * other multiplex within a network, if applicable. Use the same coding for
2117          * {@code transport_stream_id} defined in ISO/IEC 13818-1 if the channel is transmitted via
2118          * the MPEG Transport Stream.
2119          *
2120          * <p>This is a required field only if the current channel is transmitted via the MPEG
2121          * Transport Stream. Leave empty otherwise.
2122          *
2123          * <p>Type: INTEGER
2124          */
2125         public static final String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
2126 
2127         /**
2128          * The service ID of this channel.
2129          *
2130          * <p>It is used to identify the current service, or channel from any other services within
2131          * a given Transport Stream, if applicable. Use the same coding for {@code service_id} in
2132          * ETSI EN 300 468 and ARIB STD-B10 or {@code program_number} in ISO/IEC 13818-1.
2133          *
2134          * <p>This is a required field only if the underlying broadcast standard defines the same
2135          * name field, or the current channel is transmitted via the MPEG Transport Stream. Leave
2136          * empty otherwise.
2137          *
2138          * <p>Type: INTEGER
2139          */
2140         public static final String COLUMN_SERVICE_ID = "service_id";
2141 
2142         /**
2143          * The channel number that is displayed to the user.
2144          *
2145          * <p>The format can vary depending on broadcast standard and product specification.
2146          *
2147          * <p>Type: TEXT
2148          */
2149         public static final String COLUMN_DISPLAY_NUMBER = "display_number";
2150 
2151         /**
2152          * The channel name that is displayed to the user.
2153          *
2154          * <p>A call sign is a good candidate to use for this purpose but any name that helps the
2155          * user recognize the current channel will be enough. Can also be empty depending on
2156          * broadcast standard.
2157          *
2158          * <p> Type: TEXT
2159          */
2160         public static final String COLUMN_DISPLAY_NAME = "display_name";
2161 
2162         /**
2163          * The network affiliation for this TV channel.
2164          *
2165          * <p>This is used to identify a channel that is commonly called by its network affiliation
2166          * instead of the display name. Examples include ABC for the channel KGO-HD, FOX for the
2167          * channel KTVU-HD and NBC for the channel KNTV-HD. Can be empty if not applicable.
2168          *
2169          * <p>Type: TEXT
2170          */
2171         public static final String COLUMN_NETWORK_AFFILIATION = "network_affiliation";
2172 
2173         /**
2174          * The description of this TV channel.
2175          *
2176          * <p>Can be empty initially.
2177          *
2178          * <p>Type: TEXT
2179          */
2180         public static final String COLUMN_DESCRIPTION = "description";
2181 
2182         /**
2183          * The typical video format for programs from this TV channel.
2184          *
2185          * <p>This is primarily used to filter out channels based on video format by applications.
2186          * The value should match one of the followings: {@link #VIDEO_FORMAT_240P},
2187          * {@link #VIDEO_FORMAT_360P}, {@link #VIDEO_FORMAT_480I}, {@link #VIDEO_FORMAT_480P},
2188          * {@link #VIDEO_FORMAT_576I}, {@link #VIDEO_FORMAT_576P}, {@link #VIDEO_FORMAT_720P},
2189          * {@link #VIDEO_FORMAT_1080I}, {@link #VIDEO_FORMAT_1080P}, {@link #VIDEO_FORMAT_2160P},
2190          * {@link #VIDEO_FORMAT_4320P}. Note that the actual video resolution of each program from a
2191          * given channel can vary thus one should use {@link Programs#COLUMN_VIDEO_WIDTH} and
2192          * {@link Programs#COLUMN_VIDEO_HEIGHT} to get more accurate video resolution.
2193          *
2194          * <p>Type: TEXT
2195          *
2196          * @see #getVideoResolution
2197          */
2198         public static final String COLUMN_VIDEO_FORMAT = "video_format";
2199 
2200         /**
2201          * The flag indicating whether this TV channel is browsable or not.
2202          *
2203          * <p>This column can only be set by applications having proper system permission. For
2204          * other applications, this is a read-only column.
2205          *
2206          * <p>A value of 1 indicates the channel is included in the channel list that applications
2207          * use to browse channels, a value of 0 indicates the channel is not included in the list.
2208          * If not specified, this value is set to 0 (not browsable) by default.
2209          *
2210          * <p>Type: INTEGER (boolean)
2211          */
2212         public static final String COLUMN_BROWSABLE = "browsable";
2213 
2214         /**
2215          * The flag indicating whether this TV channel is searchable or not.
2216          *
2217          * <p>The columns of searchable channels can be read by other applications that have proper
2218          * permission. Care must be taken not to open sensitive data.
2219          *
2220          * <p>A value of 1 indicates that the channel is searchable and its columns can be read by
2221          * other applications, a value of 0 indicates that the channel is hidden and its columns can
2222          * be read only by the package that owns the channel and the system. If not specified, this
2223          * value is set to 1 (searchable) by default.
2224          *
2225          * <p>Type: INTEGER (boolean)
2226          */
2227         public static final String COLUMN_SEARCHABLE = "searchable";
2228 
2229         /**
2230          * The flag indicating whether this TV channel is locked or not.
2231          *
2232          * <p>This is primarily used for alternative parental control to prevent unauthorized users
2233          * from watching the current channel regardless of the content rating. A value of 1
2234          * indicates the channel is locked and the user is required to enter passcode to unlock it
2235          * in order to watch the current program from the channel, a value of 0 indicates the
2236          * channel is not locked thus the user is not prompted to enter passcode If not specified,
2237          * this value is set to 0 (not locked) by default.
2238          *
2239          * <p>This column can only be set by applications having proper system permission to
2240          * modify parental control settings. For other applications, this is a read-only column.
2241 
2242          * <p>Type: INTEGER (boolean)
2243          */
2244         public static final String COLUMN_LOCKED = "locked";
2245 
2246         /**
2247          * The URI for the app badge icon of the app link template for this channel.
2248          *
2249          * <p>This small icon is overlaid at the bottom of the poster art specified by
2250          * {@link #COLUMN_APP_LINK_POSTER_ART_URI}. The data in the column must be a URI in one of
2251          * the following formats:
2252          *
2253          * <ul>
2254          * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
2255          * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
2256          * </li>
2257          * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
2258          * </ul>
2259          *
2260          * <p>The app-linking allows channel input sources to provide activity links from their live
2261          * channel programming to another activity. This enables content providers to increase user
2262          * engagement by offering the viewer other content or actions.
2263          *
2264          * <p>Type: TEXT
2265          * @see #COLUMN_APP_LINK_COLOR
2266          * @see #COLUMN_APP_LINK_INTENT_URI
2267          * @see #COLUMN_APP_LINK_POSTER_ART_URI
2268          * @see #COLUMN_APP_LINK_TEXT
2269          */
2270         public static final String COLUMN_APP_LINK_ICON_URI = "app_link_icon_uri";
2271 
2272         /**
2273          * The URI for the poster art used as the background of the app link template for this
2274          * channel.
2275          *
2276          * <p>The data in the column must be a URL, or a URI in one of the following formats:
2277          *
2278          * <ul>
2279          * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
2280          * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
2281          * </li>
2282          * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
2283          * </ul>
2284          *
2285          * <p>The app-linking allows channel input sources to provide activity links from their live
2286          * channel programming to another activity. This enables content providers to increase user
2287          * engagement by offering the viewer other content or actions.
2288          *
2289          * <p>Type: TEXT
2290          * @see #COLUMN_APP_LINK_COLOR
2291          * @see #COLUMN_APP_LINK_ICON_URI
2292          * @see #COLUMN_APP_LINK_INTENT_URI
2293          * @see #COLUMN_APP_LINK_TEXT
2294          */
2295         public static final String COLUMN_APP_LINK_POSTER_ART_URI = "app_link_poster_art_uri";
2296 
2297         /**
2298          * The link text of the app link template for this channel.
2299          *
2300          * <p>This provides a short description of the action that happens when the corresponding
2301          * app link is clicked.
2302          *
2303          * <p>The app-linking allows channel input sources to provide activity links from their live
2304          * channel programming to another activity. This enables content providers to increase user
2305          * engagement by offering the viewer other content or actions.
2306          *
2307          * <p>Type: TEXT
2308          * @see #COLUMN_APP_LINK_COLOR
2309          * @see #COLUMN_APP_LINK_ICON_URI
2310          * @see #COLUMN_APP_LINK_INTENT_URI
2311          * @see #COLUMN_APP_LINK_POSTER_ART_URI
2312          */
2313         public static final String COLUMN_APP_LINK_TEXT = "app_link_text";
2314 
2315         /**
2316          * The accent color of the app link template for this channel. This is primarily used for
2317          * the background color of the text box in the template.
2318          *
2319          * <p>The app-linking allows channel input sources to provide activity links from their live
2320          * channel programming to another activity. This enables content providers to increase user
2321          * engagement by offering the viewer other content or actions.
2322          *
2323          * <p>Type: INTEGER (color value)
2324          * @see #COLUMN_APP_LINK_ICON_URI
2325          * @see #COLUMN_APP_LINK_INTENT_URI
2326          * @see #COLUMN_APP_LINK_POSTER_ART_URI
2327          * @see #COLUMN_APP_LINK_TEXT
2328          */
2329         public static final String COLUMN_APP_LINK_COLOR = "app_link_color";
2330 
2331         /**
2332          * The intent URI of the app link for this channel.
2333          *
2334          * <p>The URI is created using {@link Intent#toUri} with {@link Intent#URI_INTENT_SCHEME}
2335          * and converted back to the original intent with {@link Intent#parseUri}. The intent is
2336          * launched when the user clicks the corresponding app link for the current channel.
2337          *
2338          * <p>The app-linking allows channel input sources to provide activity links from their live
2339          * channel programming to another activity. This enables content providers to increase user
2340          * engagement by offering the viewer other content or actions.
2341          *
2342          * <p>Type: TEXT
2343          * @see #COLUMN_APP_LINK_COLOR
2344          * @see #COLUMN_APP_LINK_ICON_URI
2345          * @see #COLUMN_APP_LINK_POSTER_ART_URI
2346          * @see #COLUMN_APP_LINK_TEXT
2347          */
2348         public static final String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
2349 
2350         /**
2351          * The internal ID used by individual TV input services.
2352          *
2353          * <p>This is internal to the provider that inserted it, and should not be decoded by other
2354          * apps.
2355          *
2356          * <p>Can be empty.
2357          *
2358          * <p>Type: TEXT
2359          */
2360         public static final String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
2361 
2362         /**
2363          * Internal data used by individual TV input services.
2364          *
2365          * <p>This is internal to the provider that inserted it, and should not be decoded by other
2366          * apps.
2367          *
2368          * <p>Type: BLOB
2369          */
2370         public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
2371 
2372         /**
2373          * Internal integer flag used by individual TV input services.
2374          *
2375          * <p>This is internal to the provider that inserted it, and should not be decoded by other
2376          * apps.
2377          *
2378          * <p>Type: INTEGER
2379          */
2380         public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
2381 
2382         /**
2383          * Internal integer flag used by individual TV input services.
2384          *
2385          * <p>This is internal to the provider that inserted it, and should not be decoded by other
2386          * apps.
2387          *
2388          * <p>Type: INTEGER
2389          */
2390         public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
2391 
2392         /**
2393          * Internal integer flag used by individual TV input services.
2394          *
2395          * <p>This is internal to the provider that inserted it, and should not be decoded by other
2396          * apps.
2397          *
2398          * <p>Type: INTEGER
2399          */
2400         public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
2401 
2402         /**
2403          * Internal integer flag used by individual TV input services.
2404          *
2405          * <p>This is internal to the provider that inserted it, and should not be decoded by other
2406          * apps.
2407          *
2408          * <p>Type: INTEGER
2409          */
2410         public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
2411 
2412         /**
2413          * The version number of this row entry used by TV input services.
2414          *
2415          * <p>This is best used by sync adapters to identify the rows to update. The number can be
2416          * defined by individual TV input services. One may assign the same value as
2417          * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are
2418          * coming from a TV broadcast.
2419          *
2420          * <p>Type: INTEGER
2421          */
2422         public static final String COLUMN_VERSION_NUMBER = "version_number";
2423 
2424         /**
2425          * The flag indicating whether this TV channel is transient or not.
2426          *
2427          * <p>A value of 1 indicates that the channel will be automatically removed by the system on
2428          * reboot, and a value of 0 indicates that the channel is persistent across reboot. If not
2429          * specified, this value is set to 0 (not transient) by default.
2430          *
2431          * <p>Type: INTEGER (boolean)
2432          * @see PreviewPrograms#COLUMN_TRANSIENT
2433          * @see WatchNextPrograms#COLUMN_TRANSIENT
2434          */
2435         public static final String COLUMN_TRANSIENT = "transient";
2436 
2437         /**
2438          * The global content ID of this TV channel, as a URI.
2439          *
2440          * <p>A globally unique URI that identifies this TV channel, if applicable. Suitable URIs
2441          * include
2442          * <ul>
2443          * <li>{@code globalServiceId} from ATSC A/331. ex {@code https://doi.org/10.5239/7E4E-B472}
2444          * <li>Other broadcast ID provider. ex {@code http://example.com/tv_channel/1234}
2445          * </ul>
2446          *
2447          * <p>Can be empty.
2448          *
2449          * <p>Type: TEXT
2450          */
2451         public static final String COLUMN_GLOBAL_CONTENT_ID = "global_content_id";
2452 
Channels()2453         private Channels() {}
2454 
2455         /**
2456          * A sub-directory of a single TV channel that represents its primary logo.
2457          *
2458          * <p>To access this directory, append {@link Channels.Logo#CONTENT_DIRECTORY} to the raw
2459          * channel URI.  The resulting URI represents an image file, and should be interacted
2460          * using ContentResolver.openAssetFileDescriptor.
2461          *
2462          * <p>Note that this sub-directory also supports opening the logo as an asset file in write
2463          * mode.  Callers can create or replace the primary logo associated with this channel by
2464          * opening the asset file and writing the full-size photo contents into it. (Make sure there
2465          * is no padding around the logo image.) When the file is closed, the image will be parsed,
2466          * sized down if necessary, and stored.
2467          *
2468          * <p>Usage example:
2469          * <pre>
2470          * public void writeChannelLogo(long channelId, byte[] logo) {
2471          *     Uri channelLogoUri = TvContract.buildChannelLogoUri(channelId);
2472          *     try {
2473          *         AssetFileDescriptor fd =
2474          *             getContentResolver().openAssetFileDescriptor(channelLogoUri, "rw");
2475          *         OutputStream os = fd.createOutputStream();
2476          *         os.write(logo);
2477          *         os.close();
2478          *         fd.close();
2479          *     } catch (IOException e) {
2480          *         // Handle error cases.
2481          *     }
2482          * }
2483          * </pre>
2484          */
2485         public static final class Logo {
2486 
2487             /**
2488              * The directory twig for this sub-table.
2489              */
2490             public static final String CONTENT_DIRECTORY = "logo";
2491 
Logo()2492             private Logo() {}
2493         }
2494     }
2495 
2496     /**
2497      * Column definitions for the TV programs table.
2498      *
2499      * <p>By default, the query results will be sorted by
2500      * {@link Programs#COLUMN_START_TIME_UTC_MILLIS} in ascending order.
2501      */
2502     public static final class Programs implements BaseTvColumns, ProgramColumns {
2503 
2504         /**
2505          * The content:// style URI for this table.
2506          *
2507          * <p>SQL selection is not supported for {@link ContentResolver#query},
2508          * {@link ContentResolver#update} and {@link ContentResolver#delete} operations.
2509          */
2510         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
2511                 + PATH_PROGRAM);
2512 
2513         /** The MIME type of a directory of TV programs. */
2514         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/program";
2515 
2516         /** The MIME type of a single TV program. */
2517         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
2518 
2519         /**
2520          * The ID of the TV channel that provides this TV program.
2521          *
2522          * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
2523          *
2524          * <p>This is a required field.
2525          *
2526          * <p>Type: INTEGER (long)
2527          */
2528         public static final String COLUMN_CHANNEL_ID = "channel_id";
2529 
2530         /**
2531          * The season number of this TV program for episodic TV shows.
2532          *
2533          * <p>Can be empty.
2534          *
2535          * <p>Type: INTEGER
2536          *
2537          * @deprecated Use {@link #COLUMN_SEASON_DISPLAY_NUMBER} instead.
2538          */
2539         @Deprecated
2540         public static final String COLUMN_SEASON_NUMBER = "season_number";
2541 
2542         /**
2543          * The episode number of this TV program for episodic TV shows.
2544          *
2545          * <p>Can be empty.
2546          *
2547          * <p>Type: INTEGER
2548          *
2549          * @deprecated Use {@link #COLUMN_EPISODE_DISPLAY_NUMBER} instead.
2550          */
2551         @Deprecated
2552         public static final String COLUMN_EPISODE_NUMBER = "episode_number";
2553 
2554         /**
2555          * The start time of this TV program, in milliseconds since the epoch.
2556          *
2557          * <p>The value should be equal to or larger than {@link #COLUMN_END_TIME_UTC_MILLIS} of the
2558          * previous program in the same channel. In practice, start time will usually be the end
2559          * time of the previous program.
2560          *
2561          * <p>Can be empty if this program belongs to a {@link Channels#TYPE_PREVIEW} channel.
2562          *
2563          * <p>Type: INTEGER (long)
2564          */
2565         public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
2566 
2567         /**
2568          * The end time of this TV program, in milliseconds since the epoch.
2569          *
2570          * <p>The value should be equal to or less than {@link #COLUMN_START_TIME_UTC_MILLIS} of the
2571          * next program in the same channel. In practice, end time will usually be the start time of
2572          * the next program.
2573          *
2574          * <p>Can be empty if this program belongs to a {@link Channels#TYPE_PREVIEW} channel.
2575          *
2576          * <p>Type: INTEGER (long)
2577          */
2578         public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
2579 
2580         /**
2581          * The comma-separated genre string of this TV program.
2582          *
2583          * <p>Use the same language appeared in the underlying broadcast standard, if applicable.
2584          * (For example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
2585          * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty. Use
2586          * {@link Genres#encode} to create a text that can be stored in this column. Use
2587          * {@link Genres#decode} to get the broadcast genre strings from the text stored in the
2588          * column.
2589          *
2590          * <p>Type: TEXT
2591          * @see Genres#encode
2592          * @see Genres#decode
2593          */
2594         public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";
2595 
2596         /**
2597          * The flag indicating whether recording of this program is prohibited.
2598          *
2599          * <p>A value of 1 indicates that recording of this program is prohibited and application
2600          * will not schedule any recording for this program. A value of 0 indicates that the
2601          * recording is not prohibited. If not specified, this value is set to 0 (not prohibited) by
2602          * default.
2603          *
2604          * <p>Type: INTEGER (boolean)
2605          */
2606         public static final String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
2607 
2608         /**
2609          * The event ID of this TV program.
2610          *
2611          * <p>It is used to identify the current TV program in the same channel, if applicable.
2612          * Use the same coding for {@code event_id} in the underlying broadcast standard if it
2613          * is defined there (e.g. ATSC A/65, ETSI EN 300 468 and ARIB STD-B10).
2614          *
2615          * <p>This is a required field only if the underlying broadcast standard defines the same
2616          * name field. Otherwise, leave empty.
2617          *
2618          * <p>Type: INTEGER
2619          */
2620         public static final String COLUMN_EVENT_ID = "event_id";
2621 
2622         /**
2623          * The global content ID of this TV program, as a URI.
2624          *
2625          * <p>A globally unique ID that identifies this TV program, if applicable. Suitable URIs
2626          * include
2627          * <ul>
2628          * <li>{@code crid://<CRIDauthority>/<data>} from ETSI TS 102 323
2629          * <li>{@code globalContentId} from ATSC A/332
2630          * <li>Other broadcast ID provider. ex {@code http://example.com/tv_program/1234}
2631          * </ul>
2632          *
2633          * <p>Can be empty.
2634          *
2635          * <p>Type: TEXT
2636          */
2637         public static final String COLUMN_GLOBAL_CONTENT_ID = "global_content_id";
2638 
Programs()2639         private Programs() {}
2640 
2641         /** Canonical genres for TV programs. */
2642         public static final class Genres {
2643             /** @hide */
2644             @StringDef({
2645                     FAMILY_KIDS,
2646                     SPORTS,
2647                     SHOPPING,
2648                     MOVIES,
2649                     COMEDY,
2650                     TRAVEL,
2651                     DRAMA,
2652                     EDUCATION,
2653                     ANIMAL_WILDLIFE,
2654                     NEWS,
2655                     GAMING,
2656                     ARTS,
2657                     ENTERTAINMENT,
2658                     LIFE_STYLE,
2659                     MUSIC,
2660                     PREMIER,
2661                     TECH_SCIENCE,
2662             })
2663             @Retention(RetentionPolicy.SOURCE)
2664             public @interface Genre {}
2665 
2666             /** The genre for Family/Kids. */
2667             public static final String FAMILY_KIDS = "FAMILY_KIDS";
2668 
2669             /** The genre for Sports. */
2670             public static final String SPORTS = "SPORTS";
2671 
2672             /** The genre for Shopping. */
2673             public static final String SHOPPING = "SHOPPING";
2674 
2675             /** The genre for Movies. */
2676             public static final String MOVIES = "MOVIES";
2677 
2678             /** The genre for Comedy. */
2679             public static final String COMEDY = "COMEDY";
2680 
2681             /** The genre for Travel. */
2682             public static final String TRAVEL = "TRAVEL";
2683 
2684             /** The genre for Drama. */
2685             public static final String DRAMA = "DRAMA";
2686 
2687             /** The genre for Education. */
2688             public static final String EDUCATION = "EDUCATION";
2689 
2690             /** The genre for Animal/Wildlife. */
2691             public static final String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE";
2692 
2693             /** The genre for News. */
2694             public static final String NEWS = "NEWS";
2695 
2696             /** The genre for Gaming. */
2697             public static final String GAMING = "GAMING";
2698 
2699             /** The genre for Arts. */
2700             public static final String ARTS = "ARTS";
2701 
2702             /** The genre for Entertainment. */
2703             public static final String ENTERTAINMENT = "ENTERTAINMENT";
2704 
2705             /** The genre for Life Style. */
2706             public static final String LIFE_STYLE = "LIFE_STYLE";
2707 
2708             /** The genre for Music. */
2709             public static final String MUSIC = "MUSIC";
2710 
2711             /** The genre for Premier. */
2712             public static final String PREMIER = "PREMIER";
2713 
2714             /** The genre for Tech/Science. */
2715             public static final String TECH_SCIENCE = "TECH_SCIENCE";
2716 
2717             private static final ArraySet<String> CANONICAL_GENRES = new ArraySet<>();
2718             static {
2719                 CANONICAL_GENRES.add(FAMILY_KIDS);
2720                 CANONICAL_GENRES.add(SPORTS);
2721                 CANONICAL_GENRES.add(SHOPPING);
2722                 CANONICAL_GENRES.add(MOVIES);
2723                 CANONICAL_GENRES.add(COMEDY);
2724                 CANONICAL_GENRES.add(TRAVEL);
2725                 CANONICAL_GENRES.add(DRAMA);
2726                 CANONICAL_GENRES.add(EDUCATION);
2727                 CANONICAL_GENRES.add(ANIMAL_WILDLIFE);
2728                 CANONICAL_GENRES.add(NEWS);
2729                 CANONICAL_GENRES.add(GAMING);
2730                 CANONICAL_GENRES.add(ARTS);
2731                 CANONICAL_GENRES.add(ENTERTAINMENT);
2732                 CANONICAL_GENRES.add(LIFE_STYLE);
2733                 CANONICAL_GENRES.add(MUSIC);
2734                 CANONICAL_GENRES.add(PREMIER);
2735                 CANONICAL_GENRES.add(TECH_SCIENCE);
2736             }
2737 
2738             private static final char DOUBLE_QUOTE = '"';
2739             private static final char COMMA = ',';
2740             private static final String DELIMITER = ",";
2741 
2742             private static final String[] EMPTY_STRING_ARRAY = new String[0];
2743 
Genres()2744             private Genres() {}
2745 
2746             /**
2747              * Encodes genre strings to a text that can be put into the database.
2748              *
2749              * @param genres Genre strings.
2750              * @return an encoded genre string that can be inserted into the
2751              *         {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
2752              */
encode(@onNull @enre String... genres)2753             public static String encode(@NonNull @Genre String... genres) {
2754                 if (genres == null) {
2755                     // MNC and before will throw a NPE.
2756                     return null;
2757                 }
2758                 StringBuilder sb = new StringBuilder();
2759                 String separator = "";
2760                 for (String genre : genres) {
2761                     sb.append(separator).append(encodeToCsv(genre));
2762                     separator = DELIMITER;
2763                 }
2764                 return sb.toString();
2765             }
2766 
encodeToCsv(String genre)2767             private static String encodeToCsv(String genre) {
2768                 StringBuilder sb = new StringBuilder();
2769                 int length = genre.length();
2770                 for (int i = 0; i < length; ++i) {
2771                     char c = genre.charAt(i);
2772                     switch (c) {
2773                         case DOUBLE_QUOTE:
2774                             sb.append(DOUBLE_QUOTE);
2775                             break;
2776                         case COMMA:
2777                             sb.append(DOUBLE_QUOTE);
2778                             break;
2779                     }
2780                     sb.append(c);
2781                 }
2782                 return sb.toString();
2783             }
2784 
2785             /**
2786              * Decodes the genre strings from the text stored in the database.
2787              *
2788              * @param genres The encoded genre string retrieved from the
2789              *            {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
2790              * @return genre strings.
2791              */
decode(@onNull String genres)2792             public static @Genre String[] decode(@NonNull String genres) {
2793                 if (TextUtils.isEmpty(genres)) {
2794                     // MNC and before will throw a NPE for {@code null} genres.
2795                     return EMPTY_STRING_ARRAY;
2796                 }
2797                 if (genres.indexOf(COMMA) == -1 && genres.indexOf(DOUBLE_QUOTE) == -1) {
2798                     return new String[] {genres.trim()};
2799                 }
2800                 StringBuilder sb = new StringBuilder();
2801                 List<String> results = new ArrayList<>();
2802                 int length = genres.length();
2803                 boolean escape = false;
2804                 for (int i = 0; i < length; ++i) {
2805                     char c = genres.charAt(i);
2806                     switch (c) {
2807                         case DOUBLE_QUOTE:
2808                             if (!escape) {
2809                                 escape = true;
2810                                 continue;
2811                             }
2812                             break;
2813                         case COMMA:
2814                             if (!escape) {
2815                                 String string = sb.toString().trim();
2816                                 if (string.length() > 0) {
2817                                     results.add(string);
2818                                 }
2819                                 sb = new StringBuilder();
2820                                 continue;
2821                             }
2822                             break;
2823                     }
2824                     sb.append(c);
2825                     escape = false;
2826                 }
2827                 String string = sb.toString().trim();
2828                 if (string.length() > 0) {
2829                     results.add(string);
2830                 }
2831                 return results.toArray(new String[results.size()]);
2832             }
2833 
2834             /**
2835              * Returns whether a given text is a canonical genre defined in {@link Genres}.
2836              *
2837              * @param genre The name of genre to be checked.
2838              * @return {@code true} if the genre is canonical, otherwise {@code false}.
2839              */
isCanonical(String genre)2840             public static boolean isCanonical(String genre) {
2841                 return CANONICAL_GENRES.contains(genre);
2842             }
2843         }
2844     }
2845 
2846     /**
2847      * Column definitions for the recorded TV programs table.
2848      *
2849      * <p>By default, the query results will be sorted by {@link #COLUMN_START_TIME_UTC_MILLIS} in
2850      * ascending order.
2851      */
2852     public static final class RecordedPrograms implements BaseTvColumns, ProgramColumns {
2853 
2854         /**
2855          * The content:// style URI for this table.
2856          *
2857          * <p>SQL selection is not supported for {@link ContentResolver#query},
2858          * {@link ContentResolver#update} and {@link ContentResolver#delete} operations.
2859          */
2860         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
2861                 + PATH_RECORDED_PROGRAM);
2862 
2863         /** The MIME type of a directory of recorded TV programs. */
2864         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
2865 
2866         /** The MIME type of a single recorded TV program. */
2867         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
2868 
2869         /**
2870          * The ID of the TV channel that provides this recorded program.
2871          *
2872          * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
2873          *
2874          * <p>Type: INTEGER (long)
2875          */
2876         public static final String COLUMN_CHANNEL_ID = "channel_id";
2877 
2878         /**
2879          * The ID of the TV input service that is associated with this recorded program.
2880          *
2881          * <p>Use {@link #buildInputId} to build the ID.
2882          *
2883          * <p>This is a required field.
2884          *
2885          * <p>Type: TEXT
2886          */
2887         public static final String COLUMN_INPUT_ID = "input_id";
2888 
2889         /**
2890          * The start time of the original TV program, in milliseconds since the epoch.
2891          *
2892          * <p>Type: INTEGER (long)
2893          * @see Programs#COLUMN_START_TIME_UTC_MILLIS
2894          */
2895         public static final String COLUMN_START_TIME_UTC_MILLIS =
2896                 Programs.COLUMN_START_TIME_UTC_MILLIS;
2897 
2898         /**
2899          * The end time of the original TV program, in milliseconds since the epoch.
2900          *
2901          * <p>Type: INTEGER (long)
2902          * @see Programs#COLUMN_END_TIME_UTC_MILLIS
2903          */
2904         public static final String COLUMN_END_TIME_UTC_MILLIS = Programs.COLUMN_END_TIME_UTC_MILLIS;
2905 
2906         /**
2907          * The comma-separated genre string of this recorded TV program.
2908          *
2909          * <p>Use the same language appeared in the underlying broadcast standard, if applicable.
2910          * (For example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
2911          * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty. Use
2912          * {@link Genres#encode Genres.encode()} to create a text that can be stored in this column.
2913          * Use {@link Genres#decode Genres.decode()} to get the broadcast genre strings from the
2914          * text stored in the column.
2915          *
2916          * <p>Type: TEXT
2917          * @see Programs#COLUMN_BROADCAST_GENRE
2918          */
2919         public static final String COLUMN_BROADCAST_GENRE = Programs.COLUMN_BROADCAST_GENRE;
2920 
2921         /**
2922          * The URI of the recording data for this recorded program.
2923          *
2924          * <p>Together with {@link #COLUMN_RECORDING_DATA_BYTES}, applications can use this
2925          * information to manage recording storage. The URI should indicate a file or directory with
2926          * the scheme {@link android.content.ContentResolver#SCHEME_FILE}.
2927          *
2928          * <p>Type: TEXT
2929          * @see #COLUMN_RECORDING_DATA_BYTES
2930          */
2931         public static final String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
2932 
2933         /**
2934          * The data size (in bytes) for this recorded program.
2935          *
2936          * <p>Together with {@link #COLUMN_RECORDING_DATA_URI}, applications can use this
2937          * information to manage recording storage.
2938          *
2939          * <p>Type: INTEGER (long)
2940          * @see #COLUMN_RECORDING_DATA_URI
2941          */
2942         public static final String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
2943 
2944         /**
2945          * The duration (in milliseconds) of this recorded program.
2946          *
2947          * <p>The actual duration of the recorded program can differ from the one calculated by
2948          * {@link #COLUMN_END_TIME_UTC_MILLIS} - {@link #COLUMN_START_TIME_UTC_MILLIS} as program
2949          * recording can be interrupted in the middle for some reason, resulting in a partially
2950          * recorded program, which is still playable.
2951          *
2952          * <p>Type: INTEGER
2953          */
2954         public static final String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
2955 
2956         /**
2957          * The expiration time for this recorded program, in milliseconds since the epoch.
2958          *
2959          * <p>Recorded TV programs do not expire by default unless explicitly requested by the user
2960          * or the user allows applications to delete them in order to free up disk space for future
2961          * recording. However, some TV content can have expiration date set by the content provider
2962          * when recorded. This field is used to indicate such a restriction.
2963          *
2964          * <p>Can be empty.
2965          *
2966          * <p>Type: INTEGER (long)
2967          */
2968         public static final String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS =
2969                 "recording_expire_time_utc_millis";
2970 
RecordedPrograms()2971         private RecordedPrograms() {}
2972     }
2973 
2974     /**
2975      * Column definitions for the preview TV programs table.
2976      */
2977     public static final class PreviewPrograms implements BaseTvColumns, ProgramColumns,
2978         PreviewProgramColumns {
2979 
2980         /**
2981          * The content:// style URI for this table.
2982          *
2983          * <p>SQL selection is not supported for {@link ContentResolver#query},
2984          * {@link ContentResolver#update} and {@link ContentResolver#delete} operations.
2985          */
2986         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
2987                 + PATH_PREVIEW_PROGRAM);
2988 
2989         /** The MIME type of a directory of preview TV programs. */
2990         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
2991 
2992         /** The MIME type of a single preview TV program. */
2993         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
2994 
2995         /**
2996          * The ID of the TV channel that provides this TV program.
2997          *
2998          * <p>This value cannot be changed once it's set. Trying to modify it will make the update
2999          * fail.
3000          *
3001          * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
3002          *
3003          * <p>This is a required field.
3004          *
3005          * <p>Type: INTEGER (long)
3006          */
3007         public static final String COLUMN_CHANNEL_ID = "channel_id";
3008 
3009         /**
3010          * The weight of the preview program within the channel.
3011          *
3012          * <p>The UI may choose to show this item in a different position in the channel row.
3013          * A larger weight value means the program is more important than other programs having
3014          * smaller weight values. The value is relevant for the preview programs in the same
3015          * channel. This is only relevant to {@link Channels#TYPE_PREVIEW}.
3016          *
3017          * <p>Can be empty.
3018          *
3019          * <p>Type: INTEGER
3020          */
3021         public static final String COLUMN_WEIGHT = "weight";
3022 
PreviewPrograms()3023         private PreviewPrograms() {}
3024     }
3025 
3026     /**
3027      * Column definitions for the "watch next" TV programs table.
3028      */
3029     public static final class WatchNextPrograms implements BaseTvColumns, ProgramColumns,
3030         PreviewProgramColumns {
3031 
3032         /**
3033          * The content:// style URI for this table.
3034          *
3035          * <p>SQL selection is not supported for {@link ContentResolver#query},
3036          * {@link ContentResolver#update} and {@link ContentResolver#delete} operations.
3037          */
3038         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
3039                 + PATH_WATCH_NEXT_PROGRAM);
3040 
3041         /** The MIME type of a directory of "watch next" TV programs. */
3042         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
3043 
3044         /** The MIME type of a single preview TV program. */
3045         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
3046 
3047         /** @hide */
3048         @IntDef({
3049                 WATCH_NEXT_TYPE_CONTINUE,
3050                 WATCH_NEXT_TYPE_NEXT,
3051                 WATCH_NEXT_TYPE_NEW,
3052                 WATCH_NEXT_TYPE_WATCHLIST,
3053         })
3054         @Retention(RetentionPolicy.SOURCE)
3055         public @interface WatchNextType {}
3056 
3057         /**
3058          * The watch next type for CONTINUE. Use this type when the user has already watched more
3059          * than 1 minute of this content.
3060          *
3061          * @see #COLUMN_WATCH_NEXT_TYPE
3062          */
3063         public static final int WATCH_NEXT_TYPE_CONTINUE = 0;
3064 
3065         /**
3066          * The watch next type for NEXT. Use this type when the user has watched one or more
3067          * complete episodes from some episodic content, but there remains more than one episode
3068          * remaining or there is one last episode remaining, but it is not “new” in that it was
3069          * released before the user started watching the show.
3070          *
3071          * @see #COLUMN_WATCH_NEXT_TYPE
3072          */
3073         public static final int WATCH_NEXT_TYPE_NEXT = 1;
3074 
3075         /**
3076          * The watch next type for NEW. Use this type when the user had watched all of the available
3077          * episodes from some episodic content, but a new episode became available since the user
3078          * started watching the first episode and now there is exactly one unwatched episode. This
3079          * could also work for recorded events in a series e.g. soccer matches or football games.
3080          *
3081          * @see #COLUMN_WATCH_NEXT_TYPE
3082          */
3083         public static final int WATCH_NEXT_TYPE_NEW = 2;
3084 
3085         /**
3086          * The watch next type for WATCHLIST. Use this type when the user has elected to explicitly
3087          * add a movie, event or series to a “watchlist” as a manual way of curating what they
3088          * want to watch next.
3089          *
3090          * @see #COLUMN_WATCH_NEXT_TYPE
3091          */
3092         public static final int WATCH_NEXT_TYPE_WATCHLIST = 3;
3093 
3094         /**
3095          * The "watch next" type of this program content.
3096          *
3097          * <p>The value should match one of the followings:
3098          * {@link #WATCH_NEXT_TYPE_CONTINUE},
3099          * {@link #WATCH_NEXT_TYPE_NEXT},
3100          * {@link #WATCH_NEXT_TYPE_NEW}, and
3101          * {@link #WATCH_NEXT_TYPE_WATCHLIST}.
3102          *
3103          * <p>This is a required field.
3104          *
3105          * <p>Type: INTEGER
3106          */
3107         public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
3108 
3109         /**
3110          * The last UTC time that the user engaged in this TV program, in milliseconds since the
3111          * epoch. This is a hint for the application that is used for ordering of "watch next"
3112          * programs.
3113          *
3114          * <p>The meaning of the value varies depending on the {@link #COLUMN_WATCH_NEXT_TYPE}:
3115          * <ul>
3116          *     <li>{@link #WATCH_NEXT_TYPE_CONTINUE}: the date that the user was last watching the
3117          *     content.</li>
3118          *     <li>{@link #WATCH_NEXT_TYPE_NEXT}: the date of the last episode watched.</li>
3119          *     <li>{@link #WATCH_NEXT_TYPE_NEW}: the release date of the new episode.</li>
3120          *     <li>{@link #WATCH_NEXT_TYPE_WATCHLIST}: the date the item was added to the Watchlist.
3121          *     </li>
3122          * </ul>
3123          *
3124          * <p>This is a required field.
3125          *
3126          * <p>Type: INTEGER (long)
3127          */
3128         public static final String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS =
3129                 "last_engagement_time_utc_millis";
3130 
WatchNextPrograms()3131         private WatchNextPrograms() {}
3132     }
3133 
3134     /**
3135      * Column definitions for the TV programs that the user watched. Applications do not have access
3136      * to this table.
3137      *
3138      * <p>By default, the query results will be sorted by
3139      * {@link WatchedPrograms#COLUMN_WATCH_START_TIME_UTC_MILLIS} in descending order.
3140      * @hide
3141      */
3142     @SystemApi
3143     public static final class WatchedPrograms implements BaseTvColumns {
3144 
3145         /** The content:// style URI for this table. */
3146         public static final Uri CONTENT_URI =
3147                 Uri.parse("content://" + AUTHORITY + "/watched_program");
3148 
3149         /** The MIME type of a directory of watched programs. */
3150         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watched_program";
3151 
3152         /** The MIME type of a single item in this table. */
3153         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watched_program";
3154 
3155         /**
3156          * The UTC time that the user started watching this TV program, in milliseconds since the
3157          * epoch.
3158          *
3159          * <p>Type: INTEGER (long)
3160          */
3161         public static final String COLUMN_WATCH_START_TIME_UTC_MILLIS =
3162                 "watch_start_time_utc_millis";
3163 
3164         /**
3165          * The UTC time that the user stopped watching this TV program, in milliseconds since the
3166          * epoch.
3167          *
3168          * <p>Type: INTEGER (long)
3169          */
3170         public static final String COLUMN_WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis";
3171 
3172         /**
3173          * The ID of the TV channel that provides this TV program.
3174          *
3175          * <p>This is a required field.
3176          *
3177          * <p>Type: INTEGER (long)
3178          */
3179         public static final String COLUMN_CHANNEL_ID = "channel_id";
3180 
3181         /**
3182          * The title of this TV program.
3183          *
3184          * <p>Type: TEXT
3185          */
3186         public static final String COLUMN_TITLE = "title";
3187 
3188         /**
3189          * The start time of this TV program, in milliseconds since the epoch.
3190          *
3191          * <p>Type: INTEGER (long)
3192          */
3193         public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
3194 
3195         /**
3196          * The end time of this TV program, in milliseconds since the epoch.
3197          *
3198          * <p>Type: INTEGER (long)
3199          */
3200         public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
3201 
3202         /**
3203          * The description of this TV program.
3204          *
3205          * <p>Type: TEXT
3206          */
3207         public static final String COLUMN_DESCRIPTION = "description";
3208 
3209         /**
3210          * Extra parameters given to {@link TvInputService.Session#tune(Uri, android.os.Bundle)
3211          * TvInputService.Session.tune(Uri, android.os.Bundle)} when tuning to the channel that
3212          * provides this TV program. (Used internally.)
3213          *
3214          * <p>This column contains an encoded string that represents comma-separated key-value pairs of
3215          * the tune parameters. (Ex. "[key1]=[value1], [key2]=[value2]"). '%' is used as an escape
3216          * character for '%', '=', and ','.
3217          *
3218          * <p>Type: TEXT
3219          */
3220         public static final String COLUMN_INTERNAL_TUNE_PARAMS = "tune_params";
3221 
3222         /**
3223          * The session token of this TV program. (Used internally.)
3224          *
3225          * <p>This contains a String representation of {@link IBinder} for
3226          * {@link TvInputService.Session} that provides the current TV program. It is used
3227          * internally to distinguish watched programs entries from different TV input sessions.
3228          *
3229          * <p>Type: TEXT
3230          */
3231         public static final String COLUMN_INTERNAL_SESSION_TOKEN = "session_token";
3232 
WatchedPrograms()3233         private WatchedPrograms() {}
3234     }
3235 }
3236