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.media.tv.TvInputManager;
22 import android.os.Bundle;
23 import android.os.UserHandle;
24 import android.provider.Settings;
25 import android.support.v17.preference.LeanbackPreferenceFragment;
26 import android.support.v7.preference.Preference;
27 import android.support.v7.preference.PreferenceGroup;
28 import android.support.v7.preference.TwoStatePreference;
29 import android.text.TextUtils;
30 
31 import com.android.tv.settings.R;
32 
33 import java.util.Map;
34 import java.util.Set;
35 
36 /**
37  * Fragment to control TV input settings.
38  */
39 public class InputsFragment extends LeanbackPreferenceFragment {
40 
41     private static final String KEY_CONNECTED_INPUTS = "connected_inputs";
42     private static final String KEY_STANDBY_INPUTS = "standby_inputs";
43     private static final String KEY_DISCONNECTED_INPUTS = "disconnected_inputs";
44     private static final String KEY_HDMI_CONTROL = "hdmi_control";
45     private static final String KEY_DEVICE_AUTO_OFF = "device_auto_off";
46     private static final String KEY_TV_AUTO_ON = "tv_auto_on";
47 
48     private PreferenceGroup mConnectedGroup;
49     private PreferenceGroup mStandbyGroup;
50     private PreferenceGroup mDisconnectedGroup;
51 
52     private TwoStatePreference mHdmiControlPref;
53     private TwoStatePreference mDeviceAutoOffPref;
54     private TwoStatePreference mTvAutoOnPref;
55 
56     private TvInputManager mTvInputManager;
57     private Map<String, String> mCustomLabels;
58     private Set<String> mHiddenIds;
59 
newInstance()60     public static InputsFragment newInstance() {
61         return new InputsFragment();
62     }
63 
64     @Override
onCreate(Bundle savedInstanceState)65     public void onCreate(Bundle savedInstanceState) {
66         super.onCreate(savedInstanceState);
67         mTvInputManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE);
68     }
69 
70     @Override
onResume()71     public void onResume() {
72         super.onResume();
73         final Context context = getContext();
74         mCustomLabels =
75                 TvInputInfo.TvInputSettings.getCustomLabels(context, UserHandle.USER_SYSTEM);
76         mHiddenIds =
77                 TvInputInfo.TvInputSettings.getHiddenTvInputIds(context, UserHandle.USER_SYSTEM);
78         refresh();
79     }
80 
81     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)82     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
83         setPreferencesFromResource(R.xml.inputs, null);
84 
85         mConnectedGroup = (PreferenceGroup) findPreference(KEY_CONNECTED_INPUTS);
86         mStandbyGroup = (PreferenceGroup) findPreference(KEY_STANDBY_INPUTS);
87         mDisconnectedGroup = (PreferenceGroup) findPreference(KEY_DISCONNECTED_INPUTS);
88 
89         mHdmiControlPref = (TwoStatePreference) findPreference(KEY_HDMI_CONTROL);
90         mDeviceAutoOffPref = (TwoStatePreference) findPreference(KEY_DEVICE_AUTO_OFF);
91         mTvAutoOnPref = (TwoStatePreference) findPreference(KEY_TV_AUTO_ON);
92     }
93 
refresh()94     private void refresh() {
95         mHdmiControlPref.setChecked(readCecOption(Settings.Global.HDMI_CONTROL_ENABLED));
96         mDeviceAutoOffPref.setChecked(readCecOption(
97                 Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED));
98         mTvAutoOnPref.setChecked(readCecOption(Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED));
99 
100         for (TvInputInfo info : mTvInputManager.getTvInputList()) {
101             if (info.getType() == TvInputInfo.TYPE_TUNER
102                     || !TextUtils.isEmpty(info.getParentId())) {
103                 continue;
104             }
105 
106             int state;
107             try {
108                 state = mTvInputManager.getInputState(info.getId());
109             } catch (IllegalArgumentException e) {
110                 // Input is gone while iterating. Ignore.
111                 continue;
112             }
113 
114             InputPreference inputPref = (InputPreference) findPreference(makeInputPrefKey(info));
115             if (inputPref == null) {
116                 inputPref = new InputPreference(getPreferenceManager().getContext());
117             }
118             inputPref.refresh(info);
119 
120             switch (state) {
121                 case TvInputManager.INPUT_STATE_CONNECTED:
122                     mConnectedGroup.addPreference(inputPref);
123                     mStandbyGroup.removePreference(inputPref);
124                     mDisconnectedGroup.removePreference(inputPref);
125                     break;
126                 case TvInputManager.INPUT_STATE_CONNECTED_STANDBY:
127                     mConnectedGroup.removePreference(inputPref);
128                     mStandbyGroup.addPreference(inputPref);
129                     mDisconnectedGroup.removePreference(inputPref);
130                     break;
131                 case TvInputManager.INPUT_STATE_DISCONNECTED:
132                     mConnectedGroup.removePreference(inputPref);
133                     mStandbyGroup.removePreference(inputPref);
134                     mDisconnectedGroup.addPreference(inputPref);
135                     break;
136             }
137         }
138 
139         final int connectedCount = mConnectedGroup.getPreferenceCount();
140         mConnectedGroup.setTitle(getResources().getQuantityString(
141                 R.plurals.inputs_header_connected_input,
142                 connectedCount));
143         mConnectedGroup.setVisible(connectedCount > 0);
144 
145         final int standbyCount = mStandbyGroup.getPreferenceCount();
146         mStandbyGroup.setTitle(getResources().getQuantityString(
147                 R.plurals.inputs_header_standby_input,
148                 standbyCount));
149         mStandbyGroup.setVisible(standbyCount > 0);
150 
151         final int disconnectedCount = mDisconnectedGroup.getPreferenceCount();
152         mDisconnectedGroup.setTitle(getResources().getQuantityString(
153                 R.plurals.inputs_header_disconnected_input,
154                 disconnectedCount));
155         mDisconnectedGroup.setVisible(disconnectedCount > 0);
156     }
157 
158     @Override
onPreferenceTreeClick(Preference preference)159     public boolean onPreferenceTreeClick(Preference preference) {
160         final String key = preference.getKey();
161         if (key == null) {
162             return super.onPreferenceTreeClick(preference);
163         }
164         switch (key) {
165             case KEY_HDMI_CONTROL:
166                 writeCecOption(Settings.Global.HDMI_CONTROL_ENABLED, mHdmiControlPref.isChecked());
167                 return true;
168             case KEY_DEVICE_AUTO_OFF:
169                 writeCecOption(Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
170                         mDeviceAutoOffPref.isChecked());
171                 return true;
172             case KEY_TV_AUTO_ON:
173                 writeCecOption(Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
174                         mTvAutoOnPref.isChecked());
175                 return true;
176         }
177         return super.onPreferenceTreeClick(preference);
178     }
179 
readCecOption(String key)180     private boolean readCecOption(String key) {
181         return Settings.Global.getInt(getContext().getContentResolver(), key, 1) == 1;
182     }
183 
writeCecOption(String key, boolean value)184     private void writeCecOption(String key, boolean value) {
185         Settings.Global.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
186     }
187 
188     private class InputPreference extends Preference {
InputPreference(Context context)189         public InputPreference(Context context) {
190             super(context);
191         }
192 
refresh(TvInputInfo inputInfo)193         public void refresh(TvInputInfo inputInfo) {
194             setKey(makeInputPrefKey(inputInfo));
195 
196             setTitle(inputInfo.loadLabel(getContext()));
197 
198             String customLabel;
199             if (mHiddenIds.contains(inputInfo.getId())) {
200                 customLabel = getString(R.string.inputs_hide);
201             } else {
202                 customLabel = mCustomLabels.get(inputInfo.getId());
203                 if (TextUtils.isEmpty(customLabel)) {
204                     customLabel = inputInfo.loadLabel(getContext()).toString();
205                 }
206             }
207             setSummary(customLabel);
208             setFragment(InputOptionsFragment.class.getName());
209             InputOptionsFragment.prepareArgs(getExtras(), inputInfo);
210         }
211     }
212 
makeInputPrefKey(TvInputInfo inputInfo)213     public static String makeInputPrefKey(TvInputInfo inputInfo) {
214         return "InputPref:" + inputInfo.getId();
215     }
216 }
217