1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media.tv; 18 19 import android.annotation.SystemApi; 20 import android.content.ComponentName; 21 import android.content.ContentResolver; 22 import android.content.ContentUris; 23 import android.net.Uri; 24 import android.os.IBinder; 25 import android.provider.BaseColumns; 26 import android.util.ArraySet; 27 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.Map; 31 32 /** 33 * <p> 34 * The contract between the TV provider and applications. Contains definitions for the supported 35 * URIs and columns. 36 * </p> 37 * <h3>Overview</h3> 38 * <p> 39 * TvContract defines a basic database of TV content metadata such as channel and program 40 * information. The information is stored in {@link Channels} and {@link Programs} tables. 41 * </p> 42 * <ul> 43 * <li>A row in the {@link Channels} table represents information about a TV channel. The data 44 * format can vary greatly from standard to standard or according to service provider, thus 45 * the columns here are mostly comprised of basic entities that are usually seen to users 46 * regardless of standard such as channel number and name.</li> 47 * <li>A row in the {@link Programs} table represents a set of data describing a TV program such 48 * as program title and start time.</li> 49 * </ul> 50 */ 51 public final class TvContract { 52 /** The authority for the TV provider. */ 53 public static final String AUTHORITY = "android.media.tv"; 54 55 private static final String PATH_CHANNEL = "channel"; 56 private static final String PATH_PROGRAM = "program"; 57 private static final String PATH_PASSTHROUGH = "passthrough"; 58 59 /** 60 * An optional query, update or delete URI parameter that allows the caller to specify TV input 61 * ID to filter channels. 62 * @hide 63 */ 64 public static final String PARAM_INPUT = "input"; 65 66 /** 67 * An optional query, update or delete URI parameter that allows the caller to specify channel 68 * ID to filter programs. 69 * @hide 70 */ 71 public static final String PARAM_CHANNEL = "channel"; 72 73 /** 74 * An optional query, update or delete URI parameter that allows the caller to specify start 75 * time (in milliseconds since the epoch) to filter programs. 76 * @hide 77 */ 78 public static final String PARAM_START_TIME = "start_time"; 79 80 /** 81 * An optional query, update or delete URI parameter that allows the caller to specify end time 82 * (in milliseconds since the epoch) to filter programs. 83 * @hide 84 */ 85 public static final String PARAM_END_TIME = "end_time"; 86 87 /** 88 * A query, update or delete URI parameter that allows the caller to operate on all or 89 * browsable-only channels. If set to "true", the rows that contain non-browsable channels are 90 * not affected. 91 * @hide 92 */ 93 public static final String PARAM_BROWSABLE_ONLY = "browsable_only"; 94 95 /** 96 * A optional query, update or delete URI parameter that allows the caller to specify canonical 97 * genre to filter programs. 98 * @hide 99 */ 100 public static final String PARAM_CANONICAL_GENRE = "canonical_genre"; 101 102 /** 103 * Builds an ID that uniquely identifies a TV input service. 104 * 105 * @param name The {@link ComponentName} of the TV input service to build ID for. 106 * @return the ID for the given TV input service. 107 */ 108 public static final String buildInputId(ComponentName name) { 109 return name.flattenToShortString(); 110 } 111 112 /** 113 * Builds a URI that points to a specific channel. 114 * 115 * @param channelId The ID of the channel to point to. 116 */ 117 public static final Uri buildChannelUri(long channelId) { 118 return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId); 119 } 120 121 /** 122 * Build a special channel URI intended to be used with pass-through inputs. (e.g. HDMI) 123 * 124 * @param inputId The ID of the pass-through input to build a channels URI for. 125 * @see TvInputInfo#isPassthroughInput() 126 */ 127 public static final Uri buildChannelUriForPassthroughInput(String inputId) { 128 return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY) 129 .appendPath(PATH_PASSTHROUGH).appendPath(inputId).build(); 130 } 131 132 /** 133 * Builds a URI that points to a channel logo. See {@link Channels.Logo}. 134 * 135 * @param channelId The ID of the channel whose logo is pointed to. 136 */ 137 public static final Uri buildChannelLogoUri(long channelId) { 138 return buildChannelLogoUri(buildChannelUri(channelId)); 139 } 140 141 /** 142 * Builds a URI that points to a channel logo. See {@link Channels.Logo}. 143 * 144 * @param channelUri The URI of the channel whose logo is pointed to. 145 */ 146 public static final Uri buildChannelLogoUri(Uri channelUri) { 147 if (!isChannelUriForTunerInput(channelUri)) { 148 throw new IllegalArgumentException("Not a channel: " + channelUri); 149 } 150 return Uri.withAppendedPath(channelUri, Channels.Logo.CONTENT_DIRECTORY); 151 } 152 153 /** 154 * Builds a URI that points to all channels from a given TV input. 155 * 156 * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a 157 * URI for all the TV inputs. 158 */ 159 public static final Uri buildChannelsUriForInput(String inputId) { 160 return buildChannelsUriForInput(inputId, false); 161 } 162 163 /** 164 * Builds a URI that points to all or browsable-only channels from a given TV input. 165 * 166 * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a 167 * URI for all the TV inputs. 168 * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set 169 * to {@code false} the URI points to all channels regardless of whether they are 170 * browsable or not. 171 * @hide 172 */ 173 @SystemApi 174 public static final Uri buildChannelsUriForInput(String inputId, boolean browsableOnly) { 175 Uri.Builder builder = Channels.CONTENT_URI.buildUpon(); 176 if (inputId != null) { 177 builder.appendQueryParameter(PARAM_INPUT, inputId); 178 } 179 return builder.appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly)) 180 .build(); 181 } 182 183 /** 184 * Builds a URI that points to all or browsable-only channels which have programs with the given 185 * genre from the given TV input. 186 * 187 * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a 188 * URI for all the TV inputs. 189 * @param genre {@link Programs.Genres} to search. If {@code null}, builds a URI for all genres. 190 * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set 191 * to {@code false} the URI points to all channels regardless of whether they are 192 * browsable or not. 193 * @hide 194 */ 195 @SystemApi 196 public static final Uri buildChannelsUriForInput(String inputId, String genre, 197 boolean browsableOnly) { 198 if (genre == null) { 199 return buildChannelsUriForInput(inputId, browsableOnly); 200 } 201 if (!Programs.Genres.isCanonical(genre)) { 202 throw new IllegalArgumentException("Not a canonical genre: '" + genre + "'"); 203 } 204 return buildChannelsUriForInput(inputId, browsableOnly).buildUpon() 205 .appendQueryParameter(PARAM_CANONICAL_GENRE, genre).build(); 206 } 207 208 /** 209 * Builds a URI that points to a specific program. 210 * 211 * @param programId The ID of the program to point to. 212 */ 213 public static final Uri buildProgramUri(long programId) { 214 return ContentUris.withAppendedId(Programs.CONTENT_URI, programId); 215 } 216 217 /** 218 * Builds a URI that points to all programs on a given channel. 219 * 220 * @param channelId The ID of the channel to return programs for. 221 */ 222 public static final Uri buildProgramsUriForChannel(long channelId) { 223 return Programs.CONTENT_URI.buildUpon() 224 .appendQueryParameter(PARAM_CHANNEL, String.valueOf(channelId)).build(); 225 } 226 227 /** 228 * Builds a URI that points to all programs on a given channel. 229 * 230 * @param channelUri The URI of the channel to return programs for. 231 */ 232 public static final Uri buildProgramsUriForChannel(Uri channelUri) { 233 if (!isChannelUriForTunerInput(channelUri)) { 234 throw new IllegalArgumentException("Not a channel: " + channelUri); 235 } 236 return buildProgramsUriForChannel(ContentUris.parseId(channelUri)); 237 } 238 239 /** 240 * Builds a URI that points to programs on a specific channel whose schedules overlap with the 241 * given time frame. 242 * 243 * @param channelId The ID of the channel to return programs for. 244 * @param startTime The start time used to filter programs. The returned programs should have 245 * {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time. 246 * @param endTime The end time used to filter programs. The returned programs should have 247 * {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time. 248 */ 249 public static final Uri buildProgramsUriForChannel(long channelId, long startTime, 250 long endTime) { 251 Uri uri = buildProgramsUriForChannel(channelId); 252 return uri.buildUpon().appendQueryParameter(PARAM_START_TIME, String.valueOf(startTime)) 253 .appendQueryParameter(PARAM_END_TIME, String.valueOf(endTime)).build(); 254 } 255 256 /** 257 * Builds a URI that points to programs on a specific channel whose schedules overlap with the 258 * given time frame. 259 * 260 * @param channelUri The URI of the channel to return programs for. 261 * @param startTime The start time used to filter programs. The returned programs should have 262 * {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time. 263 * @param endTime The end time used to filter programs. The returned programs should have 264 * {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time. 265 */ 266 public static final Uri buildProgramsUriForChannel(Uri channelUri, long startTime, 267 long endTime) { 268 if (!isChannelUriForTunerInput(channelUri)) { 269 throw new IllegalArgumentException("Not a channel: " + channelUri); 270 } 271 return buildProgramsUriForChannel(ContentUris.parseId(channelUri), startTime, endTime); 272 } 273 274 /** 275 * Builds a URI that points to a specific program the user watched. 276 * 277 * @param watchedProgramId The ID of the watched program to point to. 278 * @hide 279 */ 280 public static final Uri buildWatchedProgramUri(long watchedProgramId) { 281 return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId); 282 } 283 284 private static final boolean isTvUri(Uri uri) { 285 return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) 286 && AUTHORITY.equals(uri.getAuthority()); 287 } 288 289 private static final boolean isTwoSegmentUriStartingWith(Uri uri, String pathSegment) { 290 List<String> pathSegments = uri.getPathSegments(); 291 return pathSegments.size() == 2 && pathSegment.equals(pathSegments.get(0)); 292 } 293 294 /** 295 * Returns true, if {@code uri} is a channel URI. 296 * @hide 297 */ 298 public static final boolean isChannelUri(Uri uri) { 299 return isChannelUriForTunerInput(uri) || isChannelUriForPassthroughInput(uri); 300 } 301 302 /** 303 * Returns true, if {@code uri} is a channel URI for a tuner input. 304 * @hide 305 */ 306 public static final boolean isChannelUriForTunerInput(Uri uri) { 307 return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_CHANNEL); 308 } 309 310 /** 311 * Returns true, if {@code uri} is a channel URI for a passthrough input. 312 * @hide 313 */ 314 @SystemApi 315 public static final boolean isChannelUriForPassthroughInput(Uri uri) { 316 return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PASSTHROUGH); 317 } 318 319 /** 320 * Returns true, if {@code uri} is a program URI. 321 * @hide 322 */ 323 public static final boolean isProgramUri(Uri uri) { 324 return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM); 325 } 326 327 328 private TvContract() {} 329 330 /** 331 * Common base for the tables of TV channels/programs. 332 */ 333 public interface BaseTvColumns extends BaseColumns { 334 /** 335 * The name of the package that owns a row in each table. 336 * <p> 337 * The TV provider fills it in with the name of the package that provides the initial data 338 * of that row. If the package is later uninstalled, the rows it owns are automatically 339 * removed from the tables. 340 * </p><p> 341 * Type: TEXT 342 * </p> 343 */ 344 public static final String COLUMN_PACKAGE_NAME = "package_name"; 345 } 346 347 /** Column definitions for the TV channels table. */ 348 public static final class Channels implements BaseTvColumns { 349 350 /** The content:// style URI for this table. */ 351 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" 352 + PATH_CHANNEL); 353 354 /** The MIME type of a directory of TV channels. */ 355 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/channel"; 356 357 /** The MIME type of a single TV channel. */ 358 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel"; 359 360 /** A generic channel type. */ 361 public static final String TYPE_OTHER = "TYPE_OTHER"; 362 363 /** The channel type for NTSC. */ 364 public static final String TYPE_NTSC = "TYPE_NTSC"; 365 366 /** The channel type for PAL. */ 367 public static final String TYPE_PAL = "TYPE_PAL"; 368 369 /** The channel type for SECAM. */ 370 public static final String TYPE_SECAM = "TYPE_SECAM"; 371 372 /** The channel type for DVB-T (terrestrial). */ 373 public static final String TYPE_DVB_T = "TYPE_DVB_T"; 374 375 /** The channel type for DVB-T2 (terrestrial). */ 376 public static final String TYPE_DVB_T2 = "TYPE_DVB_T2"; 377 378 /** The channel type for DVB-S (satellite). */ 379 public static final String TYPE_DVB_S = "TYPE_DVB_S"; 380 381 /** The channel type for DVB-S2 (satellite). */ 382 public static final String TYPE_DVB_S2 = "TYPE_DVB_S2"; 383 384 /** The channel type for DVB-C (cable). */ 385 public static final String TYPE_DVB_C = "TYPE_DVB_C"; 386 387 /** The channel type for DVB-C2 (cable). */ 388 public static final String TYPE_DVB_C2 = "TYPE_DVB_C2"; 389 390 /** The channel type for DVB-H (handheld). */ 391 public static final String TYPE_DVB_H = "TYPE_DVB_H"; 392 393 /** The channel type for DVB-SH (satellite). */ 394 public static final String TYPE_DVB_SH = "TYPE_DVB_SH"; 395 396 /** The channel type for ATSC (terrestrial). */ 397 public static final String TYPE_ATSC_T = "TYPE_ATSC_T"; 398 399 /** The channel type for ATSC (cable). */ 400 public static final String TYPE_ATSC_C = "TYPE_ATSC_C"; 401 402 /** The channel type for ATSC-M/H (mobile/handheld). */ 403 public static final String TYPE_ATSC_M_H = "TYPE_ATSC_M_H"; 404 405 /** The channel type for ISDB-T (terrestrial). */ 406 public static final String TYPE_ISDB_T = "TYPE_ISDB_T"; 407 408 /** The channel type for ISDB-Tb (Brazil). */ 409 public static final String TYPE_ISDB_TB = "TYPE_ISDB_TB"; 410 411 /** The channel type for ISDB-S (satellite). */ 412 public static final String TYPE_ISDB_S = "TYPE_ISDB_S"; 413 414 /** The channel type for ISDB-C (cable). */ 415 public static final String TYPE_ISDB_C = "TYPE_ISDB_C"; 416 417 /** The channel type for 1seg (handheld). */ 418 public static final String TYPE_1SEG = "TYPE_1SEG"; 419 420 /** The channel type for DTMB (terrestrial). */ 421 public static final String TYPE_DTMB = "TYPE_DTMB"; 422 423 /** The channel type for CMMB (handheld). */ 424 public static final String TYPE_CMMB = "TYPE_CMMB"; 425 426 /** The channel type for T-DMB (terrestrial). */ 427 public static final String TYPE_T_DMB = "TYPE_T_DMB"; 428 429 /** The channel type for S-DMB (satellite). */ 430 public static final String TYPE_S_DMB = "TYPE_S_DMB"; 431 432 /** A generic service type. */ 433 public static final String SERVICE_TYPE_OTHER = "SERVICE_TYPE_OTHER"; 434 435 /** The service type for regular TV channels that have both audio and video. */ 436 public static final String SERVICE_TYPE_AUDIO_VIDEO = "SERVICE_TYPE_AUDIO_VIDEO"; 437 438 /** The service type for radio channels that have audio only. */ 439 public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO"; 440 441 /** The video format for 240p. */ 442 public static final String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P"; 443 444 /** The video format for 360p. */ 445 public static final String VIDEO_FORMAT_360P = "VIDEO_FORMAT_360P"; 446 447 /** The video format for 480i. */ 448 public static final String VIDEO_FORMAT_480I = "VIDEO_FORMAT_480I"; 449 450 /** The video format for 480p. */ 451 public static final String VIDEO_FORMAT_480P = "VIDEO_FORMAT_480P"; 452 453 /** The video format for 576i. */ 454 public static final String VIDEO_FORMAT_576I = "VIDEO_FORMAT_576I"; 455 456 /** The video format for 576p. */ 457 public static final String VIDEO_FORMAT_576P = "VIDEO_FORMAT_576P"; 458 459 /** The video format for 720p. */ 460 public static final String VIDEO_FORMAT_720P = "VIDEO_FORMAT_720P"; 461 462 /** The video format for 1080i. */ 463 public static final String VIDEO_FORMAT_1080I = "VIDEO_FORMAT_1080I"; 464 465 /** The video format for 1080p. */ 466 public static final String VIDEO_FORMAT_1080P = "VIDEO_FORMAT_1080P"; 467 468 /** The video format for 2160p. */ 469 public static final String VIDEO_FORMAT_2160P = "VIDEO_FORMAT_2160P"; 470 471 /** The video format for 4320p. */ 472 public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P"; 473 474 /** The video resolution for standard-definition. */ 475 public static final String VIDEO_RESOLUTION_SD = "VIDEO_RESOLUTION_SD"; 476 477 /** The video resolution for enhanced-definition. */ 478 public static final String VIDEO_RESOLUTION_ED = "VIDEO_RESOLUTION_ED"; 479 480 /** The video resolution for high-definition. */ 481 public static final String VIDEO_RESOLUTION_HD = "VIDEO_RESOLUTION_HD"; 482 483 /** The video resolution for full high-definition. */ 484 public static final String VIDEO_RESOLUTION_FHD = "VIDEO_RESOLUTION_FHD"; 485 486 /** The video resolution for ultra high-definition. */ 487 public static final String VIDEO_RESOLUTION_UHD = "VIDEO_RESOLUTION_UHD"; 488 489 private static final Map<String, String> VIDEO_FORMAT_TO_RESOLUTION_MAP = 490 new HashMap<String, String>(); 491 492 static { 493 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480I, VIDEO_RESOLUTION_SD); 494 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480P, VIDEO_RESOLUTION_ED); 495 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576I, VIDEO_RESOLUTION_SD); 496 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576P, VIDEO_RESOLUTION_ED); 497 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_720P, VIDEO_RESOLUTION_HD); 498 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080I, VIDEO_RESOLUTION_HD); 499 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080P, VIDEO_RESOLUTION_FHD); 500 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_2160P, VIDEO_RESOLUTION_UHD); 501 VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_4320P, VIDEO_RESOLUTION_UHD); 502 } 503 504 /** 505 * Returns the video resolution (definition) for a given video format. 506 * 507 * @param videoFormat The video format defined in {@link Channels}. 508 * @return the corresponding video resolution string. {@code null} if the resolution string 509 * is not defined for the given video format. 510 * @see #COLUMN_VIDEO_FORMAT 511 */ 512 public static final String getVideoResolution(String videoFormat) { 513 return VIDEO_FORMAT_TO_RESOLUTION_MAP.get(videoFormat); 514 } 515 516 /** 517 * The ID of the TV input service that provides this TV channel. 518 * <p> 519 * Use {@link #buildInputId} to build the ID. 520 * </p><p> 521 * This is a required field. 522 * </p><p> 523 * Type: TEXT 524 * </p> 525 */ 526 public static final String COLUMN_INPUT_ID = "input_id"; 527 528 /** 529 * The predefined type of this TV channel. 530 * <p> 531 * This is primarily used to indicate which broadcast standard (e.g. ATSC, DVB or ISDB) the 532 * current channel conforms to. The value should match to one of the followings: 533 * {@link #TYPE_OTHER}, {@link #TYPE_DVB_T}, {@link #TYPE_DVB_T2}, {@link #TYPE_DVB_S}, 534 * {@link #TYPE_DVB_S2}, {@link #TYPE_DVB_C}, {@link #TYPE_DVB_C2}, {@link #TYPE_DVB_H}, 535 * {@link #TYPE_DVB_SH}, {@link #TYPE_ATSC_T}, {@link #TYPE_ATSC_C}, 536 * {@link #TYPE_ATSC_M_H}, {@link #TYPE_ISDB_T}, {@link #TYPE_ISDB_TB}, 537 * {@link #TYPE_ISDB_S}, {@link #TYPE_ISDB_C}, {@link #TYPE_1SEG}, {@link #TYPE_DTMB}, 538 * {@link #TYPE_CMMB}, {@link #TYPE_T_DMB}, {@link #TYPE_S_DMB} 539 * </p><p> 540 * This is a required field. 541 * </p><p> 542 * Type: TEXT 543 * </p> 544 */ 545 public static final String COLUMN_TYPE = "type"; 546 547 /** 548 * The predefined service type of this TV channel. 549 * <p> 550 * This is primarily used to indicate whether the current channel is a regular TV channel or 551 * a radio-like channel. Use the same coding for {@code service_type} in the underlying 552 * broadcast standard if it is defined there (e.g. ATSC A/53, ETSI EN 300 468 and ARIB 553 * STD-B10). Otherwise use one of the followings: {@link #SERVICE_TYPE_OTHER}, 554 * {@link #SERVICE_TYPE_AUDIO_VIDEO}, {@link #SERVICE_TYPE_AUDIO} 555 * </p><p> 556 * This is a required field. 557 * </p><p> 558 * Type: TEXT 559 * </p> 560 */ 561 public static final String COLUMN_SERVICE_TYPE = "service_type"; 562 563 /** 564 * The original network ID of this TV channel. 565 * <p> 566 * This is used to identify the originating delivery system, if applicable. Use the same 567 * coding for {@code original_network_id} in the underlying broadcast standard if it is 568 * defined there (e.g. ETSI EN 300 468/TR 101 211 and ARIB STD-B10). If channels cannot be 569 * globally identified by 2-tuple {{@link #COLUMN_TRANSPORT_STREAM_ID}, 570 * {@link #COLUMN_SERVICE_ID}}, one must carefully assign a value to this field to form a 571 * unique 3-tuple identification {{@link #COLUMN_ORIGINAL_NETWORK_ID}, 572 * {@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}} for its channels. 573 * </p><p> 574 * This is a required field if the channel cannot be uniquely identified by a 2-tuple 575 * {{@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}}. 576 * </p><p> 577 * Type: INTEGER 578 * </p> 579 */ 580 public static final String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id"; 581 582 /** 583 * The transport stream ID of this channel. 584 * <p> 585 * This is used to identify the Transport Stream that contains the current channel from any 586 * other multiplex within a network, if applicable. Use the same coding for 587 * {@code transport_stream_id} defined in ISO/IEC 13818-1 if the channel is transmitted via 588 * the MPEG Transport Stream as is the case for many digital broadcast standards. 589 * </p><p> 590 * This is a required field if the current channel is transmitted via the MPEG Transport 591 * Stream. 592 * </p><p> 593 * Type: INTEGER 594 * </p> 595 */ 596 public static final String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id"; 597 598 /** 599 * The service ID of this channel. 600 * <p> 601 * This is used to identify the current service (roughly equivalent to channel) from any 602 * other service within the Transport Stream, if applicable. Use the same coding for 603 * {@code service_id} in the underlying broadcast standard if it is defined there (e.g. ETSI 604 * EN 300 468 and ARIB STD-B10) or {@code program_number} (which usually has the same value 605 * as {@code service_id}) in ISO/IEC 13818-1 if the channel is transmitted via the MPEG 606 * Transport Stream. 607 * </p><p> 608 * This is a required field if the current channel is transmitted via the MPEG Transport 609 * Stream. 610 * </p><p> 611 * Type: INTEGER 612 * </p> 613 */ 614 public static final String COLUMN_SERVICE_ID = "service_id"; 615 616 /** 617 * The channel number that is displayed to the user. 618 * <p> 619 * The format can vary depending on broadcast standard and product specification. 620 * </p><p> 621 * Type: TEXT 622 * </p> 623 */ 624 public static final String COLUMN_DISPLAY_NUMBER = "display_number"; 625 626 /** 627 * The channel name that is displayed to the user. 628 * <p> 629 * A call sign is a good candidate to use for this purpose but any name that helps the user 630 * recognize the current channel will be enough. Can also be empty depending on broadcast 631 * standard. 632 * </p><p> 633 * Type: TEXT 634 * </p> 635 */ 636 public static final String COLUMN_DISPLAY_NAME = "display_name"; 637 638 /** 639 * The network affiliation for this TV channel. 640 * <p> 641 * This is used to identify a channel that is commonly called by its network affiliation 642 * instead of the display name. Examples include ABC for the channel KGO-HD, FOX for the 643 * channel KTVU-HD and NBC for the channel KNTV-HD. Can be empty if not applicable. 644 * </p><p> 645 * Type: TEXT 646 * </p> 647 */ 648 public static final String COLUMN_NETWORK_AFFILIATION = "network_affiliation"; 649 650 /** 651 * The description of this TV channel. 652 * <p> 653 * Can be empty initially. 654 * </p><p> 655 * Type: TEXT 656 * </p> 657 */ 658 public static final String COLUMN_DESCRIPTION = "description"; 659 660 /** 661 * The typical video format for programs from this TV channel. 662 * <p> 663 * This is primarily used to filter out channels based on video format by applications. The 664 * value should match one of the followings: {@link #VIDEO_FORMAT_240P}, 665 * {@link #VIDEO_FORMAT_360P}, {@link #VIDEO_FORMAT_480I}, {@link #VIDEO_FORMAT_480P}, 666 * {@link #VIDEO_FORMAT_576I}, {@link #VIDEO_FORMAT_576P}, {@link #VIDEO_FORMAT_720P}, 667 * {@link #VIDEO_FORMAT_1080I}, {@link #VIDEO_FORMAT_1080P}, {@link #VIDEO_FORMAT_2160P}, 668 * {@link #VIDEO_FORMAT_4320P}. Note that the actual video resolution of each program from a 669 * given channel can vary thus one should use {@link Programs#COLUMN_VIDEO_WIDTH} and 670 * {@link Programs#COLUMN_VIDEO_HEIGHT} to get more accurate video resolution. 671 * </p><p> 672 * Type: TEXT 673 * </p> 674 * @see #getVideoResolution 675 */ 676 public static final String COLUMN_VIDEO_FORMAT = "video_format"; 677 678 /** 679 * The flag indicating whether this TV channel is browsable or not. 680 * <p> 681 * A value of 1 indicates the channel is included in the channel list that applications use 682 * to browse channels, a value of 0 indicates the channel is not included in the list. If 683 * not specified, this value is set to 0 (not browsable) by default. 684 * </p><p> 685 * Type: INTEGER (boolean) 686 * </p> 687 * @hide 688 */ 689 @SystemApi 690 public static final String COLUMN_BROWSABLE = "browsable"; 691 692 /** 693 * The flag indicating whether this TV channel is searchable or not. 694 * <p> 695 * In some regions, it is not allowed to surface search results for a given channel without 696 * broadcaster's consent. This is used to impose such restriction. Channels marked with 697 * "not searchable" cannot be used by other services except for the system service that 698 * shows the TV content. A value of 1 indicates the channel is searchable and can be 699 * included in search results, a value of 0 indicates the channel and its TV programs are 700 * hidden from search. If not specified, this value is set to 1 (searchable) by default. 701 * </p><p> 702 * Type: INTEGER (boolean) 703 * </p> 704 */ 705 public static final String COLUMN_SEARCHABLE = "searchable"; 706 707 /** 708 * The flag indicating whether this TV channel is locked or not. 709 * <p> 710 * This is primarily used for alternative parental control to prevent unauthorized users 711 * from watching the current channel regardless of the content rating. A value of 1 712 * indicates the channel is locked and the user is required to enter passcode to unlock it 713 * in order to watch the current program from the channel, a value of 0 indicates the 714 * channel is not locked thus the user is not prompted to enter passcode If not specified, 715 * this value is set to 0 (not locked) by default. 716 * </p><p> 717 * Type: INTEGER (boolean) 718 * </p> 719 * @hide 720 */ 721 @SystemApi 722 public static final String COLUMN_LOCKED = "locked"; 723 724 /** 725 * Internal data used by individual TV input services. 726 * <p> 727 * This is internal to the provider that inserted it, and should not be decoded by other 728 * apps. 729 * </p><p> 730 * Type: BLOB 731 * </p> 732 */ 733 public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; 734 735 /** 736 * The version number of this row entry used by TV input services. 737 * <p> 738 * This is best used by sync adapters to identify the rows to update. The number can be 739 * defined by individual TV input services. One may assign the same value as 740 * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are 741 * coming from a TV broadcast. 742 * </p><p> 743 * Type: INTEGER 744 * </p> 745 */ 746 public static final String COLUMN_VERSION_NUMBER = "version_number"; 747 748 private Channels() {} 749 750 /** 751 * A sub-directory of a single TV channel that represents its primary logo. 752 * <p> 753 * To access this directory, append {@link Channels.Logo#CONTENT_DIRECTORY} to the raw 754 * channel URI. The resulting URI represents an image file, and should be interacted 755 * using ContentResolver.openAssetFileDescriptor. 756 * </p><p> 757 * Note that this sub-directory also supports opening the logo as an asset file in write 758 * mode. Callers can create or replace the primary logo associated with this channel by 759 * opening the asset file and writing the full-size photo contents into it. When the file 760 * is closed, the image will be parsed, sized down if necessary, and stored. 761 * </p><p> 762 * Usage example: 763 * <pre> 764 * public void writeChannelLogo(long channelId, byte[] logo) { 765 * Uri channelLogoUri = TvContract.buildChannelLogoUri(channelId); 766 * try { 767 * AssetFileDescriptor fd = 768 * getContentResolver().openAssetFileDescriptor(channelLogoUri, "rw"); 769 * OutputStream os = fd.createOutputStream(); 770 * os.write(logo); 771 * os.close(); 772 * fd.close(); 773 * } catch (IOException e) { 774 * // Handle error cases. 775 * } 776 * } 777 * </pre> 778 * </p> 779 */ 780 public static final class Logo { 781 782 /** 783 * The directory twig for this sub-table. 784 */ 785 public static final String CONTENT_DIRECTORY = "logo"; 786 787 private Logo() {} 788 } 789 } 790 791 /** Column definitions for the TV programs table. */ 792 public static final class Programs implements BaseTvColumns { 793 794 /** The content:// style URI for this table. */ 795 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" 796 + PATH_PROGRAM); 797 798 /** The MIME type of a directory of TV programs. */ 799 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/program"; 800 801 /** The MIME type of a single TV program. */ 802 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program"; 803 804 /** 805 * The ID of the TV channel that provides this TV program. 806 * <p> 807 * This is a part of the channel URI and matches to {@link BaseColumns#_ID}. 808 * </p><p> 809 * Type: INTEGER (long) 810 * </p> 811 */ 812 public static final String COLUMN_CHANNEL_ID = "channel_id"; 813 814 /** 815 * The title of this TV program. 816 * <p> 817 * If this program is an episodic TV show, it is recommended that the title is the series 818 * title and its related fields ({@link #COLUMN_SEASON_NUMBER}, 819 * {@link #COLUMN_EPISODE_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in. 820 * </p><p> 821 * Type: TEXT 822 * </p> 823 **/ 824 public static final String COLUMN_TITLE = "title"; 825 826 /** 827 * The season number of this TV program for episodic TV shows. 828 * <p> 829 * Can be empty. 830 * </p><p> 831 * Type: INTEGER 832 * </p> 833 **/ 834 public static final String COLUMN_SEASON_NUMBER = "season_number"; 835 836 /** 837 * The episode number of this TV program for episodic TV shows. 838 * <p> 839 * Can be empty. 840 * </p><p> 841 * Type: INTEGER 842 * </p> 843 **/ 844 public static final String COLUMN_EPISODE_NUMBER = "episode_number"; 845 846 /** 847 * The episode title of this TV program for episodic TV shows. 848 * <p> 849 * Can be empty. 850 * </p><p> 851 * Type: TEXT 852 * </p> 853 **/ 854 public static final String COLUMN_EPISODE_TITLE = "episode_title"; 855 856 /** 857 * The start time of this TV program, in milliseconds since the epoch. 858 * <p> 859 * The value should be equal to or larger than {@link #COLUMN_END_TIME_UTC_MILLIS} of the 860 * previous program in the same channel. 861 * </p><p> 862 * Type: INTEGER (long) 863 * </p> 864 */ 865 public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; 866 867 /** 868 * The end time of this TV program, in milliseconds since the epoch. 869 * <p> 870 * The value should be equal to or less than {@link #COLUMN_START_TIME_UTC_MILLIS} of the 871 * next program in the same channel. 872 * </p><p> 873 * Type: INTEGER (long) 874 * </p> 875 */ 876 public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; 877 878 /** 879 * The comma-separated genre string of this TV program. 880 * <p> 881 * Use the same language appeared in the underlying broadcast standard, if applicable. (For 882 * example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or 883 * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty. 884 * </p><p> 885 * Type: TEXT 886 * </p> 887 */ 888 public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre"; 889 890 /** 891 * The comma-separated canonical genre string of this TV program. 892 * <p> 893 * Canonical genres are defined in {@link Genres}. Use {@link Genres#encode Genres.encode()} 894 * to create a text that can be stored in this column. Use {@link Genres#decode 895 * Genres.decode()} to get the canonical genre strings from the text stored in this column. 896 * </p><p> 897 * Type: TEXT 898 * </p> 899 * @see Genres 900 */ 901 public static final String COLUMN_CANONICAL_GENRE = "canonical_genre"; 902 903 /** 904 * The short description of this TV program that is displayed to the user by default. 905 * <p> 906 * It is recommended to limit the length of the descriptions to 256 characters. 907 * </p><p> 908 * Type: TEXT 909 * </p> 910 */ 911 public static final String COLUMN_SHORT_DESCRIPTION = "short_description"; 912 913 /** 914 * The detailed, lengthy description of this TV program that is displayed only when the user 915 * wants to see more information. 916 * <p> 917 * TV input services should leave this field empty if they have no additional details beyond 918 * {@link #COLUMN_SHORT_DESCRIPTION}. 919 * </p><p> 920 * Type: TEXT 921 * </p> 922 */ 923 public static final String COLUMN_LONG_DESCRIPTION = "long_description"; 924 925 /** 926 * The width of the video for this TV program, in the unit of pixels. 927 * <p> 928 * Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video resolution 929 * of the current TV program. Can be empty if it is not known initially or the program does 930 * not convey any video such as the programs from type {@link Channels#SERVICE_TYPE_AUDIO} 931 * channels. 932 * </p><p> 933 * Type: INTEGER 934 * </p> 935 */ 936 public static final String COLUMN_VIDEO_WIDTH = "video_width"; 937 938 /** 939 * The height of the video for this TV program, in the unit of pixels. 940 * <p> 941 * Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video resolution 942 * of the current TV program. Can be empty if it is not known initially or the program does 943 * not convey any video such as the programs from type {@link Channels#SERVICE_TYPE_AUDIO} 944 * channels. 945 * </p><p> 946 * Type: INTEGER 947 * </p> 948 */ 949 public static final String COLUMN_VIDEO_HEIGHT = "video_height"; 950 951 /** 952 * The comma-separated audio languages of this TV program. 953 * <p> 954 * This is used to describe available audio languages included in the program. Use either 955 * ISO 639-1 or 639-2/T codes. 956 * </p><p> 957 * Type: TEXT 958 * </p> 959 */ 960 public static final String COLUMN_AUDIO_LANGUAGE = "audio_language"; 961 962 /** 963 * The comma-separated content ratings of this TV program. 964 * <p> 965 * This is used to describe the content rating(s) of this program. Each comma-separated 966 * content rating sub-string should be generated by calling 967 * {@link TvContentRating#flattenToString}. Note that in most cases the program content is 968 * rated by a single rating system, thus resulting in a corresponding single sub-string that 969 * does not require comma separation and multiple sub-strings appear only when the program 970 * content is rated by two or more content rating systems. If any of those ratings is 971 * specified as "blocked rating" in the user's parental control settings, the TV input 972 * service should block the current content and wait for the signal that it is okay to 973 * unblock. 974 * </p><p> 975 * Type: TEXT 976 * </p> 977 */ 978 public static final String COLUMN_CONTENT_RATING = "content_rating"; 979 980 /** 981 * The URI for the poster art of this TV program. 982 * <p> 983 * Can be empty. 984 * </p><p> 985 * Type: TEXT 986 * </p> 987 */ 988 public static final String COLUMN_POSTER_ART_URI = "poster_art_uri"; 989 990 /** 991 * The URI for the thumbnail of this TV program. 992 * <p> 993 * Can be empty. 994 * </p><p> 995 * Type: TEXT 996 * </p> 997 */ 998 public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; 999 1000 /** 1001 * Internal data used by individual TV input services. 1002 * <p> 1003 * This is internal to the provider that inserted it, and should not be decoded by other 1004 * apps. 1005 * </p><p> 1006 * Type: BLOB 1007 * </p> 1008 */ 1009 public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; 1010 1011 /** 1012 * The version number of this row entry used by TV input services. 1013 * <p> 1014 * This is best used by sync adapters to identify the rows to update. The number can be 1015 * defined by individual TV input services. One may assign the same value as 1016 * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV 1017 * broadcast. 1018 * </p><p> 1019 * Type: INTEGER 1020 * </p> 1021 */ 1022 public static final String COLUMN_VERSION_NUMBER = "version_number"; 1023 1024 private Programs() {} 1025 1026 /** Canonical genres for TV programs. */ 1027 public static final class Genres { 1028 /** The genre for Family/Kids. */ 1029 public static final String FAMILY_KIDS = "FAMILY_KIDS"; 1030 1031 /** The genre for Sports. */ 1032 public static final String SPORTS = "SPORTS"; 1033 1034 /** The genre for Shopping. */ 1035 public static final String SHOPPING = "SHOPPING"; 1036 1037 /** The genre for Movies. */ 1038 public static final String MOVIES = "MOVIES"; 1039 1040 /** The genre for Comedy. */ 1041 public static final String COMEDY = "COMEDY"; 1042 1043 /** The genre for Travel. */ 1044 public static final String TRAVEL = "TRAVEL"; 1045 1046 /** The genre for Drama. */ 1047 public static final String DRAMA = "DRAMA"; 1048 1049 /** The genre for Education. */ 1050 public static final String EDUCATION = "EDUCATION"; 1051 1052 /** The genre for Animal/Wildlife. */ 1053 public static final String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE"; 1054 1055 /** The genre for News. */ 1056 public static final String NEWS = "NEWS"; 1057 1058 /** The genre for Gaming. */ 1059 public static final String GAMING = "GAMING"; 1060 1061 /** The genre for Arts. */ 1062 public static final String ARTS = "ARTS"; 1063 1064 /** The genre for Entertainment. */ 1065 public static final String ENTERTAINMENT = "ENTERTAINMENT"; 1066 1067 /** The genre for Life Style. */ 1068 public static final String LIFE_STYLE = "LIFE_STYLE"; 1069 1070 /** The genre for Music. */ 1071 public static final String MUSIC = "MUSIC"; 1072 1073 /** The genre for Premier. */ 1074 public static final String PREMIER = "PREMIER"; 1075 1076 /** The genre for Tech/Science. */ 1077 public static final String TECH_SCIENCE = "TECH_SCIENCE"; 1078 1079 private static final ArraySet<String> CANONICAL_GENRES = new ArraySet<String>(); 1080 static { 1081 CANONICAL_GENRES.add(FAMILY_KIDS); 1082 CANONICAL_GENRES.add(SPORTS); 1083 CANONICAL_GENRES.add(SHOPPING); 1084 CANONICAL_GENRES.add(MOVIES); 1085 CANONICAL_GENRES.add(COMEDY); 1086 CANONICAL_GENRES.add(TRAVEL); 1087 CANONICAL_GENRES.add(DRAMA); 1088 CANONICAL_GENRES.add(EDUCATION); 1089 CANONICAL_GENRES.add(ANIMAL_WILDLIFE); 1090 CANONICAL_GENRES.add(NEWS); 1091 CANONICAL_GENRES.add(GAMING); 1092 CANONICAL_GENRES.add(ARTS); 1093 CANONICAL_GENRES.add(ENTERTAINMENT); 1094 CANONICAL_GENRES.add(LIFE_STYLE); 1095 CANONICAL_GENRES.add(MUSIC); 1096 CANONICAL_GENRES.add(PREMIER); 1097 CANONICAL_GENRES.add(TECH_SCIENCE); 1098 } 1099 1100 private Genres() {} 1101 1102 /** 1103 * Encodes canonical genre strings to a text that can be put into the database. 1104 * 1105 * @param genres Canonical genre strings. Use the strings defined in this class. 1106 * @return an encoded genre string that can be inserted into the 1107 * {@link #COLUMN_CANONICAL_GENRE} column. 1108 */ 1109 public static String encode(String... genres) { 1110 StringBuilder sb = new StringBuilder(); 1111 String separator = ""; 1112 for (String genre : genres) { 1113 sb.append(separator).append(genre); 1114 separator = ","; 1115 } 1116 return sb.toString(); 1117 } 1118 1119 /** 1120 * Decodes the canonical genre strings from the text stored in the database. 1121 * 1122 * @param genres The encoded genre string retrieved from the 1123 * {@link #COLUMN_CANONICAL_GENRE} column. 1124 * @return canonical genre strings. 1125 */ 1126 public static String[] decode(String genres) { 1127 return genres.split("\\s*,\\s*"); 1128 } 1129 1130 /** 1131 * Check whether a given genre is canonical or not. 1132 * 1133 * @param genre The name of genre to be checked. 1134 * @return {@code true} if the genre is canonical, otherwise {@code false}. 1135 * @hide 1136 */ 1137 @SystemApi 1138 public static boolean isCanonical(String genre) { 1139 return CANONICAL_GENRES.contains(genre); 1140 } 1141 } 1142 } 1143 1144 /** 1145 * Column definitions for the TV programs that the user watched. Applications do not have access 1146 * to this table. 1147 * @hide 1148 */ 1149 @SystemApi 1150 public static final class WatchedPrograms implements BaseTvColumns { 1151 1152 /** The content:// style URI for this table. */ 1153 public static final Uri CONTENT_URI = 1154 Uri.parse("content://" + AUTHORITY + "/watched_program"); 1155 1156 /** The MIME type of a directory of watched programs. */ 1157 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watched_program"; 1158 1159 /** The MIME type of a single item in this table. */ 1160 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watched_program"; 1161 1162 /** 1163 * The UTC time that the user started watching this TV program, in milliseconds since the 1164 * epoch. 1165 * <p> 1166 * Type: INTEGER (long) 1167 * </p> 1168 */ 1169 public static final String COLUMN_WATCH_START_TIME_UTC_MILLIS = 1170 "watch_start_time_utc_millis"; 1171 1172 /** 1173 * The UTC time that the user stopped watching this TV program, in milliseconds since the 1174 * epoch. 1175 * <p> 1176 * Type: INTEGER (long) 1177 * </p> 1178 */ 1179 public static final String COLUMN_WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis"; 1180 1181 /** 1182 * The ID of the TV channel that provides this TV program. 1183 * <p> 1184 * Type: INTEGER (long) 1185 * </p> 1186 */ 1187 public static final String COLUMN_CHANNEL_ID = "channel_id"; 1188 1189 /** 1190 * The title of this TV program. 1191 * <p> 1192 * Type: TEXT 1193 * </p> 1194 */ 1195 public static final String COLUMN_TITLE = "title"; 1196 1197 /** 1198 * The start time of this TV program, in milliseconds since the epoch. 1199 * <p> 1200 * Type: INTEGER (long) 1201 * </p> 1202 */ 1203 public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; 1204 1205 /** 1206 * The end time of this TV program, in milliseconds since the epoch. 1207 * <p> 1208 * Type: INTEGER (long) 1209 * </p> 1210 */ 1211 public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; 1212 1213 /** 1214 * The description of this TV program. 1215 * <p> 1216 * Type: TEXT 1217 * </p> 1218 */ 1219 public static final String COLUMN_DESCRIPTION = "description"; 1220 1221 /** 1222 * Extra parameters given to {@link TvInputService.Session#tune(Uri, android.os.Bundle) 1223 * TvInputService.Session.tune(Uri, android.os.Bundle)} when tuning to the channel that 1224 * provides this TV program. (Used internally.) 1225 * <p> 1226 * This column contains an encoded string that represents comma-separated key-value pairs of 1227 * the tune parameters. (Ex. "[key1]=[value1], [key2]=[value2]"). '%' is used as an escape 1228 * character for '%', '=', and ','. 1229 * </p><p> 1230 * Type: TEXT 1231 * </p> 1232 */ 1233 public static final String COLUMN_INTERNAL_TUNE_PARAMS = "tune_params"; 1234 1235 /** 1236 * The session token of this TV program. (Used internally.) 1237 * <p> 1238 * This contains a String representation of {@link IBinder} for 1239 * {@link TvInputService.Session} that provides the current TV program. It is used 1240 * internally to distinguish watched programs entries from different TV input sessions. 1241 * </p><p> 1242 * Type: TEXT 1243 * </p> 1244 */ 1245 public static final String COLUMN_INTERNAL_SESSION_TOKEN = "session_token"; 1246 1247 private WatchedPrograms() {} 1248 } 1249 } 1250