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