blob: 9990ae358d932a4aecde8df961620d86c7a8e2c7 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tv.parental;
import android.content.Context;
import android.media.tv.TvContentRating;
import android.media.tv.TvInputManager;
import com.android.tv.parental.ContentRatingSystem.Rating;
import com.android.tv.parental.ContentRatingSystem.SubRating;
import com.android.tv.util.TvSettings;
import com.android.tv.util.TvSettings.ContentRatingLevel;
import com.google.common.collect.ImmutableList;
import com.android.tv.common.flags.LegacyFlags;
import java.util.HashSet;
import java.util.Set;
public class ParentalControlSettings {
/** The rating and all of its sub-ratings are blocked. */
public static final int RATING_BLOCKED = 0;
/** The rating is blocked but not all of its sub-ratings are blocked. */
public static final int RATING_BLOCKED_PARTIAL = 1;
/** The rating is not blocked. */
public static final int RATING_NOT_BLOCKED = 2;
private final Context mContext;
private final TvInputManager mTvInputManager;
private final LegacyFlags mLegacyFlags;
// mRatings is expected to be synchronized with mTvInputManager.getBlockedRatings().
private Set<TvContentRating> mRatings;
private Set<TvContentRating> mCustomRatings;
public ParentalControlSettings(Context context, LegacyFlags legacyFlags) {
mContext = context;
mTvInputManager = (TvInputManager) mContext.getSystemService(Context.TV_INPUT_SERVICE);
mLegacyFlags = legacyFlags;
}
public boolean isParentalControlsEnabled() {
return mTvInputManager.isParentalControlsEnabled();
}
public void setParentalControlsEnabled(boolean enabled) {
mTvInputManager.setParentalControlsEnabled(enabled);
}
public void setContentRatingSystemEnabled(
ContentRatingsManager manager,
ContentRatingSystem contentRatingSystem,
boolean enabled) {
if (enabled) {
TvSettings.addContentRatingSystem(mContext, contentRatingSystem.getId());
// Ensure newly added system has ratings for current level set
updateRatingsForCurrentLevel(manager);
} else {
// Ensure no ratings are blocked for the selected rating system
for (TvContentRating tvContentRating : mTvInputManager.getBlockedRatings()) {
if (contentRatingSystem.ownsRating(tvContentRating)) {
mTvInputManager.removeBlockedRating(tvContentRating);
}
}
TvSettings.removeContentRatingSystem(mContext, contentRatingSystem.getId());
}
}
public boolean isContentRatingSystemEnabled(ContentRatingSystem contentRatingSystem) {
return TvSettings.hasContentRatingSystem(mContext, contentRatingSystem.getId());
}
public void loadRatings() {
mRatings = new HashSet<>(mTvInputManager.getBlockedRatings());
}
private void storeRatings() {
Set<TvContentRating> removed = new HashSet<>(mTvInputManager.getBlockedRatings());
removed.removeAll(mRatings);
for (TvContentRating tvContentRating : removed) {
mTvInputManager.removeBlockedRating(tvContentRating);
}
Set<TvContentRating> added = new HashSet<>(mRatings);
added.removeAll(mTvInputManager.getBlockedRatings());
for (TvContentRating tvContentRating : added) {
mTvInputManager.addBlockedRating(tvContentRating);
}
}
private void updateRatingsForCurrentLevel(ContentRatingsManager manager) {
@ContentRatingLevel int currentLevel = getContentRatingLevel();
if (currentLevel != TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
mRatings = ContentRatingLevelPolicy.getRatingsForLevel(this, manager, currentLevel);
if (currentLevel != TvSettings.CONTENT_RATING_LEVEL_NONE) {
// UNRATED contents should be blocked unless the rating level is none or custom
mRatings.add(TvContentRating.UNRATED);
}
storeRatings();
}
}
public void setContentRatingLevel(
ContentRatingsManager manager, @ContentRatingLevel int level) {
@ContentRatingLevel int currentLevel = getContentRatingLevel();
if (level == currentLevel) {
return;
}
if (currentLevel == TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
mCustomRatings = mRatings;
}
TvSettings.setContentRatingLevel(mContext, level);
if (level == TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
if (mCustomRatings != null) {
mRatings = new HashSet<>(mCustomRatings);
}
} else {
mRatings = ContentRatingLevelPolicy.getRatingsForLevel(this, manager, level);
if (level != TvSettings.CONTENT_RATING_LEVEL_NONE
&& mLegacyFlags.enableUnratedContentSettings()) {
// UNRATED contents should be blocked unless the rating level is none or custom
mRatings.add(TvContentRating.UNRATED);
}
}
storeRatings();
}
@ContentRatingLevel
public int getContentRatingLevel() {
return TvSettings.getContentRatingLevel(mContext);
}
/** Sets the blocked status of a unrated contents. */
public boolean setUnratedBlocked(boolean blocked) {
boolean changed;
if (blocked) {
changed = mRatings.add(TvContentRating.UNRATED);
mTvInputManager.addBlockedRating(TvContentRating.UNRATED);
} else {
changed = mRatings.remove(TvContentRating.UNRATED);
mTvInputManager.removeBlockedRating(TvContentRating.UNRATED);
}
if (changed) {
// change to custom level if the blocked status is changed
changeToCustomLevel();
}
return changed;
}
/**
* Checks whether any of given ratings is blocked and returns the first blocked rating.
*
* @param ratings The array of ratings to check
* @return The {@link TvContentRating} that is blocked.
*/
public TvContentRating getBlockedRating(ImmutableList<TvContentRating> ratings) {
if (ratings == null || ratings.isEmpty()) {
return mTvInputManager.isRatingBlocked(TvContentRating.UNRATED)
? TvContentRating.UNRATED
: null;
}
for (TvContentRating rating : ratings) {
if (mTvInputManager.isRatingBlocked(rating)) {
return rating;
}
}
return null;
}
/**
* Sets the blocked status of a given content rating.
*
* <p>Note that a call to this method automatically changes the current rating level to {@code
* TvSettings.CONTENT_RATING_LEVEL_CUSTOM} if needed.
*
* @param contentRatingSystem The content rating system where the given rating belongs.
* @param rating The content rating to set.
* @return {@code true} if changed, {@code false} otherwise.
* @see #setSubRatingBlocked
*/
public boolean setRatingBlocked(
ContentRatingSystem contentRatingSystem, Rating rating, boolean blocked) {
return setRatingBlockedInternal(contentRatingSystem, rating, null, blocked);
}
/**
* Checks whether any of given ratings is blocked.
*
* @param ratings The list of ratings to check
* @return {@code true} if a rating is blocked, {@code false} otherwise.
*/
public boolean isRatingBlocked(ImmutableList<TvContentRating> ratings) {
return getBlockedRating(ratings) != null;
}
/**
* Checks whether a given rating is blocked by the user or not.
*
* @param contentRatingSystem The content rating system where the given rating belongs.
* @param rating The content rating to check.
* @return {@code true} if blocked, {@code false} otherwise.
*/
public boolean isRatingBlocked(ContentRatingSystem contentRatingSystem, Rating rating) {
return mRatings.contains(toTvContentRating(contentRatingSystem, rating));
}
/**
* Sets the blocked status of a given content sub-rating.
*
* <p>Note that a call to this method automatically changes the current rating level to {@code
* TvSettings.CONTENT_RATING_LEVEL_CUSTOM} if needed.
*
* @param contentRatingSystem The content rating system where the given rating belongs.
* @param rating The content rating associated with the given sub-rating.
* @param subRating The content sub-rating to set.
* @return {@code true} if changed, {@code false} otherwise.
* @see #setRatingBlocked
*/
public boolean setSubRatingBlocked(
ContentRatingSystem contentRatingSystem,
Rating rating,
SubRating subRating,
boolean blocked) {
return setRatingBlockedInternal(contentRatingSystem, rating, subRating, blocked);
}
/**
* Checks whether a given content sub-rating is blocked by the user or not.
*
* @param contentRatingSystem The content rating system where the given rating belongs.
* @param rating The content rating associated with the given sub-rating.
* @param subRating The content sub-rating to check.
* @return {@code true} if blocked, {@code false} otherwise.
*/
public boolean isSubRatingEnabled(
ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating) {
return mRatings.contains(toTvContentRating(contentRatingSystem, rating, subRating));
}
private boolean setRatingBlockedInternal(
ContentRatingSystem contentRatingSystem,
Rating rating,
SubRating subRating,
boolean blocked) {
TvContentRating tvContentRating =
(subRating == null)
? toTvContentRating(contentRatingSystem, rating)
: toTvContentRating(contentRatingSystem, rating, subRating);
boolean changed;
if (blocked) {
changed = mRatings.add(tvContentRating);
mTvInputManager.addBlockedRating(tvContentRating);
} else {
changed = mRatings.remove(tvContentRating);
mTvInputManager.removeBlockedRating(tvContentRating);
}
if (changed) {
changeToCustomLevel();
}
return changed;
}
private void changeToCustomLevel() {
if (getContentRatingLevel() != TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
TvSettings.setContentRatingLevel(mContext, TvSettings.CONTENT_RATING_LEVEL_CUSTOM);
}
}
/**
* Returns the blocked status of a given rating. The status can be one of the followings: {@link
* #RATING_BLOCKED}, {@link #RATING_BLOCKED_PARTIAL} and {@link #RATING_NOT_BLOCKED}
*/
public int getBlockedStatus(ContentRatingSystem contentRatingSystem, Rating rating) {
if (isRatingBlocked(contentRatingSystem, rating)) {
return RATING_BLOCKED;
}
for (SubRating subRating : rating.getSubRatings()) {
if (isSubRatingEnabled(contentRatingSystem, rating, subRating)) {
return RATING_BLOCKED_PARTIAL;
}
}
return RATING_NOT_BLOCKED;
}
private TvContentRating toTvContentRating(
ContentRatingSystem contentRatingSystem, Rating rating) {
return TvContentRating.createRating(
contentRatingSystem.getDomain(), contentRatingSystem.getName(), rating.getName());
}
private TvContentRating toTvContentRating(
ContentRatingSystem contentRatingSystem, Rating rating, SubRating subRating) {
return TvContentRating.createRating(
contentRatingSystem.getDomain(),
contentRatingSystem.getName(),
rating.getName(),
subRating.getName());
}
}