/* * Copyright (C) 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. */ package android.media.tv; import android.annotation.SystemApi; import android.text.TextUtils; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; /** * A class representing a TV content rating. When a TV input service inserts the content rating * information on a program into the database, this class can be used to generate the formatted * string for * {@link TvContract.Programs#COLUMN_CONTENT_RATING TvContract.Programs.COLUMN_CONTENT_RATING}. * To create a {@code TvContentRating} object, use the * {@link #createRating TvContentRating.createRating} method with valid rating system string * constants. *

* It is possible for an application to define its own content rating system by supplying a content * rating system definition XML resource (see example below) and declaring a broadcast receiver that * filters {@link TvInputManager#ACTION_QUERY_CONTENT_RATING_SYSTEMS} in its manifest. *

*

Example: Rating system definition for the TV Parental Guidelines

* The following XML example shows how the TV Parental Guidelines in the United States can be * defined: *

 * {@literal
 * 
 *     
 *         
 *         
 *         
 *         
 *         
 *
 *         
 *         
 *             
 *         
 *         
 *         
 *             
 *             
 *             
 *             
 *         
 *         
 *             
 *             
 *             
 *             
 *         
 *         
 *             
 *             
 *             
 *         
 *         
 *             
 *             
 *         
 *         
 *             
 *             
 *             
 *             
 *         
 *     
 * }

* *

System defined rating strings

* The following strings are defined by the system to provide a standard way to create * {@code TvContentRating} objects. *

For example, to create an object that represents TV-PG rating with suggestive dialogue and * coarse language from the TV Parental Guidelines in the United States, one can use the following * code snippet: *

*
 * TvContentRating rating = TvContentRating.createRating(
 *         "com.android.tv",
 *         "US_TV",
 *         "US_TV_PG",
 *         "US_TV_D", "US_TV_L");
 * 
*

System defined string for domains

* * * * * * * * * *
Constant ValueDescription
com.android.tvUsed for creating system defined content ratings
* *

System defined strings for rating systems

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Constant ValueDescription
AR_TVTV content rating system for Argentina
AU_TVTV content rating system for Australia
BR_TVTV content rating system for Brazil
DVBDVB content rating system
ES_DVBDVB content rating system for Spain
FR_DVBDVB content rating system for France
ISDBISDB content rating system
KR_TVTV content rating system for South Korea
SG_TVTV content rating system for Singapore
US_TVTV content rating system for the United States
* *

System defined strings for ratings

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Rating SystemConstant ValueDescription
AR_TVAR_TV_ATPSuitable for all audiences. Programs may contain mild violence, language and mature * situations
AR_TV_SAM_13Suitable for ages 13 and up. Programs may contain mild to moderate language and mild * violence and sexual references
AR_TV_SAM_16Suitable for ages 16 and up. Programs may contain more intensive violence and coarse * language, partial nudity and moderate sexual references
AR_TV_SAM_18Suitable for mature audiences only. Programs contain strong violence, coarse language * and explicit sexual references
AU_TVAU_TV_PRecommended for younger children aged between 2 and 11 years
AU_TV_CRecommended for older children aged between 5 and 14 years
AU_TV_GRecommended for all ages
AU_TV_PGParental guidance is recommended for young viewers under 15
AU_TV_MRecommended for mature audiences aged 15 years and over
AU_TV_MANot suitable for children and teens under 15, due to sexual descriptions, course * language, adult themes or drug use
AU_TV_AVNot suitable for children and teens under 15. This category is used specifically for * violent programs
AU_TV_RNot for children under 18. Content may include graphic violence, sexual situations, * coarse language and explicit drug use
BR_TVBR_TV_LContent is suitable for all audiences
BR_TV_10Content suitable for viewers over the age of 10
BR_TV_12Content suitable for viewers over the age of 12
BR_TV_14Content suitable for viewers over the age of 14
BR_TV_16Content suitable for viewers over the age of 16
BR_TV_18Content suitable for viewers over the age of 18
DVBDVB_4Recommended for ages 4 and over
DVB_5Recommended for ages 5 and over
DVB_6Recommended for ages 6 and over
DVB_7Recommended for ages 7 and over
DVB_8Recommended for ages 8 and over
DVB_9Recommended for ages 9 and over
DVB_10Recommended for ages 10 and over
DVB_11Recommended for ages 11 and over
DVB_12Recommended for ages 12 and over
DVB_13Recommended for ages 13 and over
DVB_14Recommended for ages 14 and over
DVB_15Recommended for ages 15 and over
DVB_16Recommended for ages 16 and over
DVB_17Recommended for ages 17 and over
DVB_18Recommended for ages 18 and over
ES_DVBES_DVB_ALLRecommended for all ages
ES_DVB_CRecommended for children
ES_DVB_XRecommended for adults
ES_DVB_4Recommended for ages 4 and over
ES_DVB_5Recommended for ages 5 and over
ES_DVB_6Recommended for ages 6 and over
ES_DVB_7Recommended for ages 7 and over
ES_DVB_8Recommended for ages 8 and over
ES_DVB_9Recommended for ages 9 and over
ES_DVB_10Recommended for ages 10 and over
ES_DVB_11Recommended for ages 11 and over
ES_DVB_12Recommended for ages 12 and over
ES_DVB_13Recommended for ages 13 and over
ES_DVB_14Recommended for ages 14 and over
ES_DVB_15Recommended for ages 15 and over
ES_DVB_16Recommended for ages 16 and over
ES_DVB_17Recommended for ages 17 and over
ES_DVB_18Recommended for ages 18 and over
FR_DVBFR_DVB_URecommended for all ages
FR_DVB_4Recommended for ages 4 and over
FR_DVB_5Recommended for ages 5 and over
FR_DVB_6Recommended for ages 6 and over
FR_DVB_7Recommended for ages 7 and over
FR_DVB_8Recommended for ages 8 and over
FR_DVB_9Recommended for ages 9 and over
FR_DVB_10Recommended for ages 10 and over
FR_DVB_11Recommended for ages 11 and over
FR_DVB_12Recommended for ages 12 and over
FR_DVB_13Recommended for ages 13 and over
FR_DVB_14Recommended for ages 14 and over
FR_DVB_15Recommended for ages 15 and over
FR_DVB_16Recommended for ages 16 and over
FR_DVB_17Recommended for ages 17 and over
FR_DVB_18Recommended for ages 18 and over
ISDBISDB_4Recommended for ages 4 and over
ISDB_5Recommended for ages 5 and over
ISDB_6Recommended for ages 6 and over
ISDB_7Recommended for ages 7 and over
ISDB_8Recommended for ages 8 and over
ISDB_9Recommended for ages 9 and over
ISDB_10Recommended for ages 10 and over
ISDB_11Recommended for ages 11 and over
ISDB_12Recommended for ages 12 and over
ISDB_13Recommended for ages 13 and over
ISDB_14Recommended for ages 14 and over
ISDB_15Recommended for ages 15 and over
ISDB_16Recommended for ages 16 and over
ISDB_17Recommended for ages 17 and over
ISDB_18Recommended for ages 18 and over
ISDB_19Recommended for ages 19 and over
ISDB_20Recommended for ages 20 and over
KR_TVKR_TV_ALLAppropriate for all ages
KR_TV_7May contain material inappropriate for children younger than 7, and parental * discretion should be used
KR_TV_12May deemed inappropriate for those younger than 12, and parental discretion should be * used
KR_TV_15May be inappropriate for children under 15, and that parental discretion should be * used
KR_TV_19For adults only
SG_TVSG_TV_GSuitable for all ages
SG_TV_PGSuitable for all but parents should guide their young
SG_TV_PG13Suitable for persons aged 13 and above but parental guidance is advised for children * below 13
SG_TV_NC16Suitable for persons aged 16 and above
SG_TV_M18Suitable for persons aged 18 and above
SG_TV_R21Suitable for adults aged 21 and above
US_TVUS_TV_YThis program is designed to be appropriate for all children
US_TV_Y7This program is designed for children age 7 and above
US_TV_GMost parents would find this program suitable for all ages
US_TV_PGThis program contains material that parents may find unsuitable for younger children *
US_TV_14This program contains some material that many parents would find unsuitable for * children under 14 years of age
US_TV_MAThis program is specifically designed to be viewed by adults and therefore may be * unsuitable for children under 17
* *

System defined strings for sub-ratings

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Rating SystemConstant ValueDescription
BR_TVBR_TV_DDrugs
Applicable to BR_TV_L, BR_TV_10, BR_TV_12, BR_TV_14, BR_TV_16, and BR_TV_18 *
BR_TV_SSex
Applicable to BR_TV_L, BR_TV_10, BR_TV_12, BR_TV_14, BR_TV_16, and BR_TV_18 *
BR_TV_VViolence
Applicable to BR_TV_L, BR_TV_10, BR_TV_12, BR_TV_14, BR_TV_16, and * BR_TV_18
US_TVUS_TV_DSuggestive dialogue (Usually means talks about sex)
Applicable to US_TV_PG, and * US_TV_14
US_TV_LCoarse language
Applicable to US_TV_PG, US_TV_14, and US_TV_MA
US_TV_SSexual content
Applicable to US_TV_PG, US_TV_14, and US_TV_MA
US_TV_VViolence
Applicable to US_TV_PG, US_TV_14, and US_TV_MA
US_TV_FVFantasy violence (Children's programming only)
Applicable to US_TV_Y7
*/ public final class TvContentRating { // 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 final String mDomain; private final String mRatingSystem; private final String mRating; private final String[] mSubRatings; private final int mHashCode; /** * Creates a {@code TvContentRating} object with predefined content rating strings. * * @param domain The domain string. For example, "com.android.tv". * @param ratingSystem The rating system string. For example, "US_TV". * @param rating The content rating string. For example, "US_TV_PG". * @param subRatings The sub-rating strings. For example, "US_TV_D" and "US_TV_L". * @return A {@code TvContentRating} object. * @throws IllegalArgumentException If {@code domain}, {@code ratingSystem} or {@code rating} is * {@code null}. */ public static TvContentRating createRating(String domain, String ratingSystem, String rating, String... subRatings) { if (TextUtils.isEmpty(domain)) { throw new IllegalArgumentException("domain cannot be empty"); } if (TextUtils.isEmpty(ratingSystem)) { throw new IllegalArgumentException("ratingSystem cannot be empty"); } if (TextUtils.isEmpty(rating)) { throw new IllegalArgumentException("rating cannot be empty"); } return new TvContentRating(domain, ratingSystem, rating, subRatings); } /** * Recovers a {@code TvContentRating} object from the string that was previously created from * {@link #flattenToString}. * * @param ratingString The string returned by {@link #flattenToString}. * @return the {@code TvContentRating} object containing the domain, rating system, rating and * sub-ratings information encoded in {@code ratingString}. * @see #flattenToString */ 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 < 3) { throw new IllegalArgumentException("Invalid rating string: " + ratingString); } if (strs.length > 3) { String[] subRatings = new String[strs.length - 3]; System.arraycopy(strs, 3, subRatings, 0, subRatings.length); return new TvContentRating(strs[0], strs[1], strs[2], subRatings); } return new TvContentRating(strs[0], strs[1], strs[2], null); } /** * Constructs a TvContentRating object from a given rating and sub-rating constants. * * @param domain The string for domain of the content rating system such as "com.android.tv". * @param ratingSystem The rating system string such as "US_TV". * @param rating The content rating string such as "US_TV_PG". * @param subRatings The sub-rating strings such as "US_TV_D" and "US_TV_L". */ private TvContentRating( String domain, String ratingSystem, String rating, String[] subRatings) { mDomain = domain; mRatingSystem = ratingSystem; mRating = rating; if (subRatings == null || subRatings.length == 0) { mSubRatings = null; } else { Arrays.sort(subRatings); mSubRatings = subRatings; } mHashCode = 31 * Objects.hash(mDomain, mRating) + Arrays.hashCode(mSubRatings); } /** * Returns the domain of this {@code TvContentRating} object. */ public String getDomain() { return mDomain; } /** * Returns the rating system of this {@code TvContentRating} object. */ public String getRatingSystem() { return mRatingSystem; } /** * Returns the main rating of this {@code TvContentRating} object. */ public String getMainRating() { return mRating; } /** * Returns the unmodifiable sub-rating string {@link List} of this {@code TvContentRating} * object. */ public List getSubRatings() { if (mSubRatings == null) { return null; } return Collections.unmodifiableList(Arrays.asList(mSubRatings)); } /** * Returns a string that unambiguously describes the rating information contained in a * {@code TvContentRating} object. One can later recover the object from this string through * {@link #unflattenFromString}. * * @return a string containing the rating information, which can later be stored in the * database. * @see #unflattenFromString */ public String flattenToString() { StringBuilder builder = new StringBuilder(); builder.append(mDomain); builder.append(DELIMITER); builder.append(mRatingSystem); builder.append(DELIMITER); builder.append(mRating); if (mSubRatings != null) { for (String subRating : mSubRatings) { builder.append(DELIMITER); builder.append(subRating); } } return builder.toString(); } /** * Returns {@code true} if this rating has the same main rating as the specified rating and when * this rating's sub-ratings contain the other's. *

* For example, a {@code TvContentRating} object that represents TV-PG with S(Sexual content) * and V(Violence) contains TV-PG, TV-PG/S, TV-PG/V and itself. *

* * @param rating The {@link TvContentRating} to check. * @return {@code true} if this object contains {@code rating}, {@code false} otherwise. * @hide */ @SystemApi public final boolean contains(TvContentRating rating) { if (rating == null) { throw new IllegalArgumentException("rating cannot be null"); } if (!rating.getMainRating().equals(mRating)) { return false; } if (!rating.getDomain().equals(mDomain) || !rating.getRatingSystem().equals(mRatingSystem) || !rating.getMainRating().equals(mRating)) { return false; } List subRatings = getSubRatings(); List subRatingsOther = rating.getSubRatings(); if (subRatings == null && subRatingsOther == null) { return true; } else if (subRatings == null && subRatingsOther != null) { return false; } else if (subRatings != null && subRatingsOther == null) { return true; } else { return subRatings.containsAll(subRatingsOther); } } @Override public boolean equals(Object obj) { if (!(obj instanceof TvContentRating)) { return false; } TvContentRating other = (TvContentRating) obj; if (mHashCode != other.mHashCode) { return false; } if (!TextUtils.equals(mDomain, other.mDomain)) { return false; } if (!TextUtils.equals(mRatingSystem, other.mRatingSystem)) { return false; } if (!TextUtils.equals(mRating, other.mRating)) { return false; } return Arrays.equals(mSubRatings, other.mSubRatings); } @Override public int hashCode() { return mHashCode; } }