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