diff options
| author | 2014-07-29 11:48:36 +0900 | |
|---|---|---|
| committer | 2014-08-01 13:47:28 +0900 | |
| commit | 5c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5 (patch) | |
| tree | 042670f975c8ad51f618483bd9a636961e61a64c | |
| parent | 012ef36a6c5e9745d112c734aed916cab052558c (diff) | |
TIF: Use XML file for representing TvContentRating
This change addresses the following API council feedback.
- Remove all constants from TvContentRating. Instead this class becomes a
general parser for a tuple of "rating domain"+type+subtype(s).
- Instead of constants in the API, the rating definitions should come from
parsed XML meta-data tied to a TvInputService entry in the AndroidManifest.
This XML should define a ranked order of the rating constants along with
@string references for displaying in the Settings UI. Mention that the
"rating domain" should be scoped similar to a package name, for example
"com.youtube.ratings".
- For system-defined rating types (like US, Korea, etc) we should parse this
same XML format, but it may come from a hard-coded XML resource (since they
aren't tied to a single TvInputService.)
- Thoroughly document the built-in supported types in javadoc on TvContentRating.
Change-Id: I0a9526c73c8ca67fd0eeac63f3c63c05657a45e3
| -rw-r--r-- | api/current.txt | 23 | ||||
| -rw-r--r-- | core/res/res/values/attrs.xml | 4 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 2 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 37 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 1 | ||||
| -rw-r--r-- | core/res/res/xml/tv_content_rating_systems.xml | 127 | ||||
| -rw-r--r-- | media/java/android/media/tv/ITvInputManager.aidl | 2 | ||||
| -rw-r--r-- | media/java/android/media/tv/TvContentRating.java | 471 | ||||
| -rw-r--r-- | media/java/android/media/tv/TvInputInfo.java | 33 | ||||
| -rw-r--r-- | media/java/android/media/tv/TvInputManager.java | 13 | ||||
| -rw-r--r-- | services/core/java/com/android/server/tv/TvInputManagerService.java | 33 |
11 files changed, 533 insertions, 213 deletions
diff --git a/api/current.txt b/api/current.txt index 74fdd31cf148..a8bbeed111bf 100644 --- a/api/current.txt +++ b/api/current.txt @@ -465,6 +465,7 @@ package android { field public static final int contentInsetLeft = 16843863; // 0x1010457 field public static final int contentInsetRight = 16843864; // 0x1010458 field public static final int contentInsetStart = 16843861; // 0x1010455 + field public static final int contentRatingSystemXml = 16843957; // 0x10104b5 field public static final int controlX1 = 16843798; // 0x1010416 field public static final int controlX2 = 16843800; // 0x1010418 field public static final int controlY1 = 16843799; // 0x1010417 @@ -16843,28 +16844,14 @@ package android.media.session { package android.media.tv { public final class TvContentRating { - ctor public TvContentRating(java.lang.String); - ctor public TvContentRating(java.lang.String, java.lang.String[]); + method public static android.media.tv.TvContentRating createRating(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String...); method public java.lang.String flattenToString(); + method public java.lang.String getCountry(); + method public java.lang.String getDomain(); method public java.lang.String getMainRating(); + method public java.lang.String getRatingSystem(); method public java.util.List<java.lang.String> getSubRatings(); method public static android.media.tv.TvContentRating unflattenFromString(java.lang.String); - field public static final java.lang.String RATING_KR_12 = "RATING_KR_12"; - field public static final java.lang.String RATING_KR_15 = "RATING_KR_15"; - field public static final java.lang.String RATING_KR_19 = "RATING_KR_19"; - field public static final java.lang.String RATING_KR_7 = "RATING_KR_7"; - field public static final java.lang.String RATING_KR_ALL = "RATING_KR_ALL"; - field public static final java.lang.String RATING_US_TV_14 = "RATING_US_TV_14"; - field public static final java.lang.String RATING_US_TV_G = "RATING_US_TV_G"; - field public static final java.lang.String RATING_US_TV_MA = "RATING_US_TV_MA"; - field public static final java.lang.String RATING_US_TV_PG = "RATING_US_TV_PG"; - field public static final java.lang.String RATING_US_TV_Y = "RATING_US_TV_Y"; - field public static final java.lang.String RATING_US_TV_Y7 = "RATING_US_TV_Y7"; - field public static final java.lang.String SUBRATING_US_D = "SUBRATING_US_D"; - field public static final java.lang.String SUBRATING_US_FV = "SUBRATING_US_FV"; - field public static final java.lang.String SUBRATING_US_L = "SUBRATING_US_L"; - field public static final java.lang.String SUBRATING_US_S = "SUBRATING_US_S"; - field public static final java.lang.String SUBRATING_US_V = "SUBRATING_US_V"; } public final class TvContract { diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index d07d0abf73fd..a31f18f1054b 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -7259,7 +7259,9 @@ <!-- Component name of an activity that allows the user to modify the settings for this service. --> <attr name="settingsActivity" /> - <!-- Type of this service. --> + <!-- Component name of an xml file that describes the structure of TV content ratings that + this service uses. --> + <attr name="contentRatingSystemXml" format="reference" /> </declare-styleable> <declare-styleable name="ResolverDrawerLayout"> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index d8f9665e679b..08398f0932ca 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2560,4 +2560,6 @@ <public type="raw" name="loaderror" id="0x01100000"/> <!-- WebView error page for when domain lookup fails. @hide @SystemApi --> <public type="raw" name="nodomain"/> + + <public type="attr" name="contentRatingSystemXml"/> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 11c41e3b0c9f..18211158e139 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4841,4 +4841,41 @@ <!-- Lock-to-app unlock password string --> <string name="lock_to_app_unlock_password">password</string> + <string name="display_name_ustvpg" translatable="false">US-TV</string> + <string name="description_ustvpg">The TV Parental Guidelines</string> + <string name="display_name_krtv" translatable="false">KR-TV</string> + + <string name="display_name_ustvpg_d" translatable="false">D</string> + <string name="display_name_ustvpg_l" translatable="false">L</string> + <string name="display_name_ustvpg_s" translatable="false">S</string> + <string name="display_name_ustvpg_v" translatable="false">V</string> + <string name="display_name_ustvpg_fv" translatable="false">FV</string> + <string name="display_name_ustvpg_y" translatable="false">TV-Y</string> + <string name="display_name_ustvpg_y7" translatable="false">TV-Y7</string> + <string name="display_name_ustvpg_g" translatable="false">TV-G</string> + <string name="display_name_ustvpg_pg" translatable="false">TV-PG</string> + <string name="display_name_ustvpg_14" translatable="false">TV-14</string> + <string name="display_name_ustvpg_ma" translatable="false">TV-MA</string> + <string name="display_name_krtv_all" translatable="false">모든연령시청가</string> + <string name="display_name_krtv_7" translatable="false">7세이상시청가</string> + <string name="display_name_krtv_12" translatable="false">12세이상시청가</string> + <string name="display_name_krtv_15" translatable="false">15세이상시청가</string> + <string name="display_name_krtv_19" translatable="false">19세이상시청가</string> + + <string name="description_ustvpg_d">Suggestive dialogue (Usually means talks about sex)</string> + <string name="description_ustvpg_l">Coarse language</string> + <string name="description_ustvpg_s">Sexual content</string> + <string name="description_ustvpg_v">Violence</string> + <string name="description_ustvpg_fv">Fantasy violence (Children\'s programming only)</string> + <string name="description_ustvpg_y">This program is designed to be appropriate for all children.</string> + <string name="description_ustvpg_y7">This program is designed for children age 7 and above.</string> + <string name="description_ustvpg_g">Most parents would find this program suitable for all ages.</string> + <string name="description_ustvpg_pg">This program contains material that parents may find unsuitable for younger children.</string> + <string name="description_ustvpg_14">This program contains some material that many parents would find unsuitable for children under 14 years of age.</string> + <string name="description_ustvpg_ma">This program is specifically designed to be viewed by adults and therefore may be unsuitable for children under 17.</string> + <string name="description_krtv_all">모든 연령의 시청자가 시청하기에 부적절한 내용이 없는 등급을 말한다.</string> + <string name="description_krtv_7">7세미만의 어린이가 시청하기에 부적절한 내용이 포함되어 있어 보호자의 시청지도가 필요한 등급을 말한다.</string> + <string name="description_krtv_12">12세미만의 청소년이 시청하기에 부적절한 내용이 포함되어 있어 보호자의 시청지도가 필요한 등급을 말한다.</string> + <string name="description_krtv_15">15세미만의 청소년이 시청하기에 부적절한 내용이 포함되어 있어 보호자의 시청지도가 필요한 등급을 말한다.</string> + <string name="description_krtv_19">19세미만의 청소년이 시청하기에 부적절한 내용이 포함되어 있어 청소년이 시청할 수 없는 등급을 말한다.</string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6e23557331be..d37e46880c25 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1259,6 +1259,7 @@ <java-symbol type="xml" name="audio_assets" /> <java-symbol type="xml" name="global_keys" /> <java-symbol type="xml" name="default_zen_mode_config" /> + <java-symbol type="xml" name="tv_content_rating_systems" /> <java-symbol type="raw" name="accessibility_gestures" /> <java-symbol type="raw" name="incognito_mode_start_page" /> diff --git a/core/res/res/xml/tv_content_rating_systems.xml b/core/res/res/xml/tv_content_rating_systems.xml new file mode 100644 index 000000000000..238ce13864e1 --- /dev/null +++ b/core/res/res/xml/tv_content_rating_systems.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<rating-system-definitions> + <rating-system-definition id="US_TVPG" + displayName="@string/display_name_ustvpg" + description="@string/description_ustvpg" + country="US"> + <sub-rating-definition id="US_TVPG_D" + displayName="@string/display_name_ustvpg_d" + description="@string/description_ustvpg_d" /> + <sub-rating-definition id="US_TVPG_L" + displayName="@string/display_name_ustvpg_l" + description="@string/description_ustvpg_l" /> + <sub-rating-definition id="US_TVPG_S" + displayName="@string/display_name_ustvpg_s" + description="@string/description_ustvpg_s" /> + <sub-rating-definition id="US_TVPG_V" + displayName="@string/display_name_ustvpg_v" + description="@string/description_ustvpg_v" /> + <sub-rating-definition id="US_TVPG_FV" + displayName="@string/display_name_ustvpg_fv" + description="@string/description_ustvpg_fv" /> + + <rating-definition id="US_TVPG_TV_Y" + displayName="@string/display_name_ustvpg_y" + description="@string/description_ustvpg_y" + ageHint="0" /> + <rating-definition id="US_TVPG_TV_Y7" + displayName="@string/display_name_ustvpg_y7" + description="@string/description_ustvpg_y7" + ageHint="7"> + <sub-rating id="US_TVPG_FV" /> + </rating-definition> + <rating-definition id="US_TVPG_TV_G" + displayName="@string/display_name_ustvpg_g" + description="@string/description_ustvpg_g" + ageHint="0" /> + <rating-definition id="US_TVPG_TV_PG" + displayName="@string/display_name_ustvpg_pg" + description="@string/description_ustvpg_pg" + ageHint="14"> + <sub-rating id="US_TVPG_D" /> + <sub-rating id="US_TVPG_L" /> + <sub-rating id="US_TVPG_S" /> + <sub-rating id="US_TVPG_V" /> + </rating-definition> + <rating-definition id="US_TVPG_TV_14" + displayName="@string/display_name_ustvpg_14" + description="@string/description_ustvpg_14" + ageHint="14"> + <sub-rating id="US_TVPG_D" /> + <sub-rating id="US_TVPG_L" /> + <sub-rating id="US_TVPG_S" /> + <sub-rating id="US_TVPG_V" /> + </rating-definition> + <rating-definition id="US_TVPG_TV_MA" + displayName="@string/display_name_ustvpg_ma" + description="@string/description_ustvpg_ma" + ageHint="17"> + <sub-rating id="US_TVPG_L" /> + <sub-rating id="US_TVPG_S" /> + <sub-rating id="US_TVPG_V" /> + </rating-definition> + <order> + <rating id="US_TVPG_Y" /> + <rating id="US_TVPG_Y7" /> + </order> + <order> + <rating id="US_TVPG_TV_G" /> + <rating id="US_TVPG_TV_PG" /> + <rating id="US_TVPG_TV_14" /> + <rating id="US_TVPG_TV_MA" /> + </order> + </rating-system-definition> + + <rating-system-definition id="KR_TV" + displayName="@string/display_name_krtv" + country="KR"> + <rating-definition id="KR_TV_ALL" + displayName="@string/display_name_krtv_all" + description="@string/description_krtv_all" + ageHint="0" /> + <rating-definition id="KR_TV_7" + displayName="@string/display_name_krtv_7" + description="@string/description_krtv_7" + ageHint="7"> + </rating-definition> + <rating-definition id="KR_TV_12" + displayName="@string/display_name_krtv_12" + description="@string/description_krtv_12" + ageHint="12"> + </rating-definition> + <rating-definition id="KR_TV_15" + displayName="@string/display_name_krtv_15" + description="@string/description_krtv_15" + ageHint="15"> + </rating-definition> + <rating-definition id="KR_TV_19" + displayName="@string/display_name_krtv_19" + description="@string/description_krtv_19" + ageHint="19"> + </rating-definition> + <order> + <rating id="KR_TV_ALL" /> + <rating id="KR_TV_7" /> + <rating id="KR_TV_12" /> + <rating id="KR_TV_15" /> + <rating id="KR_TV_19" /> + </order> + </rating-system-definition> +</rating-system-definitions> diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl index 41c4f07186f2..8b97f328a68a 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -38,6 +38,8 @@ interface ITvInputManager { List<TvInputInfo> getTvInputList(int userId); TvInputInfo getTvInputInfo(in String inputId, int userId); + List<Uri> getTvContentRatingSystemXmls(int userId); + void registerCallback(in ITvInputManagerCallback callback, int userId); void unregisterCallback(in ITvInputManagerCallback callback, int userId); diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java index 986a7d942933..1ace7752b036 100644 --- a/media/java/android/media/tv/TvContentRating.java +++ b/media/java/android/media/tv/TvContentRating.java @@ -17,149 +17,275 @@ package android.media.tv; import android.annotation.SystemApi; +import android.net.Uri; import android.text.TextUtils; -import android.util.ArrayMap; import android.util.Log; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Map; /** * A class representing a TV content rating. + * When a TV input service provides the content rating information of a program into TV provider, + * TvContentRating class will be used for generating the value of {@link + * TvContract.Programs#COLUMN_CONTENT_RATING}. To create an object of {@link TvContentRating}, use + * the {@link #createRating} method with valid arguments. The arguments could be a system defined + * strings, or a TV input service defined strings. + * TV input service defined strings are in an xml file defined in <code><{@link + * android.R.styleable#TvInputService tv-input}></code> with the {@link + * android.R.attr#contentRatingSystemXml contentRatingSystemXml} attribute by the TV input service. + * + * <h3> Content Rating System XML format </h3> + * The XML file for publishing content rating system should follow the DTD bellow: + * <p><pre class="prettyprint"> + * <?xml version="1.0" encoding="UTF-8"?> + * <!DOCTYPE rating-systems [ + * <!ELEMENT rating-system-definitions (rating-system-definition+)> + * <!ELEMENT rating-system-definition ( + * (sub-rating-definition*, rating-definition, sub-rating-definition*)+, order*)> + * <!ATTLIST rating-system-definition + * id ID #REQUIRED + * displayName CDATA #IMPLIED + * description CDATA #IMPLIED + * country CDATA #IMPLIED> + * <!ELEMENT sub-rating-definition EMPTY> + * <!ATTLIST sub-rating-definition + * id ID #REQUIRED + * displayName CDATA #IMPLIED + * icon CDATA #IMPLIED + * description CDATA #IMPLIED> + * <!ELEMENT rating-definition (sub-rating*))> + * <!ATTLIST rating-definition + * id ID #REQUIRED + * displayName CDATA #IMPLIED + * icon CDATA #IMPLIED + * description CDATA #IMPLIED> + * <!ELEMENT sub-rating EMPTY> + * <!ATTLIST sub-rating id IDREF #REQUIRED> + * <!ELEMENT order (rating, rating+)> + * <!ELEMENT rating EMPTY> + * <!ATTLIST rating id IDREF #REQUIRED> + * ]> + * </pre></p> + * + * <h3>System defined rating strings</h3> + * + * <u>System defined string for {@code domain}</u> + * <table border="0" cellspacing="0" cellpadding="0"> + * <tr> + * <td>String value</td> + * <td>Comments</td> + * </tr> + * <tr> + * <td>android.media.tv</td> + * <td>Used for creating system defined content ratings</td> + * </tr> + * </table> + * <u>System defined string for {@code ratingSystem}</u> + * <table border="0" cellspacing="0" cellpadding="0"> + * <tr> + * <td>String value</td> + * <td>Comments</td> + * </tr> + * <tr> + * <td>US_TVPG</td> + * <td>The TV Parental Guidelines for US TV content ratings</td> + * </tr> + * <tr> + * <td>KR_TV</td> + * <td>The South Korean television rating system</td> + * </tr> + * </table> + * + * <u>System defined string for {@code rating}</u> + * <table border="0" cellspacing="0" cellpadding="0"> + * <tr> + * <td>String value</td> + * <td>Comments</td> + * </tr> + * <tr> + * <td>US_TVPG_TV_Y</td> + * <td>A rating string for the US_TVPG domain. Programs rated this are designed to be + * appropriate for all children. Whether animated or live-action, the themes and elements + * in this program are specifically designed for a very young audience, including children + * from ages 2-6. This program is not expected to frighten younger children.</td> + * </tr> + * <tr> + * <td>US_TVPG_TV_Y7</td> + * <td>A rating string for the US_TVPG domain. Programs rated this are designed for children + * age 7 and above. It may be more appropriate for children who have acquired the + * developmental skills needed to distinguish between make-believe and reality. Themes and + * elements in this program may include mild fantasy violence or comedic violence, or may + * frighten children under the age of 7. Therefore, parents may wish to consider the + * suitability of this program for their very young children. This rating may contain + * fantasy violence (US_TVPG_FV) when programs are generally more intense or more combative + * than other programs in this category.</td> + * </tr> + * <tr> + * <td>US_TVPG_TV_G</td> + * <td>A rating string for the US_TVPG domain. Most parents would find this program suitable + * for all ages. Although this rating does not signify a program designed specifically for + * children, most parents may let younger children watch this program unattended. It + * contains little or no violence, no strong language and little or no sexual dialogue or + * situations.</td> + * </tr> + * <tr> + * <td>US_TVPG_TV_PG</td> + * <td>A rating string for the US_TVPG domain. Programs rated this contain material that + * parents may find unsuitable for younger children. Many parents may want to watch it with + * their younger children. The theme itself may call for parental guidance and/or the + * program may contain one or more of the following: some suggestive dialogue (US_TVPG_D), + * infrequent coarse language (US_TVPG_L), some sexual situations (US_TVPG_S), or moderate + * violence (US_TVPG_V).</td> + * </tr> + * <tr> + * <td>US_TVPG_TV_14</td> + * <td>A rating string for the US_TVPG domain. Programs rated this contains some material + * that many parents would find unsuitable for children under 14 years of age. Parents are + * strongly urged to exercise greater care in monitoring this program and are cautioned + * against letting children under the age of 14 watch unattended. This program may contain + * one or more of the following: intensely suggestive dialogue (US_TVPG_D), strong coarse + * language (US_TVPG_L), intense sexual situations (US_TVPG_S), or intense violence + * (US_TVPG_V).</td> + * </tr> + * <tr> + * <td>US_TVPG_TV_MA</td> + * <td>A rating string for the US_TVPG domain. Programs rated TV-MA are specifically + * designed to be viewed by adults and therefore may be unsuitable for children under 17. + * This program may contain one or more of the following: crude indecent language + * (US_TVPG_L), explicit sexual activity (US_TVPG_S), or graphic violence (US_TVPG_V).</td> + * </tr> + * <tr> + * <td>KR_TV_ALL</td> + * <td>A rating string for the KR_TV domain. This rating is for programs that are + * appropriate for all ages. This program usually involves programs designed for children or + * families. This rating does not have an icon.</td> + * </tr> + * <tr> + * <td>KR_TV_7</td> + * <td>A rating string for the KR_TV domain. This rating is for programs that may contain + * material inappropriate for children younger than 7, and parental discretion should be + * used. Some cartoon programs not deemed strictly as "educational", and films rated "G" or + * "PG" in North America may fall into the 7 category.</td> + * </tr> + * <tr> + * <td>KR_TV_12</td> + * <td>A rating string for the KR_TV domain. This rating is for programs that may deemed + * inappropriate for those younger than 12, and parental discretion should be used. Usually + * used for animations that have stronger themes or violence then those designed for + * children, or for reality shows that have mild violence, themes, or language.</td> + * </tr> + * <tr> + * <td>KR_TV_15</td> + * <td>A rating string for the KR_TV domain. This rating is for programs that contain + * material that may be inappropriate for children under 15, and that parental discretion + * should be used. Examples include most dramas, and talk shows on OTA (over-the-air) TV + * (KBS, MBC, SBS), and many American TV shows/dramas on Cable TV channels like OCN and + * OnStyle. The programs that have this rating may include moderate or strong adult themes, + * language, sexual inference, and violence. As with the TV-14 rating in North America, this + * rating is commonly applied to live events where the occurrence of inappropriate dialogue + * is unpredictable. Since 2007, this rating is the most used rating for TV.</td> + * </tr> + * <tr> + * <td>KR_TV_19</td> + * <td>A rating string for the KR_TV domain. This rating is for programs that are intended + * for adults only. 19-rated programs cannot air during the hours of 7:00AM to 9:00AM, and + * 1:00PM to 10:00PM. Programs that receive this rating will almost certainly have adult + * themes, sexual situations, frequent use of strong language and disturbing scenes of + * violence.</td> + * </tr> + * </table> + * + * <u>System defined string for {@code subRating}</u> + * <table border="0" cellspacing="0" cellpadding="0"> + * <tr> + * <td>String value</td> + * <td>Comments</td> + * </tr> + * <tr> + * <td>US_TVPG_D</td> + * <td>Suggestive dialogue (Not used with US_TVPG_TV_MA)</td> + * </tr> + * <tr> + * <td>US_TVPG_L</td> + * <td>Coarse language</td> + * </tr> + * <tr> + * <td>US_TVPG_S</td> + * <td>Sexual content</td> + * </tr> + * <tr> + * <td>US_TVPG_V</td> + * <td>Violence</td> + * </tr> + * <tr> + * <td>US_TVPG_FV</td> + * <td>Fantasy violence (exclusive to US_TVPG_TV_Y7)</td> + * </tr> + * </table> */ public final class TvContentRating { private static final String TAG = "TvContentRating"; - private static final int RATING_PREFIX_LENGTH = 10; - private static final String PREFIX_RATING_US = "RATING_US_"; - private static final String PREFIX_SUBRATING_US = "SUBRATING_US_"; + /** @hide */ + public static final Uri SYSTEM_CONTENT_RATING_SYSTEM_XML = Uri.parse( + "android.resource://system/" + com.android.internal.R.xml.tv_content_rating_systems); - /** - * Rating constant for TV-Y from the TV Parental Guidelines system in US. This program is - * designed to be appropriate for all children. - */ - public static final String RATING_US_TV_Y = PREFIX_RATING_US + "TV_Y"; - /** - * Rating constant for TV-Y7 from the TV Parental Guidelines system in US. This program is - * designed for children age 7 and above. - */ - public static final String RATING_US_TV_Y7 = PREFIX_RATING_US + "TV_Y7"; - /** - * Rating constant for TV-G from the TV Parental Guidelines system in US. Most parents would - * find this program suitable for all ages. - */ - public static final String RATING_US_TV_G = PREFIX_RATING_US + "TV_G"; - /** - * Rating constant for TV-PG from the TV Parental Guidelines system in US. This program contains - * material that parents may find unsuitable for younger children. - */ - public static final String RATING_US_TV_PG = PREFIX_RATING_US + "TV_PG"; - /** - * Rating constant for TV-14 from the TV Parental Guidelines system in US. This program contains - * some material that many parents would find unsuitable for children under 14 years of age. - */ - public static final String RATING_US_TV_14 = PREFIX_RATING_US + "TV_14"; - /** - * Rating constant for TV-MA from the TV Parental Guidelines system in US. This program is - * specifically designed to be viewed by adults and therefore may be unsuitable for children - * under 17. - */ - public static final String RATING_US_TV_MA = PREFIX_RATING_US + "TV_MA"; - - /** - * Sub-rating constant for D (Suggestive dialogue) from the TV Parental Guidelines system in US. - */ - public static final String SUBRATING_US_D = PREFIX_SUBRATING_US + "D"; - /** - * Sub-rating constant for L (Coarse language) from the TV Parental Guidelines system in US. - */ - public static final String SUBRATING_US_L = PREFIX_SUBRATING_US + "L"; - /** - * Sub-rating constant for S (Sexual content) from the TV Parental Guidelines system in US. - */ - public static final String SUBRATING_US_S = PREFIX_SUBRATING_US + "S"; - /** - * Sub-rating constant for V (Violence) from the TV Parental Guidelines system in US. - */ - public static final String SUBRATING_US_V = PREFIX_SUBRATING_US + "V"; - /** - * Sub-rating constant for FV (Fantasy violence) from the TV Parental Guidelines system in US. - */ - public static final String SUBRATING_US_FV = PREFIX_SUBRATING_US + "FV"; + // TODO: Consider to use other DELIMITER. In some countries such as India may use this delimiter + // in the main ratings. + private static final String DELIMITER = "/"; - private static final String PREFIX_RATING_KR = "RATING_KR_"; + private final String mDomain; + private final String mCountryCode; + private final String mRatingSystem; + private final String mRating; + private final String[] mSubRatings; /** - * Rating constant for 'ALL' from the South Korean television rating system. This rating is for - * programming that is appropriate for all ages. - */ - public static final String RATING_KR_ALL = PREFIX_RATING_KR + "ALL"; - /** - * Rating constant for '7' from the South Korean television rating system. This rating is for - * programming that may contain material inappropriate for children younger than 7, and parental - * discretion should be used. - */ - public static final String RATING_KR_7 = PREFIX_RATING_KR + "7"; - /** - * Rating constant for '12' from the South Korean television rating system. This rating is for - * programs that may deemed inappropriate for those younger than 12, and parental discretion - * should be used. - */ - public static final String RATING_KR_12 = PREFIX_RATING_KR + "12"; - /** - * Rating constant for '15' from the South Korean television rating system. This rating is for - * programs that contain material that may be inappropriate for children under 15, and that - * parental discretion should be used. - */ - public static final String RATING_KR_15 = PREFIX_RATING_KR + "15"; - /** - * Rating constant for '19' from the South Korean television rating system. This rating is for - * programs that are intended for adults only. 19-rated programming cannot air during the hours - * of 7:00AM to 9:00AM, and 1:00PM to 10:00PM. + * Creates a TvContentRating object. + * + * @param domain The domain name. + * @param countryCode The country code in ISO 3166-2 format or {@code null}. + * @param ratingSystem The rating system id. + * @param rating The content rating string. + * @param subRatings The string array of sub-ratings. + * @return A TvContentRating object, or null if creation failed. */ - public static final String RATING_KR_19 = PREFIX_RATING_KR + "19"; - - private static final String DELIMITER = "/"; - - // A mapping from two-letter country code (ISO 3166-1 alpha-2) to its rating-to-sub-ratings map. - // This is used for validating the builder parameters. - private static final Map<String, Map<String, String[]>> sRatings - = new ArrayMap<String, Map<String, String[]>>(); - - static { - Map<String, String[]> usRatings = new ArrayMap<String, String[]>(); - usRatings.put(RATING_US_TV_Y, null); - usRatings.put(RATING_US_TV_Y7, new String[] { SUBRATING_US_FV }); - usRatings.put(RATING_US_TV_G, null); - usRatings.put(RATING_US_TV_PG, new String[] { - SUBRATING_US_D, SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V }); - usRatings.put(RATING_US_TV_14, new String[] { - SUBRATING_US_D, SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V }); - usRatings.put(RATING_US_TV_MA, new String[] { - SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V }); - sRatings.put(PREFIX_RATING_US, usRatings); - - Map<String, String[]> krRatings = new ArrayMap<String, String[]>(); - krRatings.put(RATING_KR_ALL, null); - krRatings.put(RATING_KR_7, null); - krRatings.put(RATING_KR_12, null); - krRatings.put(RATING_KR_15, null); - krRatings.put(RATING_KR_19, null); - sRatings.put(PREFIX_RATING_KR, krRatings); + public static TvContentRating createRating(String domain, String countryCode, + String ratingSystem, String rating, String... subRatings) { + if (TextUtils.isEmpty(domain)) { + throw new IllegalArgumentException("domain cannot be empty"); + } + if (TextUtils.isEmpty(rating)) { + throw new IllegalArgumentException("rating cannot be empty"); + } + return new TvContentRating(domain, countryCode, ratingSystem, rating, subRatings); } - private final String mRating; - private final String[] mSubRatings; - /** - * Constructs a TvContentRating object from a given rating constant. + * Recovers a TvContentRating from a String that was previously created with + * {@link #flattenToString}. * - * @param rating The rating constant defined in this class. + * @param ratingString The String that was returned by flattenToString(). + * @return a new TvContentRating containing the domain, countryCode, rating system, rating and + * sub-ratings information was encoded in {@code ratingString}. + * @see #flattenToString */ - public TvContentRating(String rating) { - this(rating, null); + public static TvContentRating unflattenFromString(String ratingString) { + if (TextUtils.isEmpty(ratingString)) { + throw new IllegalArgumentException("ratingString cannot be empty"); + } + String[] strs = ratingString.split(DELIMITER); + if (strs.length < 4) { + throw new IllegalArgumentException("Invalid rating string: " + ratingString); + } + if (strs.length > 4) { + String[] subRatings = new String[strs.length - 4]; + System.arraycopy(strs, 4, subRatings, 0, subRatings.length); + return new TvContentRating(strs[0], strs[1], strs[2], strs[3], subRatings); + } + return new TvContentRating(strs[0], strs[1], strs[2], strs[3], null); } /** @@ -168,57 +294,45 @@ public final class TvContentRating { * @param rating The rating constant defined in this class. * @param subRatings The String array of sub-rating constants defined in this class. */ - public TvContentRating(String rating, String[] subRatings) { - if (TextUtils.isEmpty(rating)) { - throw new IllegalArgumentException("rating cannot be null"); - } + private TvContentRating(String domain, String countryCode, + String ratingSystem, String rating, String[] subRatings) { + mDomain = domain; + mCountryCode = countryCode; + mRatingSystem = ratingSystem; mRating = rating; mSubRatings = subRatings; - String prefix = ""; - if (mRating.length() > RATING_PREFIX_LENGTH) { - prefix = mRating.substring(0, RATING_PREFIX_LENGTH); - } - Map<String, String[]> ratings = sRatings.get(prefix); - if (ratings != null) { - if (!ratings.keySet().contains(mRating)) { - Log.w(TAG, "Unknown rating: " + mRating); - } else if (mSubRatings != null) { - String[] validSubRatings = ratings.get(mRating); - if (validSubRatings == null) { - Log.w(TAG, "Invalid subratings: " + mSubRatings); - } else { - List<String> validSubRatingList = Arrays.asList(subRatings); - for (String sr : mSubRatings) { - if (TextUtils.isEmpty(sr)) { - throw new IllegalArgumentException( - "subRatings cannot contain empty elements"); - } - if (!validSubRatingList.contains(sr)) { - Log.w(TAG, "Invalid subrating: " + sr); - break; - } - } - } - } - } else { - Log.w(TAG, "Rating undefined for " + mRating); - } } /** - * Returns the main rating constant. - * - * @return the rating string that starts with "RATING_" prefix as defined in this class. + * Returns the domain. + */ + public String getDomain() { + return mDomain; + } + + /** + * Returns the country code in ISO 3166-2 format or {@code null}. + */ + public String getCountry() { + return mCountryCode; + } + + /** + * Returns the rating system id. + */ + public String getRatingSystem() { + return mRatingSystem; + } + + /** + * Returns the main rating. */ public String getMainRating() { return mRating; } /** - * Returns the list of sub-rating constants. - * - * @return the unmodifiable {@code List} of sub-rating strings that start with "SUBRATING_" - * prefix as defined in this class. + * Returns the unmodifiable {@code List} of sub-rating strings. */ public List<String> getSubRatings() { if (mSubRatings == null) { @@ -238,10 +352,14 @@ public final class TvContentRating { * @see #unflattenFromString */ public String flattenToString() { - // TODO: Consider removing all obvious/redundant sub-strings including "RATING" and - // "SUBRATING" and find out a storage-efficient string format such as: - // <country>-<primary>/<sub1>/<sub2>/<sub3> - StringBuilder builder = new StringBuilder(mRating); + StringBuilder builder = new StringBuilder(); + builder.append(mDomain); + builder.append(DELIMITER); + builder.append(mCountryCode); + builder.append(DELIMITER); + builder.append(mRatingSystem); + builder.append(DELIMITER); + builder.append(mRating); if (mSubRatings != null) { for (String subRating : mSubRatings) { builder.append(DELIMITER); @@ -252,31 +370,6 @@ public final class TvContentRating { } /** - * Recovers a TvContentRating from a String that was previously created with - * {@link #flattenToString}. - * - * @param ratingString The String that was returned by flattenToString(). - * @return a new TvContentRating containing the rating and sub-ratings information was encoded - * in {@code ratingString}. - * @see #flattenToString - */ - public static TvContentRating unflattenFromString(String ratingString) { - if (TextUtils.isEmpty(ratingString)) { - throw new IllegalArgumentException("Empty rating string"); - } - String[] strs = ratingString.split(DELIMITER); - if (strs.length < 1) { - throw new IllegalArgumentException("Invalid rating string: " + ratingString); - } - if (strs.length > 1) { - String[] subRatings = new String[strs.length - 1]; - System.arraycopy(strs, 1, subRatings, 0, subRatings.length); - return new TvContentRating(strs[0], subRatings); - } - return new TvContentRating(strs[0]); - } - - /** * Returns true if this rating has the same main rating as the specified rating and when this * rating's sub-ratings contain the other's. * <p> diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java index e48b805ad301..bc0538c3b034 100644 --- a/media/java/android/media/tv/TvInputInfo.java +++ b/media/java/android/media/tv/TvInputInfo.java @@ -18,6 +18,7 @@ package android.media.tv; import android.annotation.SystemApi; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -118,6 +119,7 @@ public final class TvInputInfo implements Parcelable { private String mLabel; private Uri mIconUri; private boolean mIsConnectedToHdmiSwitch; + private Uri mRatingSystemXmlUri; static { sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_OTHER_HARDWARE, @@ -237,6 +239,19 @@ public final class TvInputInfo implements Parcelable { Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for " + si.name); } + int contentRatingSystemXml = sa.getResourceId( + com.android.internal.R.styleable.TvInputService_contentRatingSystemXml, -1); + if (contentRatingSystemXml != -1) { + input.mRatingSystemXmlUri = new Uri.Builder() + .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) + .authority(si.packageName) + .appendPath(Integer.toString(contentRatingSystemXml)) + .build(); + if (DEBUG) { + Log.d(TAG, "Content rating xml loaded. [" + contentRatingSystemXml + "] for " + + si.name); + } + } sa.recycle(); input.mLabel = label; @@ -346,6 +361,15 @@ public final class TvInputInfo implements Parcelable { } /** + * Returns the resource uri for the rating system xml of this TV input service. + * @hide + */ + @SystemApi + public Uri getRatingSystemXmlUri() { + return mRatingSystemXmlUri; + } + + /** * Returns {@code true} if this TV input is pass-though which does not have any real channels * in TvProvider. {@code false} otherwise. * @@ -449,9 +473,10 @@ public final class TvInputInfo implements Parcelable { dest.writeString(mSetupActivity); dest.writeString(mSettingsActivity); dest.writeInt(mType); - dest.writeString(mIconUri == null ? null : mIconUri.toString()); + dest.writeParcelable(mIconUri, flags); dest.writeString(mLabel); dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0); + dest.writeParcelable(mRatingSystemXmlUri, flags); } private Drawable loadDefaultIcon(Context context) { @@ -521,11 +546,9 @@ public final class TvInputInfo implements Parcelable { mSetupActivity = in.readString(); mSettingsActivity = in.readString(); mType = in.readInt(); - String mIconUriString = in.readString(); - if (mIconUriString != null) { - mIconUri = Uri.parse(mIconUriString); - } + mIconUri = in.readParcelable(null); mLabel = in.readString(); mIsConnectedToHdmiSwitch = in.readByte() == 1 ? true : false; + mRatingSystemXmlUri = in.readParcelable(null); } } diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 49b224048978..1c83e9408ae4 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -800,6 +800,19 @@ public final class TvInputManager { } /** + * Returns the list of xml resource uris for TV content rating systems. + * @hide + */ + @SystemApi + public List<Uri> getTvContentRatingSystemXmls() { + try { + return mService.getTvContentRatingSystemXmls(mUserId); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + /** * Creates a {@link Session} for a given TV input. * <p> * The number of sessions that can be created at the same time is limited by the capability of diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 16597c05b8f4..d59c883cb65b 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -35,6 +35,7 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.res.Resources; import android.database.Cursor; import android.graphics.Rect; import android.hardware.hdmi.HdmiCecDeviceInfo; @@ -281,6 +282,18 @@ public final class TvInputManagerService extends SystemService { userState.inputMap.clear(); userState.inputMap = inputMap; + + Resources r = Resources.getSystem(); + userState.ratingSystemXmlUriSet.clear(); + userState.ratingSystemXmlUriSet.add(TvContentRating.SYSTEM_CONTENT_RATING_SYSTEM_XML); + for (TvInputState state : userState.inputMap.values()) { + Uri ratingSystemXmlUri = state.mInfo.getRatingSystemXmlUri(); + if (ratingSystemXmlUri != null) { + // TODO: need to check the validation of xml format and the duplication of rating + // systems. + userState.ratingSystemXmlUriSet.add(state.mInfo.getRatingSystemXmlUri()); + } + } } private void switchUser(int userId) { @@ -814,6 +827,23 @@ public final class TvInputManagerService extends SystemService { } @Override + public List<Uri> getTvContentRatingSystemXmls(int userId) { + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), + Binder.getCallingUid(), userId, "getTvContentRatingSystemXmls"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + UserState userState = getUserStateLocked(resolvedUserId); + List<Uri> ratingSystemXmlUriList = new ArrayList<Uri>(); + ratingSystemXmlUriList.addAll(userState.ratingSystemXmlUriSet); + return ratingSystemXmlUriList; + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public void registerCallback(final ITvInputManagerCallback callback, int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), Binder.getCallingUid(), userId, "registerCallback"); @@ -1604,6 +1634,9 @@ public final class TvInputManagerService extends SystemService { // A set of all TV input packages. private final Set<String> packageSet = new HashSet<String>(); + // A set of all TV content rating system xml uris. + private final Set<Uri> ratingSystemXmlUriSet = new HashSet<Uri>(); + // A mapping from the token of a client to its state. private final Map<IBinder, ClientState> clientStateMap = new HashMap<IBinder, ClientState>(); |