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