ParentalControlSettings.java revision 38fef3bf253578f518d1bc727da4afb263194398
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 17package com.android.tv.parental; 18 19import android.content.Context; 20import android.media.tv.TvContentRating; 21import android.media.tv.TvInputManager; 22import com.android.tv.experiments.Experiments; 23import com.android.tv.parental.ContentRatingSystem.Rating; 24import com.android.tv.parental.ContentRatingSystem.SubRating; 25import com.android.tv.util.TvSettings; 26import com.android.tv.util.TvSettings.ContentRatingLevel; 27import java.util.HashSet; 28import java.util.Set; 29 30public 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 47 public ParentalControlSettings(Context context) { 48 mContext = context; 49 mTvInputManager = (TvInputManager) mContext.getSystemService(Context.TV_INPUT_SERVICE); 50 } 51 52 public boolean isParentalControlsEnabled() { 53 return mTvInputManager.isParentalControlsEnabled(); 54 } 55 56 public void setParentalControlsEnabled(boolean enabled) { 57 mTvInputManager.setParentalControlsEnabled(enabled); 58 } 59 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 81 public boolean isContentRatingSystemEnabled(ContentRatingSystem contentRatingSystem) { 82 return TvSettings.hasContentRatingSystem(mContext, contentRatingSystem.getId()); 83 } 84 85 public void loadRatings() { 86 mRatings = new HashSet<>(mTvInputManager.getBlockedRatings()); 87 } 88 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 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 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 141 public int getContentRatingLevel() { 142 return TvSettings.getContentRatingLevel(mContext); 143 } 144 145 /** Sets the blocked status of a unrated contents. */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 247 public boolean isSubRatingEnabled( 248 ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating) { 249 return mRatings.contains(toTvContentRating(contentRatingSystem, rating, subRating)); 250 } 251 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 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 */ 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 297 private TvContentRating toTvContentRating( 298 ContentRatingSystem contentRatingSystem, Rating rating) { 299 return TvContentRating.createRating( 300 contentRatingSystem.getDomain(), contentRatingSystem.getName(), rating.getName()); 301 } 302 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