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.util;
18
19import android.content.Context;
20import android.preference.PreferenceManager;
21import android.support.annotation.IntDef;
22
23import java.lang.annotation.Retention;
24import java.lang.annotation.RetentionPolicy;
25import java.util.Collections;
26import java.util.HashSet;
27import java.util.Set;
28
29
30/**
31 * A class about the constants for TV settings.
32 * Objects that are returned from the various {@code get} methods must be treated as immutable.
33 */
34public final class TvSettings {
35    private TvSettings() {}
36
37    public static final String PREFS_FILE = "settings";
38    public static final String PREF_TV_WATCH_LOGGING_ENABLED = "tv_watch_logging_enabled";
39    public static final String PREF_CLOSED_CAPTION_ENABLED = "is_cc_enabled";  // boolean value
40    public static final String PREF_DISPLAY_MODE = "display_mode";  // int value
41    public static final String PREF_PIP_LAYOUT = "pip_layout"; // int value
42    public static final String PREF_PIP_SIZE = "pip_size";  // int value
43    public static final String PREF_PIN = "pin"; // 4-digit string value. Otherwise, it's not set.
44
45    // PIP sounds
46    @Retention(RetentionPolicy.SOURCE)
47    @IntDef({
48            PIP_SOUND_MAIN, PIP_SOUND_PIP_WINDOW })
49    public @interface PipSound {}
50    public static final int PIP_SOUND_MAIN = 0;
51    public static final int PIP_SOUND_PIP_WINDOW = PIP_SOUND_MAIN + 1;
52    public static final int PIP_SOUND_LAST = PIP_SOUND_PIP_WINDOW;
53
54    // PIP layouts
55    @Retention(RetentionPolicy.SOURCE)
56    @IntDef({
57            PIP_LAYOUT_BOTTOM_RIGHT, PIP_LAYOUT_TOP_RIGHT, PIP_LAYOUT_TOP_LEFT,
58            PIP_LAYOUT_BOTTOM_LEFT, PIP_LAYOUT_SIDE_BY_SIDE })
59    public @interface PipLayout {}
60    public static final int PIP_LAYOUT_BOTTOM_RIGHT = 0;
61    public static final int PIP_LAYOUT_TOP_RIGHT = PIP_LAYOUT_BOTTOM_RIGHT + 1;
62    public static final int PIP_LAYOUT_TOP_LEFT = PIP_LAYOUT_TOP_RIGHT + 1;
63    public static final int PIP_LAYOUT_BOTTOM_LEFT = PIP_LAYOUT_TOP_LEFT + 1;
64    public static final int PIP_LAYOUT_SIDE_BY_SIDE = PIP_LAYOUT_BOTTOM_LEFT + 1;
65    public static final int PIP_LAYOUT_LAST = PIP_LAYOUT_SIDE_BY_SIDE;
66
67    // PIP sizes
68    @Retention(RetentionPolicy.SOURCE)
69    @IntDef({ PIP_SIZE_SMALL, PIP_SIZE_BIG })
70    public @interface PipSize {}
71    public static final int PIP_SIZE_SMALL = 0;
72    public static final int PIP_SIZE_BIG = PIP_SIZE_SMALL + 1;
73    public static final int PIP_SIZE_LAST = PIP_SIZE_BIG;
74
75    // Multi-track audio settings
76    private static final String PREF_MULTI_AUDIO_ID = "pref.multi_audio_id";
77    private static final String PREF_MULTI_AUDIO_LANGUAGE = "pref.multi_audio_language";
78    private static final String PREF_MULTI_AUDIO_CHANNEL_COUNT = "pref.multi_audio_channel_count";
79
80    // Parental Control settings
81    private static final String PREF_CONTENT_RATING_SYSTEMS = "pref.content_rating_systems";
82    private static final String PREF_CONTENT_RATING_LEVEL = "pref.content_rating_level";
83    private static final String PREF_DISABLE_PIN_UNTIL = "pref.disable_pin_until";
84
85    @Retention(RetentionPolicy.SOURCE)
86    @IntDef({
87            CONTENT_RATING_LEVEL_NONE, CONTENT_RATING_LEVEL_HIGH, CONTENT_RATING_LEVEL_MEDIUM,
88            CONTENT_RATING_LEVEL_LOW, CONTENT_RATING_LEVEL_CUSTOM })
89    public @interface ContentRatingLevel {}
90    public static final int CONTENT_RATING_LEVEL_NONE = 0;
91    public static final int CONTENT_RATING_LEVEL_HIGH = 1;
92    public static final int CONTENT_RATING_LEVEL_MEDIUM = 2;
93    public static final int CONTENT_RATING_LEVEL_LOW = 3;
94    public static final int CONTENT_RATING_LEVEL_CUSTOM = 4;
95
96    // PIP settings
97    /**
98     * Returns the layout of the PIP window stored in the shared preferences.
99     *
100     * @return the saved layout of the PIP window. This value is one of
101     *         {@link #PIP_LAYOUT_TOP_LEFT}, {@link #PIP_LAYOUT_TOP_RIGHT},
102     *         {@link #PIP_LAYOUT_BOTTOM_LEFT}, {@link #PIP_LAYOUT_BOTTOM_RIGHT} and
103     *         {@link #PIP_LAYOUT_SIDE_BY_SIDE}. If the preference value does not exist,
104     *         {@link #PIP_LAYOUT_BOTTOM_RIGHT} is returned.
105     */
106    @SuppressWarnings("ResourceType")
107    @PipLayout
108    public static int getPipLayout(Context context) {
109        return PreferenceManager.getDefaultSharedPreferences(context).getInt(
110                PREF_PIP_LAYOUT, PIP_LAYOUT_BOTTOM_RIGHT);
111    }
112
113    /**
114     * Stores the layout of PIP window to the shared preferences.
115     *
116     * @param pipLayout This value should be one of {@link #PIP_LAYOUT_TOP_LEFT},
117     *            {@link #PIP_LAYOUT_TOP_RIGHT}, {@link #PIP_LAYOUT_BOTTOM_LEFT},
118     *            {@link #PIP_LAYOUT_BOTTOM_RIGHT} and {@link #PIP_LAYOUT_SIDE_BY_SIDE}.
119     */
120    public static void setPipLayout(Context context, @PipLayout int pipLayout) {
121        PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(
122                PREF_PIP_LAYOUT, pipLayout).apply();
123    }
124
125    /**
126     * Returns the size of the PIP view stored in the shared preferences.
127     *
128     * @return the saved size of the PIP view. This value is one of
129     *         {@link #PIP_SIZE_SMALL} and {@link #PIP_SIZE_BIG}. If the preference value does not
130     *         exist, {@link #PIP_SIZE_SMALL} is returned.
131     */
132    @SuppressWarnings("ResourceType")
133    @PipSize
134    public static int getPipSize(Context context) {
135        return PreferenceManager.getDefaultSharedPreferences(context).getInt(
136                PREF_PIP_SIZE, PIP_SIZE_SMALL);
137    }
138
139    /**
140     * Stores the size of PIP view to the shared preferences.
141     *
142     * @param pipSize This value should be one of {@link #PIP_SIZE_SMALL} and {@link #PIP_SIZE_BIG}.
143     */
144    public static void setPipSize(Context context, @PipSize int pipSize) {
145        PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(
146                PREF_PIP_SIZE, pipSize).apply();
147    }
148
149    // Multi-track audio settings
150    public static String getMultiAudioId(Context context) {
151        return PreferenceManager.getDefaultSharedPreferences(context).getString(
152                PREF_MULTI_AUDIO_ID, null);
153    }
154
155    public static void setMultiAudioId(Context context, String language) {
156        PreferenceManager.getDefaultSharedPreferences(context).edit().putString(
157                PREF_MULTI_AUDIO_ID, language).apply();
158    }
159
160    public static String getMultiAudioLanguage(Context context) {
161        return PreferenceManager.getDefaultSharedPreferences(context).getString(
162                PREF_MULTI_AUDIO_LANGUAGE, null);
163    }
164
165    public static void setMultiAudioLanguage(Context context, String language) {
166        PreferenceManager.getDefaultSharedPreferences(context).edit().putString(
167                PREF_MULTI_AUDIO_LANGUAGE, language).apply();
168    }
169
170    public static int getMultiAudioChannelCount(Context context) {
171        return PreferenceManager.getDefaultSharedPreferences(context).getInt(
172                PREF_MULTI_AUDIO_CHANNEL_COUNT, 0);
173    }
174
175    public static void setMultiAudioChannelCount(Context context, int channelCount) {
176        PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(
177                PREF_MULTI_AUDIO_CHANNEL_COUNT, channelCount).apply();
178    }
179
180    // Parental Control settings
181    public static void addContentRatingSystems(Context context, Set<String> ids) {
182        Set<String> contentRatingSystemSet = getContentRatingSystemSet(context);
183        if (contentRatingSystemSet.addAll(ids)) {
184            PreferenceManager.getDefaultSharedPreferences(context).edit()
185                    .putStringSet(PREF_CONTENT_RATING_SYSTEMS, contentRatingSystemSet).apply();
186        }
187    }
188
189    public static void addContentRatingSystem(Context context, String id) {
190        Set<String> contentRatingSystemSet = getContentRatingSystemSet(context);
191        if (contentRatingSystemSet.add(id)) {
192            PreferenceManager.getDefaultSharedPreferences(context).edit()
193                    .putStringSet(PREF_CONTENT_RATING_SYSTEMS, contentRatingSystemSet).apply();
194        }
195    }
196
197    public static void removeContentRatingSystems(Context context, Set<String> ids) {
198        Set<String> contentRatingSystemSet = getContentRatingSystemSet(context);
199        if (contentRatingSystemSet.removeAll(ids)) {
200            PreferenceManager.getDefaultSharedPreferences(context).edit()
201                    .putStringSet(PREF_CONTENT_RATING_SYSTEMS, contentRatingSystemSet).apply();
202        }
203    }
204
205    public static void removeContentRatingSystem(Context context, String id) {
206        Set<String> contentRatingSystemSet = getContentRatingSystemSet(context);
207        if (contentRatingSystemSet.remove(id)) {
208            PreferenceManager.getDefaultSharedPreferences(context).edit()
209                    .putStringSet(PREF_CONTENT_RATING_SYSTEMS, contentRatingSystemSet).apply();
210        }
211    }
212
213    public static boolean hasContentRatingSystem(Context context, String id) {
214        return getContentRatingSystemSet(context).contains(id);
215    }
216
217    /**
218     * Returns whether the content rating system is ever set. Returns {@code false} only when the
219     * user changes parental control settings for the first time.
220     */
221    public static boolean isContentRatingSystemSet(Context context) {
222        return PreferenceManager.getDefaultSharedPreferences(context)
223                .getStringSet(PREF_CONTENT_RATING_SYSTEMS, null) != null;
224    }
225
226    private static Set<String> getContentRatingSystemSet(Context context) {
227        return new HashSet<>(PreferenceManager.getDefaultSharedPreferences(context)
228                .getStringSet(PREF_CONTENT_RATING_SYSTEMS, Collections.<String>emptySet()));
229    }
230
231    @ContentRatingLevel
232    @SuppressWarnings("ResourceType")
233    public static int getContentRatingLevel(Context context) {
234        return PreferenceManager.getDefaultSharedPreferences(context).getInt(
235                PREF_CONTENT_RATING_LEVEL, CONTENT_RATING_LEVEL_NONE);
236    }
237
238    public static void setContentRatingLevel(Context context,
239            @ContentRatingLevel int level) {
240        PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(
241                PREF_CONTENT_RATING_LEVEL, level).apply();
242    }
243
244    /**
245     * Returns the time until we should disable the PIN dialog (because the user input wrong PINs
246     * repeatedly).
247     */
248    public static long getDisablePinUntil(Context context) {
249        return PreferenceManager.getDefaultSharedPreferences(context).getLong(
250                PREF_DISABLE_PIN_UNTIL, 0);
251    }
252
253    /**
254     * Saves the time until we should disable the PIN dialog (because the user input wrong PINs
255     * repeatedly).
256     */
257    public static void setDisablePinUntil(Context context, long timeMillis) {
258        PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(
259                PREF_DISABLE_PIN_UNTIL, timeMillis).apply();
260    }
261}
262