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