TvContentRating.java revision e16873467cda89d905027458e2664c759465d463
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.media.tv;
18
19import android.text.TextUtils;
20import android.util.Log;
21
22import java.util.Arrays;
23import java.util.HashMap;
24import java.util.List;
25import java.util.Map;
26
27/**
28 * A class representing a TV content rating.
29 */
30public class TvContentRating {
31    private static final String TAG = "TvContentRating";
32
33    private static final int RATING_PREFIX_LENGTH = 10;
34    private static final String PREFIX_RATING_US = "RATING_US_";
35    private static final String PREFIX_SUBRATING_US = "SUBRATING_US_";
36
37    /**
38     * Rating constant for TV-Y from the TV Parental Guidelines system in US. This program is
39     * designed to be appropriate for all children.
40     */
41    public static final String RATING_US_TV_Y = PREFIX_RATING_US + "TV_Y";
42    /**
43     * Rating constant for TV-Y7 from the TV Parental Guidelines system in US. This program is
44     * designed for children age 7 and above.
45     */
46    public static final String RATING_US_TV_Y7 = PREFIX_RATING_US + "TV_Y7";
47    /**
48     * Rating constant for TV-G from the TV Parental Guidelines system in US. Most parents would
49     * find this program suitable for all ages.
50     */
51    public static final String RATING_US_TV_G = PREFIX_RATING_US + "TV_G";
52    /**
53     * Rating constant for TV-PG from the TV Parental Guidelines system in US. This program contains
54     * material that parents may find unsuitable for younger children.
55     */
56    public static final String RATING_US_TV_PG = PREFIX_RATING_US + "TV_PG";
57    /**
58     * Rating constant for TV-14 from the TV Parental Guidelines system in US. This program contains
59     * some material that many parents would find unsuitable for children under 14 years of age.
60     */
61    public static final String RATING_US_TV_14 = PREFIX_RATING_US + "TV_14";
62    /**
63     * Rating constant for TV-MA from the TV Parental Guidelines system in US. This program is
64     * specifically designed to be viewed by adults and therefore may be unsuitable for children
65     * under 17.
66     */
67    public static final String RATING_US_TV_MA = PREFIX_RATING_US + "TV_MA";
68
69    /**
70     * Sub-rating constant for D (Suggestive dialogue) from the TV Parental Guidelines system in US.
71     */
72    public static final String SUBRATING_US_D = PREFIX_SUBRATING_US + "D";
73    /**
74     * Sub-rating constant for L (Coarse language) from the TV Parental Guidelines system in US.
75     */
76    public static final String SUBRATING_US_L = PREFIX_SUBRATING_US + "L";
77    /**
78     * Sub-rating constant for S (Sexual content) from the TV Parental Guidelines system in US.
79     */
80    public static final String SUBRATING_US_S = PREFIX_SUBRATING_US + "S";
81    /**
82     * Sub-rating constant for V (Violence) from the TV Parental Guidelines system in US.
83     */
84    public static final String SUBRATING_US_V = PREFIX_SUBRATING_US + "V";
85    /**
86     * Sub-rating constant for FV (Fantasy violence) from the TV Parental Guidelines system in US.
87     */
88    public static final String SUBRATING_US_FV = PREFIX_SUBRATING_US + "FV";
89
90    private static final String PREFIX_RATING_KR = "RATING_KR_";
91
92    /**
93     * Rating constant for 'ALL' from the South Korean television rating system. This rating is for
94     * programming that is appropriate for all ages.
95     */
96    public static final String RATING_KR_ALL = PREFIX_RATING_KR + "ALL";
97    /**
98     * Rating constant for '7' from the South Korean television rating system. This rating is for
99     * programming that may contain material inappropriate for children younger than 7, and parental
100     * discretion should be used.
101     */
102    public static final String RATING_KR_7 = PREFIX_RATING_KR + "7";
103    /**
104     * Rating constant for '12' from the South Korean television rating system. This rating is for
105     * programs that may deemed inappropriate for those younger than 12, and parental discretion
106     * should be used.
107     */
108    public static final String RATING_KR_12 = PREFIX_RATING_KR + "12";
109    /**
110     * Rating constant for '15' from the South Korean television rating system. This rating is for
111     * programs that contain material that may be inappropriate for children under 15, and that
112     * parental discretion should be used.
113     */
114    public static final String RATING_KR_15 = PREFIX_RATING_KR + "15";
115    /**
116     * Rating constant for '19' from the South Korean television rating system. This rating is for
117     * programs that are intended for adults only. 19-rated programming cannot air during the hours
118     * of 7:00AM to 9:00AM, and 1:00PM to 10:00PM.
119     */
120    public static final String RATING_KR_19 = PREFIX_RATING_KR + "19";
121
122    private static final String DELIMITER = "/";
123
124    // A mapping from two-letter country code (ISO 3166-1 alpha-2) to its rating-to-sub-ratings map.
125    // This is used for validating the builder parameters.
126    private static final Map<String, Map<String, String[]>> sRatings
127            = new HashMap<String, Map<String, String[]>>();
128
129    static {
130        Map<String, String[]> usRatings = new HashMap<String, String[]>();
131        usRatings.put(RATING_US_TV_Y, null);
132        usRatings.put(RATING_US_TV_Y7, new String[] { SUBRATING_US_FV });
133        usRatings.put(RATING_US_TV_G, null);
134        usRatings.put(RATING_US_TV_PG, new String[] {
135                SUBRATING_US_D, SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V });
136        usRatings.put(RATING_US_TV_14, new String[] {
137                SUBRATING_US_D, SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V });
138        usRatings.put(RATING_US_TV_MA, new String[] {
139                SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V });
140        sRatings.put(PREFIX_RATING_US, usRatings);
141
142        Map<String, String[]> krRatings = new HashMap<String, String[]>();
143        krRatings.put(RATING_KR_ALL, null);
144        krRatings.put(RATING_KR_7, null);
145        krRatings.put(RATING_KR_12, null);
146        krRatings.put(RATING_KR_15, null);
147        krRatings.put(RATING_KR_19, null);
148        sRatings.put(PREFIX_RATING_KR, krRatings);
149    }
150
151    private final String mRating;
152    private final String[] mSubRatings;
153
154    /**
155     * Constructs a TvContentRating object from a given rating constant.
156     *
157     * @param rating The rating constant defined in this class.
158     */
159    public TvContentRating(String rating) {
160        mRating = rating;
161        mSubRatings = null;
162    }
163
164    /**
165     * Constructs a TvContentRating object from a given rating and sub-rating constants.
166     *
167     * @param rating The rating constant defined in this class.
168     * @param subRatings The String array of sub-rating constants defined in this class.
169     */
170    public TvContentRating(String rating, String[] subRatings) {
171        mRating = rating;
172        mSubRatings = subRatings;
173        if (TextUtils.isEmpty(mRating)) {
174            throw new IllegalArgumentException("rating cannot be null");
175        }
176        String prefix = "";
177        if (mRating.length() > RATING_PREFIX_LENGTH) {
178            prefix = mRating.substring(0, RATING_PREFIX_LENGTH);
179        }
180        Map<String, String[]> ratings = sRatings.get(prefix);
181        if (ratings != null) {
182            if (!ratings.keySet().contains(mRating)) {
183                Log.w(TAG, "Unknown rating: " + mRating);
184            } else if (mSubRatings != null) {
185                String[] validSubRatings = ratings.get(mRating);
186                if (validSubRatings == null) {
187                    Log.w(TAG, "Invalid subratings: " + mSubRatings);
188                } else {
189                    List<String> validSubRatingList = Arrays.asList(subRatings);
190                    for (String sr : mSubRatings) {
191                        if (!validSubRatingList.contains(sr)) {
192                            Log.w(TAG, "Invalid subrating: " + sr);
193                            break;
194                        }
195                    }
196                }
197            }
198        } else {
199            Log.w(TAG, "Rating undefined for " + mRating);
200        }
201    }
202
203    /**
204     * Recovers a TvContentRating from a String that was previously created with
205     * {@link #flattenToString}.
206     *
207     * @param ratingString The String that was returned by flattenToString().
208     * @return a new TvContentRating containing the rating and sub-ratings information was encoded
209     *         in {@code ratingString}.
210     * @see #flattenToString
211     */
212    public static TvContentRating unflattenFromString(String ratingString) {
213        if (TextUtils.isEmpty(ratingString)) {
214            throw new IllegalArgumentException("Empty rating string");
215        }
216        String[] strs = ratingString.split(DELIMITER);
217        if (strs.length < 1) {
218            throw new IllegalArgumentException("Invalid rating string: " + ratingString);
219        }
220        if (strs.length > 1) {
221            String[] subRatings = new String[strs.length - 1];
222            System.arraycopy(strs, 1, subRatings, 0, subRatings.length);
223            return new TvContentRating(strs[0], subRatings);
224        }
225        return new TvContentRating(strs[0]);
226    }
227
228    /**
229     * @return a String that unambiguously describes both the rating and sub-rating information
230     *         contained in the TvContentRating. You can later recover the TvContentRating from this
231     *         string through {@link #unflattenFromString}.
232     * @see #unflattenFromString
233     */
234    public String flattenToString() {
235        StringBuffer ratingStr = new StringBuffer();
236        ratingStr.append(mRating);
237        if (mSubRatings != null) {
238            for (String subRating : mSubRatings) {
239                ratingStr.append(DELIMITER);
240                ratingStr.append(subRating);
241            }
242        }
243        return ratingStr.toString();
244    }
245}
246