1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media.tv; 18 19 import android.annotation.NonNull; 20 import android.text.TextUtils; 21 22 import com.android.internal.util.Preconditions; 23 24 import java.util.Arrays; 25 import java.util.Collections; 26 import java.util.List; 27 import java.util.Objects; 28 29 /** 30 * A class representing a TV content rating. When a TV input service inserts the content rating 31 * information on a program into the database, this class can be used to generate the formatted 32 * string for 33 * {@link TvContract.Programs#COLUMN_CONTENT_RATING TvContract.Programs.COLUMN_CONTENT_RATING}. 34 * To create a {@code TvContentRating} object, use the 35 * {@link #createRating TvContentRating.createRating} method with valid rating system string 36 * constants. 37 * 38 * <p>It is possible for an application to define its own content rating system by supplying a 39 * content rating system definition XML resource (see example below) and declaring a broadcast 40 * receiver that filters {@link TvInputManager#ACTION_QUERY_CONTENT_RATING_SYSTEMS} in its manifest. 41 * 42 * <h3> Example: Rating system definition for the TV Parental Guidelines</h3> 43 * The following XML example shows how the TV Parental Guidelines in the United States can be 44 * defined: 45 * <p><pre class="prettyprint"> 46 * {@literal 47 * <rating-system-definitions xmlns:android="http://schemas.android.com/apk/res/android" 48 * android:versionCode="1"> 49 * <rating-system-definition android:name="US_TV" 50 * android:country="US" 51 * android:description="@string/description_us_tv"> 52 * <sub-rating-definition android:name="US_TV_D" 53 * android:title="D" 54 * android:description="@string/description_us_tv_d" /> 55 * <sub-rating-definition android:name="US_TV_L" 56 * android:title="L" 57 * android:description="@string/description_us_tv_l" /> 58 * <sub-rating-definition android:name="US_TV_S" 59 * android:title="S" 60 * android:description="@string/description_us_tv_s" /> 61 * <sub-rating-definition android:name="US_TV_V" 62 * android:title="V" 63 * android:description="@string/description_us_tv_v" /> 64 * <sub-rating-definition android:name="US_TV_FV" 65 * android:title="FV" 66 * android:description="@string/description_us_tv_fv" /> 67 * 68 * <rating-definition android:name="US_TV_Y" 69 * android:title="TV-Y" 70 * android:description="@string/description_us_tv_y" 71 * android:icon="@drawable/icon_us_tv_y" 72 * android:contentAgeHint="0" /> 73 * <rating-definition android:name="US_TV_Y7" 74 * android:title="TV-Y7" 75 * android:description="@string/description_us_tv_y7" 76 * android:icon="@drawable/icon_us_tv_y7" 77 * android:contentAgeHint="7"> 78 * <sub-rating android:name="US_TV_FV" /> 79 * </rating-definition> 80 * <rating-definition android:name="US_TV_G" 81 * android:title="TV-G" 82 * android:description="@string/description_us_tv_g" 83 * android:icon="@drawable/icon_us_tv_g" 84 * android:contentAgeHint="0" /> 85 * <rating-definition android:name="US_TV_PG" 86 * android:title="TV-PG" 87 * android:description="@string/description_us_tv_pg" 88 * android:icon="@drawable/icon_us_tv_pg" 89 * android:contentAgeHint="14"> 90 * <sub-rating android:name="US_TV_D" /> 91 * <sub-rating android:name="US_TV_L" /> 92 * <sub-rating android:name="US_TV_S" /> 93 * <sub-rating android:name="US_TV_V" /> 94 * </rating-definition> 95 * <rating-definition android:name="US_TV_14" 96 * android:title="TV-14" 97 * android:description="@string/description_us_tv_14" 98 * android:icon="@drawable/icon_us_tv_14" 99 * android:contentAgeHint="14"> 100 * <sub-rating android:name="US_TV_D" /> 101 * <sub-rating android:name="US_TV_L" /> 102 * <sub-rating android:name="US_TV_S" /> 103 * <sub-rating android:name="US_TV_V" /> 104 * </rating-definition> 105 * <rating-definition android:name="US_TV_MA" 106 * android:title="TV-MA" 107 * android:description="@string/description_us_tv_ma" 108 * android:icon="@drawable/icon_us_tv_ma" 109 * android:contentAgeHint="17"> 110 * <sub-rating android:name="US_TV_L" /> 111 * <sub-rating android:name="US_TV_S" /> 112 * <sub-rating android:name="US_TV_V" /> 113 * </rating-definition> 114 * <rating-order> 115 * <rating android:name="US_TV_Y" /> 116 * <rating android:name="US_TV_Y7" /> 117 * </rating-order> 118 * <rating-order> 119 * <rating android:name="US_TV_G" /> 120 * <rating android:name="US_TV_PG" /> 121 * <rating android:name="US_TV_14" /> 122 * <rating android:name="US_TV_MA" /> 123 * </rating-order> 124 * </rating-system-definition> 125 * </rating-system-definitions>}</pre> 126 * 127 * <h3>System defined rating strings</h3> 128 * The following strings are defined by the system to provide a standard way to create 129 * {@code TvContentRating} objects. 130 * 131 * <p>For example, to create an object that represents TV-PG rating with suggestive dialogue and 132 * coarse language from the TV Parental Guidelines in the United States, one can use the following 133 * code snippet: 134 * 135 * <pre> 136 * TvContentRating rating = TvContentRating.createRating( 137 * "com.android.tv", 138 * "US_TV", 139 * "US_TV_PG", 140 * "US_TV_D", "US_TV_L"); 141 * </pre> 142 * <h4>System defined string for domains</h4> 143 * <table> 144 * <tr> 145 * <th>Constant Value</th> 146 * <th>Description</th> 147 * </tr> 148 * <tr> 149 * <td>com.android.tv</td> 150 * <td>Used for creating system defined content ratings</td> 151 * </tr> 152 * </table> 153 * 154 * <h4>System defined strings for rating systems</h4> 155 * <table> 156 * <tr> 157 * <th>Constant Value</th> 158 * <th>Description</th> 159 * </tr> 160 * <tr> 161 * <td>AR_TV</td> 162 * <td>TV content rating system for Argentina</td> 163 * </tr> 164 * <tr> 165 * <td>AU_TV</td> 166 * <td>TV content rating system for Australia</td> 167 * </tr> 168 * <tr> 169 * <td>BR_TV</td> 170 * <td>TV content rating system for Brazil</td> 171 * </tr> 172 * <tr> 173 * <td>CA_TV_EN</td> 174 * <td>TV content rating system for Canada (English)</td> 175 * </tr> 176 * <tr> 177 * <td>CA_TV_FR</td> 178 * <td>TV content rating system for Canada (French)</td> 179 * </tr> 180 * <tr> 181 * <td>DTMB</td> 182 * <td>DTMB content rating system</td> 183 * </tr> 184 * <tr> 185 * <td>DVB</td> 186 * <td>DVB content rating system</td> 187 * </tr> 188 * <tr> 189 * <td>ES_DVB</td> 190 * <td>DVB content rating system for Spain</td> 191 * </tr> 192 * <tr> 193 * <td>FR_DVB</td> 194 * <td>DVB content rating system for France</td> 195 * </tr> 196 * <tr> 197 * <td>ISDB</td> 198 * <td>ISDB content rating system</td> 199 * </tr> 200 * <tr> 201 * <td>KR_TV</td> 202 * <td>TV content rating system for South Korea</td> 203 * </tr> 204 * <tr> 205 * <td>NZ_TV</td> 206 * <td>TV content rating system for New Zealand</td> 207 * </tr> 208 * <tr> 209 * <td>SG_TV</td> 210 * <td>TV content rating system for Singapore</td> 211 * </tr> 212 * <tr> 213 * <td>TH_TV</td> 214 * <td>TV content rating system for Thailand</td> 215 * </tr> 216 * <tr> 217 * <td>US_MV</td> 218 * <td>Movie content rating system for the United States</td> 219 * </tr> 220 * <tr> 221 * <td>US_TV</td> 222 * <td>TV content rating system for the United States</td> 223 * </tr> 224 * </table> 225 * 226 * <h4>System defined strings for ratings</h4> 227 * <table> 228 * <tr> 229 * <th>Rating System</th> 230 * <th>Constant Value</th> 231 * <th>Description</th> 232 * </tr> 233 * <tr> 234 * <td valign="top" rowspan="4">AR_TV</td> 235 * <td>AR_TV_ATP</td> 236 * <td>Suitable for all audiences. Programs may contain mild violence, language and mature 237 * situations</td> 238 * </tr> 239 * <tr> 240 * <td>AR_TV_SAM_13</td> 241 * <td>Suitable for ages 13 and up. Programs may contain mild to moderate language and mild 242 * violence and sexual references</td> 243 * </tr> 244 * <tr> 245 * <td>AR_TV_SAM_16</td> 246 * <td>Suitable for ages 16 and up. Programs may contain more intensive violence and coarse 247 * language, partial nudity and moderate sexual references</td> 248 * </tr> 249 * <tr> 250 * <td>AR_TV_SAM_18</td> 251 * <td>Suitable for mature audiences only. Programs contain strong violence, coarse language 252 * and explicit sexual references</td> 253 * </tr> 254 * <tr> 255 * <td valign="top" rowspan="8">AU_TV</td> 256 * <td>AU_TV_P</td> 257 * <td>Recommended for younger children aged between 2 and 11 years</td> 258 * </tr> 259 * <tr> 260 * <td>AU_TV_C</td> 261 * <td>Recommended for older children aged between 5 and 14 years</td> 262 * </tr> 263 * <tr> 264 * <td>AU_TV_G</td> 265 * <td>Recommended for all ages</td> 266 * </tr> 267 * <tr> 268 * <td>AU_TV_PG</td> 269 * <td>Parental guidance is recommended for young viewers under 15</td> 270 * </tr> 271 * <tr> 272 * <td>AU_TV_M</td> 273 * <td>Recommended for mature audiences aged 15 years and over</td> 274 * </tr> 275 * <tr> 276 * <td>AU_TV_MA</td> 277 * <td>Not suitable for children and teens under 15, due to sexual descriptions, course 278 * language, adult themes or drug use</td> 279 * </tr> 280 * <tr> 281 * <td>AU_TV_AV</td> 282 * <td>Not suitable for children and teens under 15. This category is used specifically for 283 * violent programs</td> 284 * </tr> 285 * <tr> 286 * <td>AU_TV_R</td> 287 * <td>Not for children under 18. Content may include graphic violence, sexual situations, 288 * coarse language and explicit drug use</td> 289 * </tr> 290 * <tr> 291 * <td valign="top" rowspan="6">BR_TV</td> 292 * <td>BR_TV_L</td> 293 * <td>Content is suitable for all audiences</td> 294 * </tr> 295 * <tr> 296 * <td>BR_TV_10</td> 297 * <td>Content suitable for viewers over the age of 10</td> 298 * </tr> 299 * <tr> 300 * <td>BR_TV_12</td> 301 * <td>Content suitable for viewers over the age of 12</td> 302 * </tr> 303 * <tr> 304 * <td>BR_TV_14</td> 305 * <td>Content suitable for viewers over the age of 14</td> 306 * </tr> 307 * <tr> 308 * <td>BR_TV_16</td> 309 * <td>Content suitable for viewers over the age of 16</td> 310 * </tr> 311 * <tr> 312 * <td>BR_TV_18</td> 313 * <td>Content suitable for viewers over the age of 18</td> 314 * </tr> 315 * <tr> 316 * <td valign="top" rowspan="7">CA_TV_EN</td> 317 * <td>CA_TV_EN_EXEMPT</td> 318 * <td>Exempt from ratings</td> 319 * </tr> 320 * <tr> 321 * <td>CA_TV_EN_C</td> 322 * <td>Suitable for children ages 2–7</td> 323 * </tr> 324 * <tr> 325 * <td>CA_TV_EN_C8</td> 326 * <td>Suitable for children ages 8 and older</td> 327 * </tr> 328 * <tr> 329 * <td>CA_TV_EN_G</td> 330 * <td>Suitable for the entire family</td> 331 * </tr> 332 * <tr> 333 * <td>CA_TV_EN_PG</td> 334 * <td>May contain moderate violence, profanity, nudity, and sexual references</td> 335 * </tr> 336 * <tr> 337 * <td>CA_TV_EN_14</td> 338 * <td>Intended for viewers ages 14 and older</td> 339 * </tr> 340 * <tr> 341 * <td>CA_TV_EN_18</td> 342 * <td>Intended for viewers ages 18 and older</td> 343 * </tr> 344 * <tr> 345 * <td valign="top" rowspan="6">CA_TV_FR</td> 346 * <td>CA_TV_FR_E</td> 347 * <td>Exempt from ratings</td> 348 * </tr> 349 * <tr> 350 * <td>CA_TV_FR_G</td> 351 * <td>Appropriate for all ages</td> 352 * </tr> 353 * <tr> 354 * <td>CA_TV_FR_8</td> 355 * <td>Appropriate for children 8</td> 356 * </tr> 357 * <tr> 358 * <td>CA_TV_FR_13</td> 359 * <td>Suitable for children 13</td> 360 * </tr> 361 * <tr> 362 * <td>CA_TV_FR_16</td> 363 * <td>Recommended for children over the age of 16</td> 364 * </tr> 365 * <tr> 366 * <td>CA_TV_FR_18</td> 367 * <td>Only to be viewed by adults</td> 368 * </tr> 369 * <tr> 370 * <td valign="top" rowspan="15">DTMB</td> 371 * <td>DTMB_4</td> 372 * <td>Recommended for ages 4 and over</td> 373 * </tr> 374 * <tr> 375 * <td>DTMB_5</td> 376 * <td>Recommended for ages 5 and over</td> 377 * </tr> 378 * <tr> 379 * <td>DTMB_6</td> 380 * <td>Recommended for ages 6 and over</td> 381 * </tr> 382 * <tr> 383 * <td>DTMB_7</td> 384 * <td>Recommended for ages 7 and over</td> 385 * </tr> 386 * <tr> 387 * <td>DTMB_8</td> 388 * <td>Recommended for ages 8 and over</td> 389 * </tr> 390 * <tr> 391 * <td>DTMB_9</td> 392 * <td>Recommended for ages 9 and over</td> 393 * </tr> 394 * <tr> 395 * <td>DTMB_10</td> 396 * <td>Recommended for ages 10 and over</td> 397 * </tr> 398 * <tr> 399 * <td>DTMB_11</td> 400 * <td>Recommended for ages 11 and over</td> 401 * </tr> 402 * <tr> 403 * <td>DTMB_12</td> 404 * <td>Recommended for ages 12 and over</td> 405 * </tr> 406 * <tr> 407 * <td>DTMB_13</td> 408 * <td>Recommended for ages 13 and over</td> 409 * </tr> 410 * <tr> 411 * <td>DTMB_14</td> 412 * <td>Recommended for ages 14 and over</td> 413 * </tr> 414 * <tr> 415 * <td>DTMB_15</td> 416 * <td>Recommended for ages 15 and over</td> 417 * </tr> 418 * <tr> 419 * <td>DTMB_16</td> 420 * <td>Recommended for ages 16 and over</td> 421 * </tr> 422 * <tr> 423 * <td>DTMB_17</td> 424 * <td>Recommended for ages 17 and over</td> 425 * </tr> 426 * <tr> 427 * <td>DTMB_18</td> 428 * <td>Recommended for ages 18 and over</td> 429 * </tr> 430 * <tr> 431 * <td valign="top" rowspan="15">DVB</td> 432 * <td>DVB_4</td> 433 * <td>Recommended for ages 4 and over</td> 434 * </tr> 435 * <tr> 436 * <td>DVB_5</td> 437 * <td>Recommended for ages 5 and over</td> 438 * </tr> 439 * <tr> 440 * <td>DVB_6</td> 441 * <td>Recommended for ages 6 and over</td> 442 * </tr> 443 * <tr> 444 * <td>DVB_7</td> 445 * <td>Recommended for ages 7 and over</td> 446 * </tr> 447 * <tr> 448 * <td>DVB_8</td> 449 * <td>Recommended for ages 8 and over</td> 450 * </tr> 451 * <tr> 452 * <td>DVB_9</td> 453 * <td>Recommended for ages 9 and over</td> 454 * </tr> 455 * <tr> 456 * <td>DVB_10</td> 457 * <td>Recommended for ages 10 and over</td> 458 * </tr> 459 * <tr> 460 * <td>DVB_11</td> 461 * <td>Recommended for ages 11 and over</td> 462 * </tr> 463 * <tr> 464 * <td>DVB_12</td> 465 * <td>Recommended for ages 12 and over</td> 466 * </tr> 467 * <tr> 468 * <td>DVB_13</td> 469 * <td>Recommended for ages 13 and over</td> 470 * </tr> 471 * <tr> 472 * <td>DVB_14</td> 473 * <td>Recommended for ages 14 and over</td> 474 * </tr> 475 * <tr> 476 * <td>DVB_15</td> 477 * <td>Recommended for ages 15 and over</td> 478 * </tr> 479 * <tr> 480 * <td>DVB_16</td> 481 * <td>Recommended for ages 16 and over</td> 482 * </tr> 483 * <tr> 484 * <td>DVB_17</td> 485 * <td>Recommended for ages 17 and over</td> 486 * </tr> 487 * <tr> 488 * <td>DVB_18</td> 489 * <td>Recommended for ages 18 and over</td> 490 * </tr> 491 * <tr> 492 * <td valign="top" rowspan="18">ES_DVB</td> 493 * <td>ES_DVB_ALL</td> 494 * <td>Recommended for all ages</td> 495 * </tr> 496 * <tr> 497 * <td>ES_DVB_C</td> 498 * <td>Recommended for children</td> 499 * </tr> 500 * <tr> 501 * <td>ES_DVB_X</td> 502 * <td>Recommended for adults</td> 503 * </tr> 504 * <tr> 505 * <td>ES_DVB_4</td> 506 * <td>Recommended for ages 4 and over</td> 507 * </tr> 508 * <tr> 509 * <td>ES_DVB_5</td> 510 * <td>Recommended for ages 5 and over</td> 511 * </tr> 512 * <tr> 513 * <td>ES_DVB_6</td> 514 * <td>Recommended for ages 6 and over</td> 515 * </tr> 516 * <tr> 517 * <td>ES_DVB_7</td> 518 * <td>Recommended for ages 7 and over</td> 519 * </tr> 520 * <tr> 521 * <td>ES_DVB_8</td> 522 * <td>Recommended for ages 8 and over</td> 523 * </tr> 524 * <tr> 525 * <td>ES_DVB_9</td> 526 * <td>Recommended for ages 9 and over</td> 527 * </tr> 528 * <tr> 529 * <td>ES_DVB_10</td> 530 * <td>Recommended for ages 10 and over</td> 531 * </tr> 532 * <tr> 533 * <td>ES_DVB_11</td> 534 * <td>Recommended for ages 11 and over</td> 535 * </tr> 536 * <tr> 537 * <td>ES_DVB_12</td> 538 * <td>Recommended for ages 12 and over</td> 539 * </tr> 540 * <tr> 541 * <td>ES_DVB_13</td> 542 * <td>Recommended for ages 13 and over</td> 543 * </tr> 544 * <tr> 545 * <td>ES_DVB_14</td> 546 * <td>Recommended for ages 14 and over</td> 547 * </tr> 548 * <tr> 549 * <td>ES_DVB_15</td> 550 * <td>Recommended for ages 15 and over</td> 551 * </tr> 552 * <tr> 553 * <td>ES_DVB_16</td> 554 * <td>Recommended for ages 16 and over</td> 555 * </tr> 556 * <tr> 557 * <td>ES_DVB_17</td> 558 * <td>Recommended for ages 17 and over</td> 559 * </tr> 560 * <tr> 561 * <td>ES_DVB_18</td> 562 * <td>Recommended for ages 18 and over</td> 563 * </tr> 564 * <tr> 565 * <td valign="top" rowspan="16">FR_DVB</td> 566 * <td>FR_DVB_U</td> 567 * <td>Recommended for all ages</td> 568 * </tr> 569 * <tr> 570 * <td>FR_DVB_4</td> 571 * <td>Recommended for ages 4 and over</td> 572 * </tr> 573 * <tr> 574 * <td>FR_DVB_5</td> 575 * <td>Recommended for ages 5 and over</td> 576 * </tr> 577 * <tr> 578 * <td>FR_DVB_6</td> 579 * <td>Recommended for ages 6 and over</td> 580 * </tr> 581 * <tr> 582 * <td>FR_DVB_7</td> 583 * <td>Recommended for ages 7 and over</td> 584 * </tr> 585 * <tr> 586 * <td>FR_DVB_8</td> 587 * <td>Recommended for ages 8 and over</td> 588 * </tr> 589 * <tr> 590 * <td>FR_DVB_9</td> 591 * <td>Recommended for ages 9 and over</td> 592 * </tr> 593 * <tr> 594 * <td>FR_DVB_10</td> 595 * <td>Recommended for ages 10 and over</td> 596 * </tr> 597 * <tr> 598 * <td>FR_DVB_11</td> 599 * <td>Recommended for ages 11 and over</td> 600 * </tr> 601 * <tr> 602 * <td>FR_DVB_12</td> 603 * <td>Recommended for ages 12 and over</td> 604 * </tr> 605 * <tr> 606 * <td>FR_DVB_13</td> 607 * <td>Recommended for ages 13 and over</td> 608 * </tr> 609 * <tr> 610 * <td>FR_DVB_14</td> 611 * <td>Recommended for ages 14 and over</td> 612 * </tr> 613 * <tr> 614 * <td>FR_DVB_15</td> 615 * <td>Recommended for ages 15 and over</td> 616 * </tr> 617 * <tr> 618 * <td>FR_DVB_16</td> 619 * <td>Recommended for ages 16 and over</td> 620 * </tr> 621 * <tr> 622 * <td>FR_DVB_17</td> 623 * <td>Recommended for ages 17 and over</td> 624 * </tr> 625 * <tr> 626 * <td>FR_DVB_18</td> 627 * <td>Recommended for ages 18 and over</td> 628 * </tr> 629 * <tr> 630 * <td valign="top" rowspan="17">ISDB</td> 631 * <td>ISDB_4</td> 632 * <td>Recommended for ages 4 and over</td> 633 * </tr> 634 * <tr> 635 * <td>ISDB_5</td> 636 * <td>Recommended for ages 5 and over</td> 637 * </tr> 638 * <tr> 639 * <td>ISDB_6</td> 640 * <td>Recommended for ages 6 and over</td> 641 * </tr> 642 * <tr> 643 * <td>ISDB_7</td> 644 * <td>Recommended for ages 7 and over</td> 645 * </tr> 646 * <tr> 647 * <td>ISDB_8</td> 648 * <td>Recommended for ages 8 and over</td> 649 * </tr> 650 * <tr> 651 * <td>ISDB_9</td> 652 * <td>Recommended for ages 9 and over</td> 653 * </tr> 654 * <tr> 655 * <td>ISDB_10</td> 656 * <td>Recommended for ages 10 and over</td> 657 * </tr> 658 * <tr> 659 * <td>ISDB_11</td> 660 * <td>Recommended for ages 11 and over</td> 661 * </tr> 662 * <tr> 663 * <td>ISDB_12</td> 664 * <td>Recommended for ages 12 and over</td> 665 * </tr> 666 * <tr> 667 * <td>ISDB_13</td> 668 * <td>Recommended for ages 13 and over</td> 669 * </tr> 670 * <tr> 671 * <td>ISDB_14</td> 672 * <td>Recommended for ages 14 and over</td> 673 * </tr> 674 * <tr> 675 * <td>ISDB_15</td> 676 * <td>Recommended for ages 15 and over</td> 677 * </tr> 678 * <tr> 679 * <td>ISDB_16</td> 680 * <td>Recommended for ages 16 and over</td> 681 * </tr> 682 * <tr> 683 * <td>ISDB_17</td> 684 * <td>Recommended for ages 17 and over</td> 685 * </tr> 686 * <tr> 687 * <td>ISDB_18</td> 688 * <td>Recommended for ages 18 and over</td> 689 * </tr> 690 * <tr> 691 * <td>ISDB_19</td> 692 * <td>Recommended for ages 19 and over</td> 693 * </tr> 694 * <tr> 695 * <td>ISDB_20</td> 696 * <td>Recommended for ages 20 and over</td> 697 * </tr> 698 * <tr> 699 * <td valign="top" rowspan="5">KR_TV</td> 700 * <td>KR_TV_ALL</td> 701 * <td>Appropriate for all ages</td> 702 * </tr> 703 * <tr> 704 * <td>KR_TV_7</td> 705 * <td>May contain material inappropriate for children younger than 7, and parental 706 * discretion should be used</td> 707 * </tr> 708 * <tr> 709 * <td>KR_TV_12</td> 710 * <td>May deemed inappropriate for those younger than 12, and parental discretion should be 711 * used</td> 712 * </tr> 713 * <tr> 714 * <td>KR_TV_15</td> 715 * <td>May be inappropriate for children under 15, and that parental discretion should be 716 * used</td> 717 * </tr> 718 * <tr> 719 * <td>KR_TV_19</td> 720 * <td>For adults only</td> 721 * </tr> 722 * <tr> 723 * <td valign="top" rowspan="3">NZ_TV</td> 724 * <td>NZ_TV_G</td> 725 * <td>Programmes which exclude material likely to be unsuitable for children. Programmes 726 * may not necessarily be designed for child viewers but should not contain material likely 727 * to alarm or distress them</td> 728 * </tr> 729 * <tr> 730 * <td>NZ_TV_PGR</td> 731 * <td>Programmes containing material more suited for mature audiences but not necessarily 732 * unsuitable for child viewers when subject to the guidance of a parent or an adult</td> 733 * </tr> 734 * <tr> 735 * <td>NZ_TV_AO</td> 736 * <td>Programmes containing adult themes and directed primarily at mature audiences</td> 737 * </tr> 738 * <tr> 739 * <td valign="top" rowspan="6">SG_TV</td> 740 * <td>SG_TV_G</td> 741 * <td>Suitable for all ages</td> 742 * </tr> 743 * <tr> 744 * <td>SG_TV_PG</td> 745 * <td>Suitable for all but parents should guide their young</td> 746 * </tr> 747 * <tr> 748 * <td>SG_TV_PG13</td> 749 * <td>Suitable for persons aged 13 and above but parental guidance is advised for children 750 * below 13</td> 751 * </tr> 752 * <tr> 753 * <td>SG_TV_NC16</td> 754 * <td>Suitable for persons aged 16 and above</td> 755 * </tr> 756 * <tr> 757 * <td>SG_TV_M18</td> 758 * <td>Suitable for persons aged 18 and above</td> 759 * </tr> 760 * <tr> 761 * <td>SG_TV_R21</td> 762 * <td>Suitable for adults aged 21 and above</td> 763 * </tr> 764 * <tr> 765 * <td valign="top" rowspan="6">TH_TV</td> 766 * <td>TH_TV_4</td> 767 * <td>Suitable for audiences 3 to 5 years of age</td> 768 * </tr> 769 * <tr> 770 * <td>TH_TV_6</td> 771 * <td>Suitable for audiences 6 to 12 years of age</td> 772 * </tr> 773 * <tr> 774 * <td>TH_TV_10</td> 775 * <td>Suitable for all audiences</td> 776 * </tr> 777 * <tr> 778 * <td>TH_TV_13</td> 779 * <td>Parental guidance suggested for viewers age below 13</td> 780 * </tr> 781 * <tr> 782 * <td>TH_TV_18</td> 783 * <td>Parental guidance suggested for viewers age below 18</td> 784 * </tr> 785 * <tr> 786 * <td>TH_TV_19</td> 787 * <td>Not suitable for children and teenagers</td> 788 * </tr> 789 * <tr> 790 * <td valign="top" rowspan="5">US_MV</td> 791 * <td>US_MV_G</td> 792 * <td>General audiences</td> 793 * </tr> 794 * <tr> 795 * <td>US_MV_PG</td> 796 * <td>Parental guidance suggested</td> 797 * </tr> 798 * <tr> 799 * <td>US_MV_PG13</td> 800 * <td>Parents strongly cautioned</td> 801 * </tr> 802 * <tr> 803 * <td>US_MV_R</td> 804 * <td>Restricted, under 17 requires accompanying parent or adult guardian</td> 805 * </tr> 806 * <tr> 807 * <td>US_MV_NC17</td> 808 * <td>No one 17 and under admitted</td> 809 * </tr> 810 * <tr> 811 * <td valign="top" rowspan="6">US_TV</td> 812 * <td>US_TV_Y</td> 813 * <td>This program is designed to be appropriate for all children</td> 814 * </tr> 815 * <tr> 816 * <td>US_TV_Y7</td> 817 * <td>This program is designed for children age 7 and above</td> 818 * </tr> 819 * <tr> 820 * <td>US_TV_G</td> 821 * <td>Most parents would find this program suitable for all ages</td> 822 * </tr> 823 * <tr> 824 * <td>US_TV_PG</td> 825 * <td>This program contains material that parents may find unsuitable for younger children 826 * </td> 827 * </tr> 828 * <tr> 829 * <td>US_TV_14</td> 830 * <td>This program contains some material that many parents would find unsuitable for 831 * children under 14 years of age</td> 832 * </tr> 833 * <tr> 834 * <td>US_TV_MA</td> 835 * <td>This program is specifically designed to be viewed by adults and therefore may be 836 * unsuitable for children under 17</td> 837 * </tr> 838 * </table> 839 * 840 * <h4>System defined strings for sub-ratings</h4> 841 * <table> 842 * <tr> 843 * <th>Rating System</th> 844 * <th>Constant Value</th> 845 * <th>Description</th> 846 * </tr> 847 * <tr> 848 * <td valign="top" rowspan="3">BR_TV</td> 849 * <td>BR_TV_D</td> 850 * <td>Drugs<br/>Applicable to BR_TV_L, BR_TV_10, BR_TV_12, BR_TV_14, BR_TV_16, and BR_TV_18 851 * </td> 852 * </tr> 853 * <tr> 854 * <td>BR_TV_S</td> 855 * <td>Sex<br/>Applicable to BR_TV_L, BR_TV_10, BR_TV_12, BR_TV_14, BR_TV_16, and BR_TV_18 856 * </td> 857 * </tr> 858 * <tr> 859 * <td>BR_TV_V</td> 860 * <td>Violence<br/>Applicable to BR_TV_L, BR_TV_10, BR_TV_12, BR_TV_14, BR_TV_16, and 861 * BR_TV_18</td> 862 * </tr> 863 * <tr> 864 * <td valign="top" rowspan="5">US_TV</td> 865 * <td>US_TV_D</td> 866 * <td>Suggestive dialogue (Usually means talks about sex)<br/>Applicable to US_TV_PG, and 867 * US_TV_14</td> 868 * </tr> 869 * <tr> 870 * <td>US_TV_L</td> 871 * <td>Coarse language<br/>Applicable to US_TV_PG, US_TV_14, and US_TV_MA</td> 872 * </tr> 873 * <tr> 874 * <td>US_TV_S</td> 875 * <td>Sexual content<br/>Applicable to US_TV_PG, US_TV_14, and US_TV_MA</td> 876 * </tr> 877 * <tr> 878 * <td>US_TV_V</td> 879 * <td>Violence<br/>Applicable to US_TV_PG, US_TV_14, and US_TV_MA</td> 880 * </tr> 881 * <tr> 882 * <td>US_TV_FV</td> 883 * <td>Fantasy violence (Children's programming only)<br/>Applicable to US_TV_Y7</td> 884 * </tr> 885 * </table> 886 */ 887 public final class TvContentRating { 888 // TODO: Consider to use other DELIMITER. In some countries such as India may use this delimiter 889 // in the main ratings. 890 private static final String DELIMITER = "/"; 891 892 private final String mDomain; 893 private final String mRatingSystem; 894 private final String mRating; 895 private final String[] mSubRatings; 896 private final int mHashCode; 897 898 /** 899 * Rating constant denoting unrated content. Used to handle the case where the content rating 900 * information is missing. 901 * 902 * <p>TV input services can call {@link TvInputManager#isRatingBlocked} with this constant to 903 * determine whether they should block unrated content. The subsequent call to 904 * {@link TvInputService.Session#notifyContentBlocked} with the same constant notifies 905 * applications that the current program content is blocked by parental controls. 906 */ 907 public static final TvContentRating UNRATED = new TvContentRating("null", "null", "null", null); 908 909 /** 910 * Creates a {@code TvContentRating} object with predefined content rating strings. 911 * 912 * @param domain The domain string. For example, "com.android.tv". 913 * @param ratingSystem The rating system string. For example, "US_TV". 914 * @param rating The content rating string. For example, "US_TV_PG". 915 * @param subRatings The sub-rating strings. For example, "US_TV_D" and "US_TV_L". 916 * @return A {@code TvContentRating} object. 917 * @throws IllegalArgumentException If {@code domain}, {@code ratingSystem} or {@code rating} is 918 * {@code null}. 919 */ createRating(String domain, String ratingSystem, String rating, String... subRatings)920 public static TvContentRating createRating(String domain, String ratingSystem, 921 String rating, String... subRatings) { 922 if (TextUtils.isEmpty(domain)) { 923 throw new IllegalArgumentException("domain cannot be empty"); 924 } 925 if (TextUtils.isEmpty(ratingSystem)) { 926 throw new IllegalArgumentException("ratingSystem cannot be empty"); 927 } 928 if (TextUtils.isEmpty(rating)) { 929 throw new IllegalArgumentException("rating cannot be empty"); 930 } 931 return new TvContentRating(domain, ratingSystem, rating, subRatings); 932 } 933 934 /** 935 * Recovers a {@code TvContentRating} object from the string that was previously created from 936 * {@link #flattenToString}. 937 * 938 * @param ratingString The string returned by {@link #flattenToString}. 939 * @return the {@code TvContentRating} object containing the domain, rating system, rating and 940 * sub-ratings information encoded in {@code ratingString}. 941 * @see #flattenToString 942 */ unflattenFromString(String ratingString)943 public static TvContentRating unflattenFromString(String ratingString) { 944 if (TextUtils.isEmpty(ratingString)) { 945 throw new IllegalArgumentException("ratingString cannot be empty"); 946 } 947 String[] strs = ratingString.split(DELIMITER); 948 if (strs.length < 3) { 949 throw new IllegalArgumentException("Invalid rating string: " + ratingString); 950 } 951 if (strs.length > 3) { 952 String[] subRatings = new String[strs.length - 3]; 953 System.arraycopy(strs, 3, subRatings, 0, subRatings.length); 954 return new TvContentRating(strs[0], strs[1], strs[2], subRatings); 955 } 956 return new TvContentRating(strs[0], strs[1], strs[2], null); 957 } 958 959 /** 960 * Constructs a TvContentRating object from a given rating and sub-rating constants. 961 * 962 * @param domain The string for domain of the content rating system such as "com.android.tv". 963 * @param ratingSystem The rating system string such as "US_TV". 964 * @param rating The content rating string such as "US_TV_PG". 965 * @param subRatings The sub-rating strings such as "US_TV_D" and "US_TV_L". 966 */ TvContentRating( String domain, String ratingSystem, String rating, String[] subRatings)967 private TvContentRating( 968 String domain, String ratingSystem, String rating, String[] subRatings) { 969 mDomain = domain; 970 mRatingSystem = ratingSystem; 971 mRating = rating; 972 if (subRatings == null || subRatings.length == 0) { 973 mSubRatings = null; 974 } else { 975 Arrays.sort(subRatings); 976 mSubRatings = subRatings; 977 } 978 mHashCode = 31 * Objects.hash(mDomain, mRating) + Arrays.hashCode(mSubRatings); 979 } 980 981 /** 982 * Returns the domain of this {@code TvContentRating} object. 983 */ getDomain()984 public String getDomain() { 985 return mDomain; 986 } 987 988 /** 989 * Returns the rating system of this {@code TvContentRating} object. 990 */ getRatingSystem()991 public String getRatingSystem() { 992 return mRatingSystem; 993 } 994 995 /** 996 * Returns the main rating of this {@code TvContentRating} object. 997 */ getMainRating()998 public String getMainRating() { 999 return mRating; 1000 } 1001 1002 /** 1003 * Returns the unmodifiable sub-rating string {@link List} of this {@code TvContentRating} 1004 * object. 1005 */ getSubRatings()1006 public List<String> getSubRatings() { 1007 if (mSubRatings == null) { 1008 return null; 1009 } 1010 return Collections.unmodifiableList(Arrays.asList(mSubRatings)); 1011 } 1012 1013 /** 1014 * Returns a string that unambiguously describes the rating information contained in a 1015 * {@code TvContentRating} object. One can later recover the object from this string through 1016 * {@link #unflattenFromString}. 1017 * 1018 * @return a string containing the rating information, which can later be stored in the 1019 * database. 1020 * @see #unflattenFromString 1021 */ flattenToString()1022 public String flattenToString() { 1023 StringBuilder builder = new StringBuilder(); 1024 builder.append(mDomain); 1025 builder.append(DELIMITER); 1026 builder.append(mRatingSystem); 1027 builder.append(DELIMITER); 1028 builder.append(mRating); 1029 if (mSubRatings != null) { 1030 for (String subRating : mSubRatings) { 1031 builder.append(DELIMITER); 1032 builder.append(subRating); 1033 } 1034 } 1035 return builder.toString(); 1036 } 1037 1038 /** 1039 * Returns {@code true} if this rating has the same main rating as the specified rating and when 1040 * this rating's sub-ratings contain the other's. 1041 * 1042 * <p>For example, a {@code TvContentRating} object that represents TV-PG with 1043 * S(Sexual content) and V(Violence) contains TV-PG, TV-PG/S, TV-PG/V and itself. 1044 * 1045 * @param rating The {@link TvContentRating} to check. 1046 * @return {@code true} if this object contains {@code rating}, {@code false} otherwise. 1047 */ contains(@onNull TvContentRating rating)1048 public final boolean contains(@NonNull TvContentRating rating) { 1049 Preconditions.checkNotNull(rating); 1050 if (!rating.getMainRating().equals(mRating)) { 1051 return false; 1052 } 1053 if (!rating.getDomain().equals(mDomain) || 1054 !rating.getRatingSystem().equals(mRatingSystem) || 1055 !rating.getMainRating().equals(mRating)) { 1056 return false; 1057 } 1058 List<String> subRatings = getSubRatings(); 1059 List<String> subRatingsOther = rating.getSubRatings(); 1060 if (subRatings == null && subRatingsOther == null) { 1061 return true; 1062 } else if (subRatings == null && subRatingsOther != null) { 1063 return false; 1064 } else if (subRatings != null && subRatingsOther == null) { 1065 return true; 1066 } else { 1067 return subRatings.containsAll(subRatingsOther); 1068 } 1069 } 1070 1071 @Override equals(Object obj)1072 public boolean equals(Object obj) { 1073 if (!(obj instanceof TvContentRating)) { 1074 return false; 1075 } 1076 TvContentRating other = (TvContentRating) obj; 1077 if (mHashCode != other.mHashCode) { 1078 return false; 1079 } 1080 if (!TextUtils.equals(mDomain, other.mDomain)) { 1081 return false; 1082 } 1083 if (!TextUtils.equals(mRatingSystem, other.mRatingSystem)) { 1084 return false; 1085 } 1086 if (!TextUtils.equals(mRating, other.mRating)) { 1087 return false; 1088 } 1089 return Arrays.equals(mSubRatings, other.mSubRatings); 1090 } 1091 1092 @Override hashCode()1093 public int hashCode() { 1094 return mHashCode; 1095 } 1096 } 1097