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 android.content.Context;
20 import android.media.tv.TvInputInfo;
21 import android.os.Bundle;
22 import android.os.UserHandle;
23 import android.text.TextUtils;
24 
25 import androidx.annotation.NonNull;
26 import androidx.preference.Preference;
27 import androidx.preference.PreferenceGroup;
28 import androidx.preference.TwoStatePreference;
29 
30 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
31 import com.android.tv.settings.R;
32 import com.android.tv.settings.RadioPreference;
33 import com.android.tv.settings.SettingsPreferenceFragment;
34 
35 import java.util.Map;
36 import java.util.Set;
37 
38 /**
39  * The screen in TV Settings that shows the options for an input.
40  */
41 public class InputOptionsFragment extends SettingsPreferenceFragment implements
42         InputCustomNameFragment.Callback {
43 
44     private static final String KEY_SHOW_INPUT = "show_input";
45     private static final String KEY_NAMES = "names";
46     private static final String KEY_NAME_DEFAULT = "name_default";
47     private static final String KEY_NAME_CUSTOM = "name_custom";
48 
49     private static final String ARG_INPUT = "input";
50 
51     private TwoStatePreference mShowPref;
52     private PreferenceGroup mNamesGroup;
53     private TwoStatePreference mNameDefaultPref;
54     private TwoStatePreference mNameCustomPref;
55 
56     private Map<String, String> mCustomLabels;
57     private Set<String> mHiddenIds;
58 
59     private TvInputInfo mInputInfo;
60 
prepareArgs(@onNull Bundle args, TvInputInfo inputInfo)61     public static void prepareArgs(@NonNull Bundle args, TvInputInfo inputInfo) {
62         args.putParcelable(ARG_INPUT, inputInfo);
63     }
64 
65     @Override
onCreate(Bundle savedInstanceState)66     public void onCreate(Bundle savedInstanceState) {
67         mInputInfo = getArguments().getParcelable(ARG_INPUT);
68 
69         super.onCreate(savedInstanceState);
70 
71         final Context context = getContext();
72         mCustomLabels =
73                 TvInputInfo.TvInputSettings.getCustomLabels(context, UserHandle.USER_SYSTEM);
74         mHiddenIds =
75                 TvInputInfo.TvInputSettings.getHiddenTvInputIds(context, UserHandle.USER_SYSTEM);
76 
77     }
78 
79     @Override
onResume()80     public void onResume() {
81         super.onResume();
82         refresh();
83     }
84 
85     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)86     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
87         setPreferencesFromResource(R.xml.input_options, null);
88         getPreferenceScreen().setTitle(mInputInfo.loadLabel(getContext()));
89 
90         mShowPref = (TwoStatePreference) findPreference(KEY_SHOW_INPUT);
91 
92         mNamesGroup = (PreferenceGroup) findPreference(KEY_NAMES);
93 
94         mNameDefaultPref = (TwoStatePreference) findPreference(KEY_NAME_DEFAULT);
95         mNameCustomPref = (TwoStatePreference) findPreference(KEY_NAME_CUSTOM);
96 
97     }
98 
refresh()99     private void refresh() {
100 
101         mShowPref.setChecked(!mHiddenIds.contains(mInputInfo.getId()));
102 
103         final CharSequence defaultLabel = mInputInfo.loadLabel(getContext());
104         final CharSequence customLabel = mCustomLabels.get(mInputInfo.getId());
105 
106         boolean nameMatched = false;
107         for (int i = 0; i < mNamesGroup.getPreferenceCount(); i++) {
108             final TwoStatePreference namePref = (TwoStatePreference) mNamesGroup.getPreference(i);
109 
110             if (TextUtils.equals(namePref.getKey(), KEY_NAME_DEFAULT)
111                     || TextUtils.equals(namePref.getKey(), KEY_NAME_CUSTOM)) {
112                 continue;
113             }
114             final boolean nameMatch = TextUtils.equals(namePref.getTitle(), customLabel);
115             namePref.setChecked(nameMatch);
116             nameMatched |= nameMatch;
117         }
118 
119         mNameDefaultPref.setTitle(defaultLabel);
120 
121         final boolean nameIsDefault = TextUtils.isEmpty(customLabel);
122         mNameDefaultPref.setChecked(nameIsDefault);
123 
124         InputCustomNameFragment.prepareArgs(mNameCustomPref.getExtras(), defaultLabel,
125                 nameIsDefault ? defaultLabel : customLabel);
126 
127         if (!nameIsDefault && !nameMatched) {
128             mNameCustomPref.setChecked(true);
129             mNameCustomPref.setSummary(customLabel);
130         } else {
131             mNameCustomPref.setChecked(false);
132             mNameCustomPref.setSummary(null);
133         }
134     }
135 
136     @Override
onPreferenceTreeClick(Preference preference)137     public boolean onPreferenceTreeClick(Preference preference) {
138         final String key = preference.getKey();
139         if (key == null) {
140             return super.onPreferenceTreeClick(preference);
141         }
142         if (preference instanceof RadioPreference) {
143             final RadioPreference radioPreference = (RadioPreference) preference;
144             radioPreference.setChecked(true);
145             radioPreference.clearOtherRadioPreferences(mNamesGroup);
146 
147             if (TextUtils.equals(key, KEY_NAME_CUSTOM)) {
148                 return super.onPreferenceTreeClick(preference);
149             } else if (TextUtils.equals(key, KEY_NAME_DEFAULT)) {
150                 setInputName(null);
151                 return true;
152             } else {
153                 setInputName(preference.getTitle());
154             }
155         }
156         switch (key) {
157             case KEY_SHOW_INPUT:
158                 setInputVisible(((TwoStatePreference) preference).isChecked());
159                 return true;
160         }
161         return super.onPreferenceTreeClick(preference);
162     }
163 
setInputName(CharSequence name)164     private void setInputName(CharSequence name) {
165         if (TextUtils.isEmpty(name)) {
166             mCustomLabels.remove(mInputInfo.getId());
167         } else {
168             mCustomLabels.put(mInputInfo.getId(), name.toString());
169         }
170 
171         TvInputInfo.TvInputSettings
172                 .putCustomLabels(getContext(), mCustomLabels, UserHandle.USER_SYSTEM);
173     }
174 
setInputVisible(boolean visible)175     private void setInputVisible(boolean visible) {
176         final boolean wasVisible = !mHiddenIds.contains(mInputInfo.getId());
177 
178         if (wasVisible == visible) {
179             return;
180         }
181 
182         if (visible) {
183             mHiddenIds.remove(mInputInfo.getId());
184         } else {
185             mHiddenIds.add(mInputInfo.getId());
186         }
187 
188         TvInputInfo.TvInputSettings
189                 .putHiddenTvInputs(getContext(), mHiddenIds, UserHandle.USER_SYSTEM);
190     }
191 
192     @Override
onSetCustomName(CharSequence name)193     public void onSetCustomName(CharSequence name) {
194         setInputName(name);
195     }
196 
197     @Override
getMetricsCategory()198     public int getMetricsCategory() {
199         return MetricsEvent.SETTINGS_TV_INPUT_OPTIONS_CATEGORY;
200     }
201 }
202