1 /*
2  * Copyright (C) 2016 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.settings.system;
18 
19 import static com.android.tv.settings.util.InstrumentationUtils.logEntrySelected;
20 import static com.android.tv.settings.util.InstrumentationUtils.logToggleInteracted;
21 
22 import android.app.tvsettings.TvSettingsEnums;
23 import android.content.Intent;
24 import android.os.Bundle;
25 import android.provider.Settings;
26 import android.text.TextUtils;
27 
28 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
29 import androidx.preference.ListPreference;
30 import androidx.preference.Preference;
31 import androidx.preference.PreferenceGroup;
32 import androidx.preference.TwoStatePreference;
33 
34 import com.android.internal.app.LocalePicker;
35 import com.android.internal.logging.nano.MetricsProto;
36 import com.android.tv.settings.R;
37 import com.android.tv.settings.RadioPreference;
38 import com.android.tv.settings.SettingsPreferenceFragment;
39 
40 import java.util.List;
41 
42 /**
43  * The "Captions" screen in TV settings.
44  */
45 public class CaptionFragment extends SettingsPreferenceFragment implements
46         Preference.OnPreferenceChangeListener {
47 
48     private static final String KEY_CAPTIONS_DISPLAY = "captions_display";
49     private static final String KEY_CAPTIONS_LANGUAGE = "captions_language";
50     private static final String KEY_CAPTIONS_TEXT_SIZE = "captions_text_size";
51     private static final String KEY_CAPTIONS_STYLE_GROUP = "captions_style";
52     private static final String KEY_CAPTIONS_STYLE_0 = "captions_style_0";
53     private static final String KEY_CAPTIONS_STYLE_1 = "captions_style_1";
54     private static final String KEY_CAPTIONS_STYLE_2 = "captions_style_2";
55     private static final String KEY_CAPTIONS_STYLE_3 = "captions_style_3";
56     private static final String KEY_CAPTIONS_STYLE_CUSTOM = "captions_style_custom";
57 
58     private TwoStatePreference mCaptionsDisplayPref;
59     private ListPreference mCaptionsLanguagePref;
60     private ListPreference mCaptionsTextSizePref;
61     private PreferenceGroup mCaptionsStyleGroup;
62     private RadioPreference mCaptionsStyle0Pref;
63     private RadioPreference mCaptionsStyle1Pref;
64     private RadioPreference mCaptionsStyle2Pref;
65     private RadioPreference mCaptionsStyle3Pref;
66     private RadioPreference mCaptionsStyleCustomPref;
67 
newInstance()68     public static CaptionFragment newInstance() {
69         return new CaptionFragment();
70     }
71 
72     @Override
onResume()73     public void onResume() {
74         super.onResume();
75         refresh();
76     }
77 
78     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)79     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
80         setPreferencesFromResource(R.xml.caption, null);
81 
82         mCaptionsDisplayPref = (TwoStatePreference) findPreference(KEY_CAPTIONS_DISPLAY);
83 
84         final List<LocalePicker.LocaleInfo> localeInfoList =
85                 LocalePicker.getAllAssetLocales(getContext(), false);
86         final String[] langNames = new String[localeInfoList.size() + 1];
87         final String[] langLocales = new String[localeInfoList.size() + 1];
88         langNames[0] = getString(R.string.captions_language_default);
89         langLocales[0] = "";
90         int i = 1;
91         for (final LocalePicker.LocaleInfo info : localeInfoList) {
92             langNames[i] = info.toString();
93             langLocales[i] = info.getLocale().toString();
94             i++;
95         }
96         mCaptionsLanguagePref = (ListPreference) findPreference(KEY_CAPTIONS_LANGUAGE);
97         mCaptionsLanguagePref.setEntries(langNames);
98         mCaptionsLanguagePref.setEntryValues(langLocales);
99         mCaptionsLanguagePref.setOnPreferenceChangeListener(this);
100 
101         mCaptionsTextSizePref = (ListPreference) findPreference(KEY_CAPTIONS_TEXT_SIZE);
102         mCaptionsTextSizePref.setOnPreferenceChangeListener(this);
103 
104         mCaptionsStyleGroup = (PreferenceGroup) findPreference(KEY_CAPTIONS_STYLE_GROUP);
105 
106         mCaptionsStyle0Pref = (RadioPreference) findPreference(KEY_CAPTIONS_STYLE_0);
107         mCaptionsStyle1Pref = (RadioPreference) findPreference(KEY_CAPTIONS_STYLE_1);
108         mCaptionsStyle2Pref = (RadioPreference) findPreference(KEY_CAPTIONS_STYLE_2);
109         mCaptionsStyle3Pref = (RadioPreference) findPreference(KEY_CAPTIONS_STYLE_3);
110         mCaptionsStyleCustomPref = (RadioPreference) findPreference(KEY_CAPTIONS_STYLE_CUSTOM);
111     }
112 
113     @Override
onPreferenceTreeClick(Preference preference)114     public boolean onPreferenceTreeClick(Preference preference) {
115         final String key = preference.getKey();
116         if (TextUtils.isEmpty(key)) {
117             return super.onPreferenceTreeClick(preference);
118         }
119         switch (key) {
120             case KEY_CAPTIONS_DISPLAY:
121                 logToggleInteracted(
122                         TvSettingsEnums.SYSTEM_A11Y_CAPTIONS_DISPLAY_ON_OFF,
123                         ((TwoStatePreference) preference).isChecked());
124                 setCaptionsEnabled(((TwoStatePreference) preference).isChecked());
125                 return true;
126             case KEY_CAPTIONS_LANGUAGE:
127                 logEntrySelected(TvSettingsEnums.SYSTEM_A11Y_CAPTIONS_LANGUAGE);
128                 return super.onPreferenceTreeClick(preference);
129             case KEY_CAPTIONS_TEXT_SIZE:
130                 logEntrySelected(TvSettingsEnums.SYSTEM_A11Y_CAPTIONS_TEXT_SIZE);
131                 return super.onPreferenceTreeClick(preference);
132             case KEY_CAPTIONS_STYLE_0:
133                 logEntrySelected(TvSettingsEnums.SYSTEM_A11Y_CAPTIONS_WHITE_ON_BLACK);
134                 setCaptionsStyle(0);
135                 mCaptionsStyle0Pref.setChecked(true);
136                 mCaptionsStyle0Pref.clearOtherRadioPreferences(mCaptionsStyleGroup);
137                 return true;
138             case KEY_CAPTIONS_STYLE_1:
139                 logEntrySelected(TvSettingsEnums.SYSTEM_A11Y_CAPTIONS_BLACK_ON_WHITE);
140                 setCaptionsStyle(1);
141                 mCaptionsStyle1Pref.setChecked(true);
142                 mCaptionsStyle1Pref.clearOtherRadioPreferences(mCaptionsStyleGroup);
143                 return true;
144             case KEY_CAPTIONS_STYLE_2:
145                 logEntrySelected(TvSettingsEnums.SYSTEM_A11Y_CAPTIONS_YELLOW_ON_BLACK);
146                 setCaptionsStyle(2);
147                 mCaptionsStyle2Pref.setChecked(true);
148                 mCaptionsStyle2Pref.clearOtherRadioPreferences(mCaptionsStyleGroup);
149                 return true;
150             case KEY_CAPTIONS_STYLE_3:
151                 logEntrySelected(TvSettingsEnums.SYSTEM_A11Y_CAPTIONS_YELLOW_ON_BLUE);
152                 setCaptionsStyle(3);
153                 mCaptionsStyle3Pref.setChecked(true);
154                 mCaptionsStyle3Pref.clearOtherRadioPreferences(mCaptionsStyleGroup);
155                 return true;
156             case KEY_CAPTIONS_STYLE_CUSTOM:
157                 logEntrySelected(TvSettingsEnums.SYSTEM_A11Y_CAPTIONS_CUSTOM);
158                 setCaptionsStyle(-1);
159                 mCaptionsStyleCustomPref.setChecked(true);
160                 mCaptionsStyleCustomPref.clearOtherRadioPreferences(mCaptionsStyleGroup);
161                 // Call to super to show custom configuration screen
162                 return super.onPreferenceTreeClick(preference);
163         }
164         return super.onPreferenceTreeClick(preference);
165     }
166 
167     @Override
onPreferenceChange(Preference preference, Object newValue)168     public boolean onPreferenceChange(Preference preference, Object newValue) {
169         final String key = preference.getKey();
170         if (TextUtils.isEmpty(key)) {
171             throw new IllegalStateException("Unknown preference change");
172         }
173         switch (key) {
174             case KEY_CAPTIONS_LANGUAGE:
175                 setCaptionsLocale((String) newValue);
176                 break;
177             case KEY_CAPTIONS_TEXT_SIZE:
178                 setCaptionsTextSize((String) newValue);
179                 break;
180             default:
181                 throw new IllegalStateException("Preference change with unknown key " + key);
182         }
183         return true;
184     }
185 
refresh()186     private void refresh() {
187         mCaptionsDisplayPref.setChecked(getCaptionsEnabled());
188         mCaptionsLanguagePref.setValue(getCaptionsLocale());
189         mCaptionsTextSizePref.setValue(getCaptionsTextSize());
190         switch (getCaptionsStyle()) {
191             default:
192             case 0:
193                 mCaptionsStyle0Pref.setChecked(true);
194                 mCaptionsStyle0Pref.clearOtherRadioPreferences(mCaptionsStyleGroup);
195                 break;
196             case 1:
197                 mCaptionsStyle1Pref.setChecked(true);
198                 mCaptionsStyle1Pref.clearOtherRadioPreferences(mCaptionsStyleGroup);
199                 break;
200             case 2:
201                 mCaptionsStyle2Pref.setChecked(true);
202                 mCaptionsStyle2Pref.clearOtherRadioPreferences(mCaptionsStyleGroup);
203                 break;
204             case 3:
205                 mCaptionsStyle3Pref.setChecked(true);
206                 mCaptionsStyle3Pref.clearOtherRadioPreferences(mCaptionsStyleGroup);
207                 break;
208             case -1:
209                 mCaptionsStyleCustomPref.setChecked(true);
210                 mCaptionsStyleCustomPref.clearOtherRadioPreferences(mCaptionsStyleGroup);
211                 break;
212         }
213     }
214 
getCaptionsEnabled()215     private boolean getCaptionsEnabled() {
216         return Settings.Secure.getInt(getContext().getContentResolver(),
217             Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, 0) != 0;
218     }
219 
setCaptionsEnabled(boolean enabled)220     private void setCaptionsEnabled(boolean enabled) {
221         Settings.Secure.putInt(getContext().getContentResolver(),
222                 Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, enabled ? 1 : 0);
223     }
224 
getCaptionsStyle()225     private int getCaptionsStyle() {
226         return Settings.Secure.getInt(getContext().getContentResolver(),
227                 Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET, 0);
228     }
229 
setCaptionsStyle(int style)230     private void setCaptionsStyle(int style) {
231         Settings.Secure.putInt(getContext().getContentResolver(),
232                 Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET, style);
233         LocalBroadcastManager.getInstance(getContext())
234                 .sendBroadcast(new Intent(CaptionSettingsFragment.ACTION_REFRESH_CAPTIONS_PREVIEW));
235     }
236 
getCaptionsLocale()237     private String getCaptionsLocale() {
238         final String captionLocale = Settings.Secure.getString(getContext().getContentResolver(),
239                 Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
240         return captionLocale == null ? "" : captionLocale;
241     }
242 
setCaptionsLocale(String locale)243     private void setCaptionsLocale(String locale) {
244         Settings.Secure.putString(getContext().getContentResolver(),
245                 Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE, locale);
246     }
247 
getCaptionsTextSize()248     private String getCaptionsTextSize() {
249         final float textSize = Settings.Secure.getFloat(getContext().getContentResolver(),
250                 Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, 1);
251 
252         if (0 <= textSize && textSize < .375) {
253             return "0.25";
254         } else if (textSize < .75) {
255             return "0.5";
256         } else if (textSize < 1.25) {
257             return "1.0";
258         } else if (textSize < 1.75) {
259             return "1.5";
260         } else if (textSize < 2.5) {
261             return "2.0";
262         }
263 
264         return "1.0";
265     }
266 
setCaptionsTextSize(String textSize)267     private void setCaptionsTextSize(String textSize) {
268         Settings.Secure.putFloat(getContext().getContentResolver(),
269                 Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, Float.parseFloat(textSize));
270     }
271 
272     @Override
getMetricsCategory()273     public int getMetricsCategory() {
274         return MetricsProto.MetricsEvent.ACCESSIBILITY_CAPTION_PROPERTIES;
275     }
276 
277     @Override
getPageId()278     protected int getPageId() {
279         return TvSettingsEnums.SYSTEM_A11Y_CAPTIONS;
280     }
281 }
282