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