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