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