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