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