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