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