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