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