TvContentRating.java revision e6dca2cfa4eecd3a45792703b722fc3ef86e8744
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.net.Uri; 21import android.text.TextUtils; 22import android.util.Log; 23 24import java.util.Arrays; 25import java.util.Collections; 26import java.util.List; 27 28/** 29 * A class representing a TV content rating. 30 * When a TV input service provides the content rating information of a program into TV provider, 31 * TvContentRating class will be used for generating the value of {@link 32 * TvContract.Programs#COLUMN_CONTENT_RATING}. To create an object of {@link TvContentRating}, use 33 * the {@link #createRating} method with valid arguments. The arguments could be a system defined 34 * strings, or a TV input service defined strings. 35 * TV input service defined strings are in an xml file defined in <code><{@link 36 * android.R.styleable#TvInputService tv-input}></code> with the {@link 37 * android.R.attr#contentRatingSystemXml contentRatingSystemXml} attribute by the TV input service. 38 * 39 * <h3> Content Rating System XML format </h3> 40 * The XML file for publishing content rating system should follow the DTD bellow: 41 * <p><pre class="prettyprint"> 42 * <?xml version="1.0" encoding="UTF-8"?> 43 * <!DOCTYPE rating-systems [ 44 * <!ELEMENT rating-system-definitions (rating-system-definition+)> 45 * <!ELEMENT rating-system-definition ( 46 * (sub-rating-definition*, rating-definition, sub-rating-definition*)+, order*)> 47 * <!ATTLIST rating-system-definition 48 * id ID #REQUIRED 49 * displayName CDATA #IMPLIED 50 * description CDATA #IMPLIED 51 * country CDATA #IMPLIED> 52 * <!ELEMENT sub-rating-definition EMPTY> 53 * <!ATTLIST sub-rating-definition 54 * id ID #REQUIRED 55 * displayName CDATA #IMPLIED 56 * icon CDATA #IMPLIED 57 * description CDATA #IMPLIED> 58 * <!ELEMENT rating-definition (sub-rating*))> 59 * <!ATTLIST rating-definition 60 * id ID #REQUIRED 61 * displayName CDATA #IMPLIED 62 * icon CDATA #IMPLIED 63 * description CDATA #IMPLIED> 64 * <!ELEMENT sub-rating EMPTY> 65 * <!ATTLIST sub-rating id IDREF #REQUIRED> 66 * <!ELEMENT order (rating, rating+)> 67 * <!ELEMENT rating EMPTY> 68 * <!ATTLIST rating id IDREF #REQUIRED> 69 * ]> 70 * </pre></p> 71 * 72 * <h3>System defined rating strings</h3> 73 * 74 * <u>System defined string for {@code domain}</u> 75 * <table border="0" cellspacing="0" cellpadding="0"> 76 * <tr> 77 * <td>String value</td> 78 * <td>Comments</td> 79 * </tr> 80 * <tr> 81 * <td>android.media.tv</td> 82 * <td>Used for creating system defined content ratings</td> 83 * </tr> 84 * </table> 85 * <u>System defined string for {@code ratingSystem}</u> 86 * <table border="0" cellspacing="0" cellpadding="0"> 87 * <tr> 88 * <td>String value</td> 89 * <td>Comments</td> 90 * </tr> 91 * <!--tr> 92 * <td>AM_TV</td> 93 * <td></td> 94 * </tr--> 95 * <!--tr> 96 * <td>AR_TV</td> 97 * <td></td> 98 * </tr--> 99 * <!--tr> 100 * <td>AU_TV</td> 101 * <td></td> 102 * </tr--> 103 * <!--tr> 104 * <td>BG_TV</td> 105 * <td></td> 106 * </tr--> 107 * <!--tr> 108 * <td>BR_TV</td> 109 * <td></td> 110 * </tr--> 111 * <!--tr> 112 * <td>CA_TV</td> 113 * <td></td> 114 * </tr--> 115 * <!--tr> 116 * <td>CH_TV</td> 117 * <td></td> 118 * </tr--> 119 * <!--tr> 120 * <td>CL_TV</td> 121 * <td></td> 122 * </tr--> 123 * <!--tr> 124 * <td>CO_TV</td> 125 * <td></td> 126 * </tr--> 127 * <!--tr> 128 * <td>DE_TV</td> 129 * <td></td> 130 * </tr--> 131 * <!--tr> 132 * <td>DK_TV</td> 133 * <td></td> 134 * </tr--> 135 * <!--tr> 136 * <td>ES_TV</td> 137 * <td></td> 138 * </tr--> 139 * <!--tr> 140 * <td>FI_TV</td> 141 * <td></td> 142 * </tr--> 143 * <!--tr> 144 * <td>FR_TV</td> 145 * <td></td> 146 * </tr--> 147 * <!--tr> 148 * <td>GR_TV</td> 149 * <td></td> 150 * </tr--> 151 * <!--tr> 152 * <td>HK_TV</td> 153 * <td></td> 154 * </tr--> 155 * <!--tr> 156 * <td>HU_TV</td> 157 * <td></td> 158 * </tr--> 159 * <!--tr> 160 * <td>ID_TV</td> 161 * <td></td> 162 * </tr--> 163 * <!--tr> 164 * <td>IE_TV</td> 165 * <td></td> 166 * </tr--> 167 * <!--tr> 168 * <td>IL_TV</td> 169 * <td></td> 170 * </tr--> 171 * <!--tr> 172 * <td>IN_TV</td> 173 * <td></td> 174 * </tr--> 175 * <!--tr> 176 * <td>IS_TV</td> 177 * <td></td> 178 * </tr--> 179 * <!--tr> 180 * <td>IT_TV</td> 181 * <td></td> 182 * </tr--> 183 * <!--tr> 184 * <td>KH_TV</td> 185 * <td></td> 186 * </tr--> 187 * <tr> 188 * <td>KR_TV</td> 189 * <td>The South Korean television rating system</td> 190 * </tr> 191 * <!--tr> 192 * <td>MV_TV</td> 193 * <td></td> 194 * </tr--> 195 * <!--tr> 196 * <td>MX_TV</td> 197 * <td></td> 198 * </tr--> 199 * <!--tr> 200 * <td>MY_TV</td> 201 * <td></td> 202 * </tr--> 203 * <!--tr> 204 * <td>NL_TV</td> 205 * <td></td> 206 * </tr--> 207 * <!--tr> 208 * <td>NZ_TV</td> 209 * <td></td> 210 * </tr--> 211 * <!--tr> 212 * <td>PE_TV</td> 213 * <td></td> 214 * </tr--> 215 * <!--tr> 216 * <td>PH_TV</td> 217 * <td></td> 218 * </tr--> 219 * <!--tr> 220 * <td>PL_TV</td> 221 * <td></td> 222 * </tr--> 223 * <!--tr> 224 * <td>PT_TV</td> 225 * <td></td> 226 * </tr--> 227 * <!--tr> 228 * <td>RO_TV</td> 229 * <td></td> 230 * </tr--> 231 * <!--tr> 232 * <td>RU_TV</td> 233 * <td></td> 234 * </tr--> 235 * <!--tr> 236 * <td>RS_TV</td> 237 * <td></td> 238 * </tr--> 239 * <!--tr> 240 * <td>SG_TV</td> 241 * <td></td> 242 * </tr--> 243 * <!--tr> 244 * <td>SI_TV</td> 245 * <td></td> 246 * </tr--> 247 * <!--tr> 248 * <td>TH_TV</td> 249 * <td></td> 250 * </tr--> 251 * <!--tr> 252 * <td>TR_TV</td> 253 * <td></td> 254 * </tr--> 255 * <!--tr> 256 * <td>TW_TV</td> 257 * <td></td> 258 * </tr--> 259 * <!--tr> 260 * <td>UA_TV</td> 261 * <td></td> 262 * </tr--> 263 * <tr> 264 * <td>US_TVPG</td> 265 * <td>The TV Parental Guidelines for US TV content ratings</td> 266 * </tr> 267 * <!--tr> 268 * <td>VE_TV</td> 269 * <td></td> 270 * </tr--> 271 * <!--tr> 272 * <td>ZA_TV</td> 273 * <td></td> 274 * </tr--> 275 * </table> 276 * 277 * <u>System defined string for {@code rating}</u> 278 * <table border="0" cellspacing="0" cellpadding="0"> 279 * <tr> 280 * <td>String value</td> 281 * <td>Comments</td> 282 * </tr> 283 * <!--tr> 284 * <td>AM_TV_ALL</td> 285 * <td></td> 286 * </tr--> 287 * <!--tr> 288 * <td>AR_TV_ALL</td> 289 * <td></td> 290 * </tr--> 291 * <!--tr> 292 * <td>AU_TV_ALL</td> 293 * <td></td> 294 * </tr--> 295 * <!--tr> 296 * <td>BG_TV_ALL</td> 297 * <td></td> 298 * </tr--> 299 * <!--tr> 300 * <td>BR_TV_ALL</td> 301 * <td></td> 302 * </tr--> 303 * <!--tr> 304 * <td>CA_TV_ALL</td> 305 * <td></td> 306 * </tr--> 307 * <!--tr> 308 * <td>CH_TV_ALL</td> 309 * <td></td> 310 * </tr--> 311 * <!--tr> 312 * <td>CL_TV_ALL</td> 313 * <td></td> 314 * </tr--> 315 * <!--tr> 316 * <td>CO_TV_ALL</td> 317 * <td></td> 318 * </tr--> 319 * <!--tr> 320 * <td>DE_TV_ALL</td> 321 * <td></td> 322 * </tr--> 323 * <!--tr> 324 * <td>DK_TV_ALL</td> 325 * <td></td> 326 * </tr--> 327 * <!--tr> 328 * <td>ES_TV_ALL</td> 329 * <td></td> 330 * </tr--> 331 * <!--tr> 332 * <td>FI_TV_ALL</td> 333 * <td></td> 334 * </tr--> 335 * <!--tr> 336 * <td>FR_TV_ALL</td> 337 * <td></td> 338 * </tr--> 339 * <!--tr> 340 * <td>GR_TV_ALL</td> 341 * <td></td> 342 * </tr--> 343 * <!--tr> 344 * <td>HK_TV_ALL</td> 345 * <td></td> 346 * </tr--> 347 * <!--tr> 348 * <td>HU_TV_ALL</td> 349 * <td></td> 350 * </tr--> 351 * <!--tr> 352 * <td>ID_TV_ALL</td> 353 * <td></td> 354 * </tr--> 355 * <!--tr> 356 * <td>IE_TV_ALL</td> 357 * <td></td> 358 * </tr--> 359 * <!--tr> 360 * <td>IL_TV_ALL</td> 361 * <td></td> 362 * </tr--> 363 * <!--tr> 364 * <td>IN_TV_ALL</td> 365 * <td></td> 366 * </tr--> 367 * <!--tr> 368 * <td>IS_TV_ALL</td> 369 * <td></td> 370 * </tr--> 371 * <!--tr> 372 * <td>IT_TV_ALL</td> 373 * <td></td> 374 * </tr--> 375 * <!--tr> 376 * <td>KH_TV_ALL</td> 377 * <td></td> 378 * </tr--> 379 * <tr> 380 * <td>KR_TV_ALL</td> 381 * <td>A rating string for {@code KR_TV}. This rating is for programs that are appropriate 382 * for all ages. This program usually involves programs designed for children or families. 383 * </td> 384 * </tr> 385 * <tr> 386 * <td>KR_TV_7</td> 387 * <td>A rating string for {@code KR_TV}. This rating is for programs that may contain 388 * material inappropriate for children younger than 7, and parental guidance is required. 389 * </td> 390 * </tr> 391 * <tr> 392 * <td>KR_TV_12</td> 393 * <td>A rating string for {@code KR_TV}. This rating is for programs that may contain 394 * material inappropriate for children younger than 12, and parental guidance is required. 395 * </td> 396 * </tr> 397 * <tr> 398 * <td>KR_TV_15</td> 399 * <td>A rating string for {@code KR_TV}. This rating is for programs that may contain 400 * material inappropriate for children younger than 15, and parental guidance is required. 401 * </tr> 402 * <tr> 403 * <td>KR_TV_19</td> 404 * <td>A rating string for {@code KR_TV}. This rating is for programs designed for adults 405 * only.</td> 406 * </tr> 407 * <!--tr> 408 * <td>MV_TV_ALL</td> 409 * <td></td> 410 * </tr--> 411 * <!--tr> 412 * <td>MX_TV_ALL</td> 413 * <td></td> 414 * </tr--> 415 * <!--tr> 416 * <td>MY_TV_ALL</td> 417 * <td></td> 418 * </tr--> 419 * <!--tr> 420 * <td>NL_TV_ALL</td> 421 * <td></td> 422 * </tr--> 423 * <!--tr> 424 * <td>NZ_TV_ALL</td> 425 * <td></td> 426 * </tr--> 427 * <!--tr> 428 * <td>PE_TV_ALL</td> 429 * <td></td> 430 * </tr--> 431 * <!--tr> 432 * <td>PH_TV_ALL</td> 433 * <td></td> 434 * </tr--> 435 * <!--tr> 436 * <td>PL_TV_ALL</td> 437 * <td></td> 438 * </tr--> 439 * <!--tr> 440 * <td>PT_TV_ALL</td> 441 * <td></td> 442 * </tr--> 443 * <!--tr> 444 * <td>RO_TV_ALL</td> 445 * <td></td> 446 * </tr--> 447 * <!--tr> 448 * <td>RU_TV_ALL</td> 449 * <td></td> 450 * </tr--> 451 * <!--tr> 452 * <td>RS_TV_ALL</td> 453 * <td></td> 454 * </tr--> 455 * <!--tr> 456 * <td>SG_TV_ALL</td> 457 * <td></td> 458 * </tr--> 459 * <!--tr> 460 * <td>SI_TV_ALL</td> 461 * <td></td> 462 * </tr--> 463 * <!--tr> 464 * <td>TH_TV_ALL</td> 465 * <td></td> 466 * </tr--> 467 * <!--tr> 468 * <td>TR_TV_ALL</td> 469 * <td></td> 470 * </tr--> 471 * <!--tr> 472 * <td>TW_TV_ALL</td> 473 * <td></td> 474 * </tr--> 475 * <!--tr> 476 * <td>UA_TV_ALL</td> 477 * <td></td> 478 * </tr--> 479 * <tr> 480 * <td>US_TVPG_TV_Y</td> 481 * <td>A rating string for {@code US_TVPG}. Programs rated this are designed to be 482 * appropriate for all children. Whether animated or live-action, the themes and elements 483 * in this program are specifically designed for a very young audience, including children 484 * from ages 2-6. This program is not expected to frighten younger children.</td> 485 * </tr> 486 * <tr> 487 * <td>US_TVPG_TV_Y7</td> 488 * <td>A rating string for {@code US_TVPG}. Programs rated this are designed for children 489 * age 7 and above. It may be more appropriate for children who have acquired the 490 * developmental skills needed to distinguish between make-believe and reality. Themes and 491 * elements in this program may include mild fantasy violence or comedic violence, or may 492 * frighten children under the age of 7. Therefore, parents may wish to consider the 493 * suitability of this program for their very young children. This rating may contain 494 * fantasy violence (US_TVPG_FV) when programs are generally more intense or more combative 495 * than other programs in this category.</td> 496 * </tr> 497 * <tr> 498 * <td>US_TVPG_TV_G</td> 499 * <td>A rating string for {@code US_TVPG}. Most parents would find this program suitable 500 * for all ages. Although this rating does not signify a program designed specifically for 501 * children, most parents may let younger children watch this program unattended. It 502 * contains little or no violence, no strong language and little or no sexual dialogue or 503 * situations.</td> 504 * </tr> 505 * <tr> 506 * <td>US_TVPG_TV_PG</td> 507 * <td>A rating string for {@code US_TVPG}. Programs rated this contain material that 508 * parents may find unsuitable for younger children. Many parents may want to watch it with 509 * their younger children. The theme itself may call for parental guidance and/or the 510 * program may contain one or more of the following: some suggestive dialogue ( 511 * {@code US_TVPG_D}), infrequent coarse language ({@code US_TVPG_L}), some sexual 512 * situations ({@code US_TVPG_S}), or moderate violence ({@code US_TVPG_V}).</td> 513 * </tr> 514 * <tr> 515 * <td>US_TVPG_TV_14</td> 516 * <td>A rating string for {@code US_TVPG}. Programs rated this contains some material 517 * that many parents would find unsuitable for children under 14 years of age. Parents are 518 * strongly urged to exercise greater care in monitoring this program and are cautioned 519 * against letting children under the age of 14 watch unattended. This program may contain 520 * one or more of the following: intensely suggestive dialogue ({@code US_TVPG_D}), strong 521 * coarse language ({@code US_TVPG_L}), intense sexual situations ({@code US_TVPG_S}), or 522 * intense violence ({@code US_TVPG_V}).</td> 523 * </tr> 524 * <tr> 525 * <td>US_TVPG_TV_MA</td> 526 * <td>A rating string for {@code US_TVPG}. Programs rated TV-MA are specifically 527 * designed to be viewed by adults and therefore may be unsuitable for children under 17. 528 * This program may contain one or more of the following: crude indecent language 529 * ({@code US_TVPG_L}), explicit sexual activity ({@code US_TVPG_S}), or graphic violence 530 * ({@code US_TVPG_V}).</td> 531 * </tr> 532 * <!--tr> 533 * <td>VE_TV_ALL</td> 534 * <td></td> 535 * </tr--> 536 * <!--tr> 537 * <td>ZA_TV_ALL</td> 538 * <td></td> 539 * </tr--> 540 * </table> 541 * 542 * <u>System defined string for {@code subRating}</u> 543 * <table border="0" cellspacing="0" cellpadding="0"> 544 * <tr> 545 * <td>String value</td> 546 * <td>Comments</td> 547 * </tr> 548 * <!--tr> 549 * <td>AM_TV_</td> 550 * <td></td> 551 * </tr--> 552 * <!--tr> 553 * <td>AR_TV_</td> 554 * <td></td> 555 * </tr--> 556 * <!--tr> 557 * <td>AU_TV_</td> 558 * <td></td> 559 * </tr--> 560 * <!--tr> 561 * <td>BG_TV_</td> 562 * <td></td> 563 * </tr--> 564 * <!--tr> 565 * <td>BR_TV_</td> 566 * <td></td> 567 * </tr--> 568 * <!--tr> 569 * <td>CA_TV_</td> 570 * <td></td> 571 * </tr--> 572 * <!--tr> 573 * <td>CH_TV_</td> 574 * <td></td> 575 * </tr--> 576 * <!--tr> 577 * <td>CL_TV_</td> 578 * <td></td> 579 * </tr--> 580 * <!--tr> 581 * <td>CO_TV_</td> 582 * <td></td> 583 * </tr--> 584 * <!--tr> 585 * <td>DE_TV_</td> 586 * <td></td> 587 * </tr--> 588 * <!--tr> 589 * <td>DK_TV_</td> 590 * <td></td> 591 * </tr--> 592 * <!--tr> 593 * <td>ES_TV_</td> 594 * <td></td> 595 * </tr--> 596 * <!--tr> 597 * <td>FI_TV_</td> 598 * <td></td> 599 * </tr--> 600 * <!--tr> 601 * <td>FR_TV_</td> 602 * <td></td> 603 * </tr--> 604 * <!--tr> 605 * <td>GR_TV_</td> 606 * <td></td> 607 * </tr--> 608 * <!--tr> 609 * <td>HK_TV_</td> 610 * <td></td> 611 * </tr--> 612 * <!--tr> 613 * <td>HU_TV_</td> 614 * <td></td> 615 * </tr--> 616 * <!--tr> 617 * <td>ID_TV_</td> 618 * <td></td> 619 * </tr--> 620 * <!--tr> 621 * <td>IE_TV_</td> 622 * <td></td> 623 * </tr--> 624 * <!--tr> 625 * <td>IL_TV_</td> 626 * <td></td> 627 * </tr--> 628 * <!--tr> 629 * <td>IN_TV_</td> 630 * <td></td> 631 * </tr--> 632 * <!--tr> 633 * <td>IS_TV_</td> 634 * <td></td> 635 * </tr--> 636 * <!--tr> 637 * <td>IT_TV_</td> 638 * <td></td> 639 * </tr--> 640 * <!--tr> 641 * <td>KH_TV_</td> 642 * <td></td> 643 * </tr--> 644 * <!--tr> 645 * <td>MV_TV_</td> 646 * <td></td> 647 * </tr--> 648 * <!--tr> 649 * <td>MX_TV_</td> 650 * <td></td> 651 * </tr--> 652 * <!--tr> 653 * <td>MY_TV_</td> 654 * <td></td> 655 * </tr--> 656 * <!--tr> 657 * <td>NL_TV_</td> 658 * <td></td> 659 * </tr--> 660 * <!--tr> 661 * <td>NZ_TV_</td> 662 * <td></td> 663 * </tr--> 664 * <!--tr> 665 * <td>PE_TV_</td> 666 * <td></td> 667 * </tr--> 668 * <!--tr> 669 * <td>PH_TV_</td> 670 * <td></td> 671 * </tr--> 672 * <!--tr> 673 * <td>PL_TV_</td> 674 * <td></td> 675 * </tr--> 676 * <!--tr> 677 * <td>PT_TV_</td> 678 * <td></td> 679 * </tr--> 680 * <!--tr> 681 * <td>RO_TV_</td> 682 * <td></td> 683 * </tr--> 684 * <!--tr> 685 * <td>RU_TV_</td> 686 * <td></td> 687 * </tr--> 688 * <!--tr> 689 * <td>RS_TV_</td> 690 * <td></td> 691 * </tr--> 692 * <!--tr> 693 * <td>SG_TV_</td> 694 * <td></td> 695 * </tr--> 696 * <!--tr> 697 * <td>SI_TV_</td> 698 * <td></td> 699 * </tr--> 700 * <!--tr> 701 * <td>TH_TV_</td> 702 * <td></td> 703 * </tr--> 704 * <!--tr> 705 * <td>TR_TV_</td> 706 * <td></td> 707 * </tr--> 708 * <!--tr> 709 * <td>TW_TV_</td> 710 * <td></td> 711 * </tr--> 712 * <!--tr> 713 * <td>UA_TV_</td> 714 * <td></td> 715 * </tr--> 716 * <tr> 717 * <td>US_TVPG_D</td> 718 * <td>Suggestive dialogue (Not used with US_TVPG_TV_MA)</td> 719 * </tr> 720 * <tr> 721 * <td>US_TVPG_L</td> 722 * <td>Coarse language</td> 723 * </tr> 724 * <tr> 725 * <td>US_TVPG_S</td> 726 * <td>Sexual content</td> 727 * </tr> 728 * <tr> 729 * <td>US_TVPG_V</td> 730 * <td>Violence</td> 731 * </tr> 732 * <tr> 733 * <td>US_TVPG_FV</td> 734 * <td>Fantasy violence (exclusive to US_TVPG_TV_Y7)</td> 735 * </tr> 736 * <!--tr> 737 * <td>VE_TV_</td> 738 * <td></td> 739 * </tr--> 740 * <!--tr> 741 * <td>ZA_TV_</td> 742 * <td></td> 743 * </tr--> 744 * </table> 745 */ 746public final class TvContentRating { 747 private static final String TAG = "TvContentRating"; 748 749 /** @hide */ 750 public static final Uri SYSTEM_CONTENT_RATING_SYSTEM_XML = Uri.parse( 751 "android.resource://system/" + com.android.internal.R.xml.tv_content_rating_systems); 752 753 // TODO: Consider to use other DELIMITER. In some countries such as India may use this delimiter 754 // in the main ratings. 755 private static final String DELIMITER = "/"; 756 757 private final String mDomain; 758 private final String mCountryCode; 759 private final String mRatingSystem; 760 private final String mRating; 761 private final String[] mSubRatings; 762 763 /** 764 * Creates a TvContentRating object. 765 * 766 * @param domain The domain name. 767 * @param countryCode The country code in ISO 3166-2 format or {@code null}. 768 * @param ratingSystem The rating system id. 769 * @param rating The content rating string. 770 * @param subRatings The string array of sub-ratings. 771 * @return A TvContentRating object, or null if creation failed. 772 */ 773 public static TvContentRating createRating(String domain, String countryCode, 774 String ratingSystem, String rating, String... subRatings) { 775 if (TextUtils.isEmpty(domain)) { 776 throw new IllegalArgumentException("domain cannot be empty"); 777 } 778 if (TextUtils.isEmpty(rating)) { 779 throw new IllegalArgumentException("rating cannot be empty"); 780 } 781 return new TvContentRating(domain, countryCode, ratingSystem, rating, subRatings); 782 } 783 784 /** 785 * Recovers a TvContentRating from a String that was previously created with 786 * {@link #flattenToString}. 787 * 788 * @param ratingString The String that was returned by flattenToString(). 789 * @return a new TvContentRating containing the domain, countryCode, rating system, rating and 790 * sub-ratings information was encoded in {@code ratingString}. 791 * @see #flattenToString 792 */ 793 public static TvContentRating unflattenFromString(String ratingString) { 794 if (TextUtils.isEmpty(ratingString)) { 795 throw new IllegalArgumentException("ratingString cannot be empty"); 796 } 797 String[] strs = ratingString.split(DELIMITER); 798 if (strs.length < 4) { 799 throw new IllegalArgumentException("Invalid rating string: " + ratingString); 800 } 801 if (strs.length > 4) { 802 String[] subRatings = new String[strs.length - 4]; 803 System.arraycopy(strs, 4, subRatings, 0, subRatings.length); 804 return new TvContentRating(strs[0], strs[1], strs[2], strs[3], subRatings); 805 } 806 return new TvContentRating(strs[0], strs[1], strs[2], strs[3], null); 807 } 808 809 /** 810 * Constructs a TvContentRating object from a given rating and sub-rating constants. 811 * 812 * @param rating The rating constant defined in this class. 813 * @param subRatings The String array of sub-rating constants defined in this class. 814 */ 815 private TvContentRating(String domain, String countryCode, 816 String ratingSystem, String rating, String[] subRatings) { 817 mDomain = domain; 818 mCountryCode = countryCode; 819 mRatingSystem = ratingSystem; 820 mRating = rating; 821 mSubRatings = subRatings; 822 } 823 824 /** 825 * Returns the domain. 826 */ 827 public String getDomain() { 828 return mDomain; 829 } 830 831 /** 832 * Returns the country code in ISO 3166-2 format or {@code null}. 833 */ 834 public String getCountry() { 835 return mCountryCode; 836 } 837 838 /** 839 * Returns the rating system id. 840 */ 841 public String getRatingSystem() { 842 return mRatingSystem; 843 } 844 845 /** 846 * Returns the main rating. 847 */ 848 public String getMainRating() { 849 return mRating; 850 } 851 852 /** 853 * Returns the unmodifiable {@code List} of sub-rating strings. 854 */ 855 public List<String> getSubRatings() { 856 if (mSubRatings == null) { 857 return null; 858 } 859 return Collections.unmodifiableList(Arrays.asList(mSubRatings)); 860 } 861 862 /** 863 * Returns a String that unambiguously describes both the rating and sub-rating information 864 * contained in the TvContentRating. You can later recover the TvContentRating from this string 865 * through {@link #unflattenFromString}. 866 * 867 * @return a new String holding rating/sub-rating information, which can later be stored in the 868 * database and settings. 869 * @see #unflattenFromString 870 */ 871 public String flattenToString() { 872 StringBuilder builder = new StringBuilder(); 873 builder.append(mDomain); 874 builder.append(DELIMITER); 875 builder.append(mCountryCode); 876 builder.append(DELIMITER); 877 builder.append(mRatingSystem); 878 builder.append(DELIMITER); 879 builder.append(mRating); 880 if (mSubRatings != null) { 881 for (String subRating : mSubRatings) { 882 builder.append(DELIMITER); 883 builder.append(subRating); 884 } 885 } 886 return builder.toString(); 887 } 888 889 /** 890 * Returns true if this rating has the same main rating as the specified rating and when this 891 * rating's sub-ratings contain the other's. 892 * <p> 893 * For example, a TvContentRating object that represents TV-PG with S(Sexual content) and 894 * V(Violence) contains TV-PG, TV-PG/S, TV-PG/V and itself. 895 * </p> 896 * 897 * @param rating The {@link TvContentRating} to check. 898 * @return {@code true} if this object contains {@code rating}, {@code false} otherwise. 899 * @hide 900 */ 901 @SystemApi 902 public final boolean contains(TvContentRating rating) { 903 if (rating == null) { 904 throw new IllegalArgumentException("rating cannot be null"); 905 } 906 if (!rating.getMainRating().equals(mRating)) { 907 return false; 908 } 909 List<String> subRatings = getSubRatings(); 910 List<String> subRatingsOther = rating.getSubRatings(); 911 if (subRatings == null && subRatingsOther == null) { 912 return true; 913 } else if (subRatings == null && subRatingsOther != null) { 914 return false; 915 } else if (subRatings != null && subRatingsOther == null) { 916 return true; 917 } else { 918 return subRatings.containsAll(subRatingsOther); 919 } 920 } 921} 922