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 17package com.android.tv.settings.system; 18 19import android.content.Context; 20import android.media.tv.TvInputInfo; 21import android.media.tv.TvInputManager; 22import android.os.Bundle; 23import android.os.UserHandle; 24import android.provider.Settings; 25import android.support.v17.preference.LeanbackPreferenceFragment; 26import android.support.v7.preference.Preference; 27import android.support.v7.preference.PreferenceGroup; 28import android.support.v7.preference.TwoStatePreference; 29import android.text.TextUtils; 30 31import com.android.tv.settings.R; 32 33import java.util.Map; 34import java.util.Set; 35 36/** 37 * Fragment to control TV input settings. 38 */ 39public 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 60 public static InputsFragment newInstance() { 61 return new InputsFragment(); 62 } 63 64 @Override 65 public void onCreate(Bundle savedInstanceState) { 66 super.onCreate(savedInstanceState); 67 mTvInputManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE); 68 } 69 70 @Override 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 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 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 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 180 private boolean readCecOption(String key) { 181 return Settings.Global.getInt(getContext().getContentResolver(), key, 1) == 1; 182 } 183 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 { 189 public InputPreference(Context context) { 190 super(context); 191 } 192 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 213 public static String makeInputPrefKey(TvInputInfo inputInfo) { 214 return "InputPref:" + inputInfo.getId(); 215 } 216} 217