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