• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 com.android.tv.parental;
18 
19 import android.content.Context;
20 import android.media.tv.TvContentRating;
21 import android.media.tv.TvInputManager;
22 import com.android.tv.common.experiments.Experiments;
23 import com.android.tv.parental.ContentRatingSystem.Rating;
24 import com.android.tv.parental.ContentRatingSystem.SubRating;
25 import com.android.tv.util.TvSettings;
26 import com.android.tv.util.TvSettings.ContentRatingLevel;
27 import java.util.HashSet;
28 import java.util.Set;
29 
30 public class ParentalControlSettings {
31     /** The rating and all of its sub-ratings are blocked. */
32     public static final int RATING_BLOCKED = 0;
33 
34     /** The rating is blocked but not all of its sub-ratings are blocked. */
35     public static final int RATING_BLOCKED_PARTIAL = 1;
36 
37     /** The rating is not blocked. */
38     public static final int RATING_NOT_BLOCKED = 2;
39 
40     private final Context mContext;
41     private final TvInputManager mTvInputManager;
42 
43     // mRatings is expected to be synchronized with mTvInputManager.getBlockedRatings().
44     private Set<TvContentRating> mRatings;
45     private Set<TvContentRating> mCustomRatings;
46 
ParentalControlSettings(Context context)47     public ParentalControlSettings(Context context) {
48         mContext = context;
49         mTvInputManager = (TvInputManager) mContext.getSystemService(Context.TV_INPUT_SERVICE);
50     }
51 
isParentalControlsEnabled()52     public boolean isParentalControlsEnabled() {
53         return mTvInputManager.isParentalControlsEnabled();
54     }
55 
setParentalControlsEnabled(boolean enabled)56     public void setParentalControlsEnabled(boolean enabled) {
57         mTvInputManager.setParentalControlsEnabled(enabled);
58     }
59 
setContentRatingSystemEnabled( ContentRatingsManager manager, ContentRatingSystem contentRatingSystem, boolean enabled)60     public void setContentRatingSystemEnabled(
61             ContentRatingsManager manager,
62             ContentRatingSystem contentRatingSystem,
63             boolean enabled) {
64         if (enabled) {
65             TvSettings.addContentRatingSystem(mContext, contentRatingSystem.getId());
66 
67             // Ensure newly added system has ratings for current level set
68             updateRatingsForCurrentLevel(manager);
69         } else {
70             // Ensure no ratings are blocked for the selected rating system
71             for (TvContentRating tvContentRating : mTvInputManager.getBlockedRatings()) {
72                 if (contentRatingSystem.ownsRating(tvContentRating)) {
73                     mTvInputManager.removeBlockedRating(tvContentRating);
74                 }
75             }
76 
77             TvSettings.removeContentRatingSystem(mContext, contentRatingSystem.getId());
78         }
79     }
80 
isContentRatingSystemEnabled(ContentRatingSystem contentRatingSystem)81     public boolean isContentRatingSystemEnabled(ContentRatingSystem contentRatingSystem) {
82         return TvSettings.hasContentRatingSystem(mContext, contentRatingSystem.getId());
83     }
84 
loadRatings()85     public void loadRatings() {
86         mRatings = new HashSet<>(mTvInputManager.getBlockedRatings());
87     }
88 
storeRatings()89     private void storeRatings() {
90         Set<TvContentRating> removed = new HashSet<>(mTvInputManager.getBlockedRatings());
91         removed.removeAll(mRatings);
92         for (TvContentRating tvContentRating : removed) {
93             mTvInputManager.removeBlockedRating(tvContentRating);
94         }
95 
96         Set<TvContentRating> added = new HashSet<>(mRatings);
97         added.removeAll(mTvInputManager.getBlockedRatings());
98         for (TvContentRating tvContentRating : added) {
99             mTvInputManager.addBlockedRating(tvContentRating);
100         }
101     }
102 
updateRatingsForCurrentLevel(ContentRatingsManager manager)103     private void updateRatingsForCurrentLevel(ContentRatingsManager manager) {
104         @ContentRatingLevel int currentLevel = getContentRatingLevel();
105         if (currentLevel != TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
106             mRatings = ContentRatingLevelPolicy.getRatingsForLevel(this, manager, currentLevel);
107             if (currentLevel != TvSettings.CONTENT_RATING_LEVEL_NONE) {
108                 // UNRATED contents should be blocked unless the rating level is none or custom
109                 mRatings.add(TvContentRating.UNRATED);
110             }
111             storeRatings();
112         }
113     }
114 
setContentRatingLevel( ContentRatingsManager manager, @ContentRatingLevel int level)115     public void setContentRatingLevel(
116             ContentRatingsManager manager, @ContentRatingLevel int level) {
117         @ContentRatingLevel int currentLevel = getContentRatingLevel();
118         if (level == currentLevel) {
119             return;
120         }
121         if (currentLevel == TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
122             mCustomRatings = mRatings;
123         }
124         TvSettings.setContentRatingLevel(mContext, level);
125         if (level == TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
126             if (mCustomRatings != null) {
127                 mRatings = new HashSet<>(mCustomRatings);
128             }
129         } else {
130             mRatings = ContentRatingLevelPolicy.getRatingsForLevel(this, manager, level);
131             if (level != TvSettings.CONTENT_RATING_LEVEL_NONE
132                     && Boolean.TRUE.equals(Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get())) {
133                 // UNRATED contents should be blocked unless the rating level is none or custom
134                 mRatings.add(TvContentRating.UNRATED);
135             }
136         }
137         storeRatings();
138     }
139 
140     @ContentRatingLevel
getContentRatingLevel()141     public int getContentRatingLevel() {
142         return TvSettings.getContentRatingLevel(mContext);
143     }
144 
145     /** Sets the blocked status of a unrated contents. */
setUnratedBlocked(boolean blocked)146     public boolean setUnratedBlocked(boolean blocked) {
147         boolean changed;
148         if (blocked) {
149             changed = mRatings.add(TvContentRating.UNRATED);
150             mTvInputManager.addBlockedRating(TvContentRating.UNRATED);
151         } else {
152             changed = mRatings.remove(TvContentRating.UNRATED);
153             mTvInputManager.removeBlockedRating(TvContentRating.UNRATED);
154         }
155         if (changed) {
156             // change to custom level if the blocked status is changed
157             changeToCustomLevel();
158         }
159         return changed;
160     }
161 
162     /**
163      * Sets the blocked status of a given content rating.
164      *
165      * <p>Note that a call to this method automatically changes the current rating level to {@code
166      * TvSettings.CONTENT_RATING_LEVEL_CUSTOM} if needed.
167      *
168      * @param contentRatingSystem The content rating system where the given rating belongs.
169      * @param rating The content rating to set.
170      * @return {@code true} if changed, {@code false} otherwise.
171      * @see #setSubRatingBlocked
172      */
setRatingBlocked( ContentRatingSystem contentRatingSystem, Rating rating, boolean blocked)173     public boolean setRatingBlocked(
174             ContentRatingSystem contentRatingSystem, Rating rating, boolean blocked) {
175         return setRatingBlockedInternal(contentRatingSystem, rating, null, blocked);
176     }
177 
178     /**
179      * Checks whether any of given ratings is blocked.
180      *
181      * @param ratings The array of ratings to check
182      * @return {@code true} if a rating is blocked, {@code false} otherwise.
183      */
isRatingBlocked(TvContentRating[] ratings)184     public boolean isRatingBlocked(TvContentRating[] ratings) {
185         return getBlockedRating(ratings) != null;
186     }
187 
188     /**
189      * Checks whether any of given ratings is blocked and returns the first blocked rating.
190      *
191      * @param ratings The array of ratings to check
192      * @return The {@link TvContentRating} that is blocked.
193      */
getBlockedRating(TvContentRating[] ratings)194     public TvContentRating getBlockedRating(TvContentRating[] ratings) {
195         if (ratings == null || ratings.length <= 0) {
196             return mTvInputManager.isRatingBlocked(TvContentRating.UNRATED)
197                     ? TvContentRating.UNRATED
198                     : null;
199         }
200         for (TvContentRating rating : ratings) {
201             if (mTvInputManager.isRatingBlocked(rating)) {
202                 return rating;
203             }
204         }
205         return null;
206     }
207 
208     /**
209      * Checks whether a given rating is blocked by the user or not.
210      *
211      * @param contentRatingSystem The content rating system where the given rating belongs.
212      * @param rating The content rating to check.
213      * @return {@code true} if blocked, {@code false} otherwise.
214      */
isRatingBlocked(ContentRatingSystem contentRatingSystem, Rating rating)215     public boolean isRatingBlocked(ContentRatingSystem contentRatingSystem, Rating rating) {
216         return mRatings.contains(toTvContentRating(contentRatingSystem, rating));
217     }
218 
219     /**
220      * Sets the blocked status of a given content sub-rating.
221      *
222      * <p>Note that a call to this method automatically changes the current rating level to {@code
223      * TvSettings.CONTENT_RATING_LEVEL_CUSTOM} if needed.
224      *
225      * @param contentRatingSystem The content rating system where the given rating belongs.
226      * @param rating The content rating associated with the given sub-rating.
227      * @param subRating The content sub-rating to set.
228      * @return {@code true} if changed, {@code false} otherwise.
229      * @see #setRatingBlocked
230      */
setSubRatingBlocked( ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating, boolean blocked)231     public boolean setSubRatingBlocked(
232             ContentRatingSystem contentRatingSystem,
233             Rating rating,
234             SubRating subRating,
235             boolean blocked) {
236         return setRatingBlockedInternal(contentRatingSystem, rating, subRating, blocked);
237     }
238 
239     /**
240      * Checks whether a given content sub-rating is blocked by the user or not.
241      *
242      * @param contentRatingSystem The content rating system where the given rating belongs.
243      * @param rating The content rating associated with the given sub-rating.
244      * @param subRating The content sub-rating to check.
245      * @return {@code true} if blocked, {@code false} otherwise.
246      */
isSubRatingEnabled( ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating)247     public boolean isSubRatingEnabled(
248             ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating) {
249         return mRatings.contains(toTvContentRating(contentRatingSystem, rating, subRating));
250     }
251 
setRatingBlockedInternal( ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating, boolean blocked)252     private boolean setRatingBlockedInternal(
253             ContentRatingSystem contentRatingSystem,
254             Rating rating,
255             SubRating subRating,
256             boolean blocked) {
257         TvContentRating tvContentRating =
258                 (subRating == null)
259                         ? toTvContentRating(contentRatingSystem, rating)
260                         : toTvContentRating(contentRatingSystem, rating, subRating);
261         boolean changed;
262         if (blocked) {
263             changed = mRatings.add(tvContentRating);
264             mTvInputManager.addBlockedRating(tvContentRating);
265         } else {
266             changed = mRatings.remove(tvContentRating);
267             mTvInputManager.removeBlockedRating(tvContentRating);
268         }
269         if (changed) {
270             changeToCustomLevel();
271         }
272         return changed;
273     }
274 
changeToCustomLevel()275     private void changeToCustomLevel() {
276         if (getContentRatingLevel() != TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
277             TvSettings.setContentRatingLevel(mContext, TvSettings.CONTENT_RATING_LEVEL_CUSTOM);
278         }
279     }
280 
281     /**
282      * Returns the blocked status of a given rating. The status can be one of the followings: {@link
283      * #RATING_BLOCKED}, {@link #RATING_BLOCKED_PARTIAL} and {@link #RATING_NOT_BLOCKED}
284      */
getBlockedStatus(ContentRatingSystem contentRatingSystem, Rating rating)285     public int getBlockedStatus(ContentRatingSystem contentRatingSystem, Rating rating) {
286         if (isRatingBlocked(contentRatingSystem, rating)) {
287             return RATING_BLOCKED;
288         }
289         for (SubRating subRating : rating.getSubRatings()) {
290             if (isSubRatingEnabled(contentRatingSystem, rating, subRating)) {
291                 return RATING_BLOCKED_PARTIAL;
292             }
293         }
294         return RATING_NOT_BLOCKED;
295     }
296 
toTvContentRating( ContentRatingSystem contentRatingSystem, Rating rating)297     private TvContentRating toTvContentRating(
298             ContentRatingSystem contentRatingSystem, Rating rating) {
299         return TvContentRating.createRating(
300                 contentRatingSystem.getDomain(), contentRatingSystem.getName(), rating.getName());
301     }
302 
toTvContentRating( ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating)303     private TvContentRating toTvContentRating(
304             ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating) {
305         return TvContentRating.createRating(
306                 contentRatingSystem.getDomain(),
307                 contentRatingSystem.getName(),
308                 rating.getName(),
309                 subRating.getName());
310     }
311 }
312