1 /* 2 * Copyright 2020 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.server.hdmi; 18 19 import static android.hardware.hdmi.HdmiControlManager.SettingName; 20 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.StringDef; 25 import android.content.Context; 26 import android.content.SharedPreferences; 27 import android.hardware.hdmi.HdmiControlManager; 28 import android.os.Environment; 29 import android.os.SystemProperties; 30 import android.provider.Settings.Global; 31 import android.util.ArrayMap; 32 import android.util.Slog; 33 34 import com.android.internal.R; 35 import com.android.internal.annotations.GuardedBy; 36 import com.android.internal.annotations.VisibleForTesting; 37 import com.android.internal.util.ConcurrentUtils; 38 39 import java.io.File; 40 import java.util.ArrayList; 41 import java.util.LinkedHashMap; 42 import java.util.List; 43 import java.util.Map.Entry; 44 import java.util.concurrent.Executor; 45 46 /** 47 * The {@link HdmiCecConfig} class is used for getting information about 48 * available HDMI control settings, including CEC settings and eARC settings. 49 * 50 * TODO(b/240379115): rename this class and related methods in this package to represent that the 51 * settings storage mechanism applies to all HDMI control settings and not just CEC settings. 52 */ 53 public class HdmiCecConfig { 54 private static final String TAG = "HdmiCecConfig"; 55 56 private static final String ETC_DIR = "etc"; 57 private static final String CONFIG_FILE = "cec_config.xml"; 58 private static final String SHARED_PREFS_DIR = "shared_prefs"; 59 private static final String SHARED_PREFS_NAME = "cec_config.xml"; 60 61 private static final int STORAGE_SYSPROPS = 0; 62 private static final int STORAGE_GLOBAL_SETTINGS = 1; 63 private static final int STORAGE_SHARED_PREFS = 2; 64 65 @IntDef({ 66 STORAGE_SYSPROPS, 67 STORAGE_GLOBAL_SETTINGS, 68 STORAGE_SHARED_PREFS, 69 }) 70 private @interface Storage {} 71 72 private static final String VALUE_TYPE_STRING = "string"; 73 private static final String VALUE_TYPE_INT = "int"; 74 75 @StringDef({ 76 VALUE_TYPE_STRING, 77 VALUE_TYPE_INT, 78 }) 79 private @interface ValueType {} 80 81 @NonNull private final Context mContext; 82 @NonNull private final StorageAdapter mStorageAdapter; 83 84 private final Object mLock = new Object(); 85 86 @GuardedBy("mLock") 87 private final ArrayMap<Setting, ArrayMap<SettingChangeListener, Executor>> 88 mSettingChangeListeners = new ArrayMap<>(); 89 90 private LinkedHashMap<String, Setting> mSettings = new LinkedHashMap<>(); 91 92 /** 93 * Exception thrown when the CEC Configuration setup verification fails. 94 * This usually means a settings lacks default value or storage/storage key. 95 */ 96 public static class VerificationException extends RuntimeException { VerificationException(String message)97 public VerificationException(String message) { 98 super(message); 99 } 100 } 101 102 /** 103 * Listener used to get notifications when value of a setting changes. 104 */ 105 public interface SettingChangeListener { 106 /** 107 * Called when value of a setting changes. 108 * 109 * @param setting name of a CEC setting that changed 110 */ onChange(@onNull @ettingName String setting)111 void onChange(@NonNull @SettingName String setting); 112 } 113 114 /** 115 * Setting storage input/output helper class. 116 */ 117 public static class StorageAdapter { 118 @NonNull private final Context mContext; 119 @NonNull private final SharedPreferences mSharedPrefs; 120 StorageAdapter(@onNull Context context)121 StorageAdapter(@NonNull Context context) { 122 mContext = context; 123 // The package info in the context isn't initialized in the way it is for normal apps, 124 // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we 125 // build the path manually below using the same policy that appears in ContextImpl. 126 final Context deviceContext = mContext.createDeviceProtectedStorageContext(); 127 final File prefsFile = new File(new File(Environment.getDataSystemDirectory(), 128 SHARED_PREFS_DIR), SHARED_PREFS_NAME); 129 mSharedPrefs = deviceContext.getSharedPreferences(prefsFile, Context.MODE_PRIVATE); 130 } 131 132 /** 133 * Read the value from a system property. 134 * Returns the given default value if the system property is not set. 135 */ retrieveSystemProperty(@onNull String storageKey, @NonNull String defaultValue)136 public String retrieveSystemProperty(@NonNull String storageKey, 137 @NonNull String defaultValue) { 138 return SystemProperties.get(storageKey, defaultValue); 139 } 140 141 /** 142 * Write the value to a system property. 143 */ storeSystemProperty(@onNull String storageKey, @NonNull String value)144 public void storeSystemProperty(@NonNull String storageKey, 145 @NonNull String value) { 146 SystemProperties.set(storageKey, value); 147 } 148 149 /** 150 * Read the value from a global setting. 151 * Returns the given default value if the system property is not set. 152 */ retrieveGlobalSetting(@onNull String storageKey, @NonNull String defaultValue)153 public String retrieveGlobalSetting(@NonNull String storageKey, 154 @NonNull String defaultValue) { 155 String value = Global.getString(mContext.getContentResolver(), storageKey); 156 return value != null ? value : defaultValue; 157 } 158 159 /** 160 * Write the value to a global setting. 161 */ storeGlobalSetting(@onNull String storageKey, @NonNull String value)162 public void storeGlobalSetting(@NonNull String storageKey, 163 @NonNull String value) { 164 Global.putString(mContext.getContentResolver(), storageKey, value); 165 } 166 167 /** 168 * Read the value from a shared preference. 169 * Returns the given default value if the preference is not set. 170 */ retrieveSharedPref(@onNull String storageKey, @NonNull String defaultValue)171 public String retrieveSharedPref(@NonNull String storageKey, 172 @NonNull String defaultValue) { 173 return mSharedPrefs.getString(storageKey, defaultValue); 174 } 175 176 /** 177 * Write the value to a shared preference. 178 */ storeSharedPref(@onNull String storageKey, @NonNull String value)179 public void storeSharedPref(@NonNull String storageKey, 180 @NonNull String value) { 181 mSharedPrefs.edit().putString(storageKey, value).apply(); 182 } 183 } 184 185 private class Value { 186 private final String mStringValue; 187 private final Integer mIntValue; 188 Value(@onNull String value)189 Value(@NonNull String value) { 190 mStringValue = value; 191 mIntValue = null; 192 } 193 Value(@onNull Integer value)194 Value(@NonNull Integer value) { 195 mStringValue = null; 196 mIntValue = value; 197 } 198 getStringValue()199 String getStringValue() { 200 return mStringValue; 201 } 202 getIntValue()203 Integer getIntValue() { 204 return mIntValue; 205 } 206 } 207 208 protected class Setting { 209 @NonNull private final Context mContext; 210 @NonNull private final @SettingName String mName; 211 private final boolean mUserConfigurable; 212 213 private Value mDefaultValue = null; 214 private List<Value> mAllowedValues = new ArrayList<>(); 215 Setting(@onNull Context context, @NonNull @SettingName String name, int userConfResId)216 Setting(@NonNull Context context, 217 @NonNull @SettingName String name, 218 int userConfResId) { 219 mContext = context; 220 mName = name; 221 mUserConfigurable = mContext.getResources().getBoolean(userConfResId); 222 } 223 getName()224 public @SettingName String getName() { 225 return mName; 226 } 227 getValueType()228 public @ValueType String getValueType() { 229 return getDefaultValue().getStringValue() != null 230 ? VALUE_TYPE_STRING 231 : VALUE_TYPE_INT; 232 } 233 getDefaultValue()234 public Value getDefaultValue() { 235 if (mDefaultValue == null) { 236 throw new VerificationException("Invalid CEC setup for '" 237 + this.getName() + "' setting. " 238 + "Setting has no default value."); 239 } 240 return mDefaultValue; 241 } 242 getUserConfigurable()243 public boolean getUserConfigurable() { 244 return mUserConfigurable; 245 } 246 registerValue(@onNull Value value, int allowedResId, int defaultResId)247 private void registerValue(@NonNull Value value, 248 int allowedResId, int defaultResId) { 249 if (mContext.getResources().getBoolean(allowedResId)) { 250 mAllowedValues.add(value); 251 if (mContext.getResources().getBoolean(defaultResId)) { 252 if (mDefaultValue != null) { 253 Slog.e(TAG, 254 "Failed to set '" + value + "' as a default for '" + this.getName() 255 + "': Setting already has a default ('" + mDefaultValue 256 + "')."); 257 return; 258 } 259 mDefaultValue = value; 260 } 261 } 262 } 263 registerValue(@onNull String value, int allowedResId, int defaultResId)264 public void registerValue(@NonNull String value, int allowedResId, 265 int defaultResId) { 266 registerValue(new Value(value), allowedResId, defaultResId); 267 } 268 registerValue(int value, int allowedResId, int defaultResId)269 public void registerValue(int value, int allowedResId, 270 int defaultResId) { 271 registerValue(new Value(value), allowedResId, defaultResId); 272 } 273 274 getAllowedValues()275 public List<Value> getAllowedValues() { 276 return mAllowedValues; 277 } 278 } 279 280 @VisibleForTesting HdmiCecConfig(@onNull Context context, @NonNull StorageAdapter storageAdapter)281 HdmiCecConfig(@NonNull Context context, 282 @NonNull StorageAdapter storageAdapter) { 283 mContext = context; 284 mStorageAdapter = storageAdapter; 285 286 // IMPORTANT: when adding a config value for a particular setting, register that value AFTER 287 // the existing values for that setting. That way, defaults set in the RRO are forward 288 // compatible even if the RRO doesn't include that new value yet 289 // (e.g. because it's ported from a previous release). 290 291 Setting hdmiCecEnabled = registerSetting( 292 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 293 R.bool.config_cecHdmiCecEnabled_userConfigurable); 294 hdmiCecEnabled.registerValue(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED, 295 R.bool.config_cecHdmiCecControlEnabled_allowed, 296 R.bool.config_cecHdmiCecControlEnabled_default); 297 hdmiCecEnabled.registerValue(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED, 298 R.bool.config_cecHdmiCecControlDisabled_allowed, 299 R.bool.config_cecHdmiCecControlDisabled_default); 300 301 Setting hdmiCecVersion = registerSetting( 302 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 303 R.bool.config_cecHdmiCecVersion_userConfigurable); 304 hdmiCecVersion.registerValue(HdmiControlManager.HDMI_CEC_VERSION_1_4_B, 305 R.bool.config_cecHdmiCecVersion14b_allowed, 306 R.bool.config_cecHdmiCecVersion14b_default); 307 hdmiCecVersion.registerValue(HdmiControlManager.HDMI_CEC_VERSION_2_0, 308 R.bool.config_cecHdmiCecVersion20_allowed, 309 R.bool.config_cecHdmiCecVersion20_default); 310 311 Setting routingControlControl = registerSetting( 312 HdmiControlManager.CEC_SETTING_NAME_ROUTING_CONTROL, 313 R.bool.config_cecRoutingControl_userConfigurable); 314 routingControlControl.registerValue(HdmiControlManager.ROUTING_CONTROL_ENABLED, 315 R.bool.config_cecRoutingControlEnabled_allowed, 316 R.bool.config_cecRoutingControlEnabled_default); 317 routingControlControl.registerValue(HdmiControlManager.ROUTING_CONTROL_DISABLED, 318 R.bool.config_cecRoutingControlDisabled_allowed, 319 R.bool.config_cecRoutingControlDisabled_default); 320 321 Setting soundbarMode = registerSetting( 322 HdmiControlManager.CEC_SETTING_NAME_SOUNDBAR_MODE, 323 R.bool.config_cecSoundbarMode_userConfigurable); 324 soundbarMode.registerValue(HdmiControlManager.SOUNDBAR_MODE_ENABLED, 325 R.bool.config_cecSoundbarModeEnabled_allowed, 326 R.bool.config_cecSoundbarModeEnabled_default); 327 soundbarMode.registerValue(HdmiControlManager.SOUNDBAR_MODE_DISABLED, 328 R.bool.config_cecSoundbarModeDisabled_allowed, 329 R.bool.config_cecSoundbarModeDisabled_default); 330 331 Setting powerControlMode = registerSetting( 332 HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE, 333 R.bool.config_cecPowerControlMode_userConfigurable); 334 powerControlMode.registerValue(HdmiControlManager.POWER_CONTROL_MODE_TV, 335 R.bool.config_cecPowerControlModeTv_allowed, 336 R.bool.config_cecPowerControlModeTv_default); 337 powerControlMode.registerValue(HdmiControlManager.POWER_CONTROL_MODE_BROADCAST, 338 R.bool.config_cecPowerControlModeBroadcast_allowed, 339 R.bool.config_cecPowerControlModeBroadcast_default); 340 powerControlMode.registerValue(HdmiControlManager.POWER_CONTROL_MODE_NONE, 341 R.bool.config_cecPowerControlModeNone_allowed, 342 R.bool.config_cecPowerControlModeNone_default); 343 powerControlMode.registerValue(HdmiControlManager.POWER_CONTROL_MODE_TV_AND_AUDIO_SYSTEM, 344 R.bool.config_cecPowerControlModeTvAndAudioSystem_allowed, 345 R.bool.config_cecPowerControlModeTvAndAudioSystem_default); 346 347 Setting powerStateChangeOnActiveSourceLost = registerSetting( 348 HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, 349 R.bool.config_cecPowerStateChangeOnActiveSourceLost_userConfigurable); 350 powerStateChangeOnActiveSourceLost.registerValue( 351 HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE, 352 R.bool.config_cecPowerStateChangeOnActiveSourceLostNone_allowed, 353 R.bool.config_cecPowerStateChangeOnActiveSourceLostNone_default); 354 powerStateChangeOnActiveSourceLost.registerValue( 355 HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW, 356 R.bool.config_cecPowerStateChangeOnActiveSourceLostStandbyNow_allowed, 357 R.bool.config_cecPowerStateChangeOnActiveSourceLostStandbyNow_default); 358 359 Setting systemAudioControl = registerSetting( 360 HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, 361 R.bool.config_cecSystemAudioControl_userConfigurable); 362 systemAudioControl.registerValue(HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED, 363 R.bool.config_cecSystemAudioControlEnabled_allowed, 364 R.bool.config_cecSystemAudioControlEnabled_default); 365 systemAudioControl.registerValue(HdmiControlManager.SYSTEM_AUDIO_CONTROL_DISABLED, 366 R.bool.config_cecSystemAudioControlDisabled_allowed, 367 R.bool.config_cecSystemAudioControlDisabled_default); 368 369 Setting systemAudioModeMuting = registerSetting( 370 HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, 371 R.bool.config_cecSystemAudioModeMuting_userConfigurable); 372 systemAudioModeMuting.registerValue(HdmiControlManager.SYSTEM_AUDIO_MODE_MUTING_ENABLED, 373 R.bool.config_cecSystemAudioModeMutingEnabled_allowed, 374 R.bool.config_cecSystemAudioModeMutingEnabled_default); 375 systemAudioModeMuting.registerValue(HdmiControlManager.SYSTEM_AUDIO_MODE_MUTING_DISABLED, 376 R.bool.config_cecSystemAudioModeMutingDisabled_allowed, 377 R.bool.config_cecSystemAudioModeMutingDisabled_default); 378 379 Setting volumeControlMode = registerSetting( 380 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, 381 R.bool.config_cecVolumeControlMode_userConfigurable); 382 volumeControlMode.registerValue(HdmiControlManager.VOLUME_CONTROL_ENABLED, 383 R.bool.config_cecVolumeControlModeEnabled_allowed, 384 R.bool.config_cecVolumeControlModeEnabled_default); 385 volumeControlMode.registerValue(HdmiControlManager.VOLUME_CONTROL_DISABLED, 386 R.bool.config_cecVolumeControlModeDisabled_allowed, 387 R.bool.config_cecVolumeControlModeDisabled_default); 388 389 Setting tvWakeOnOneTouchPlay = registerSetting( 390 HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY, 391 R.bool.config_cecTvWakeOnOneTouchPlay_userConfigurable); 392 tvWakeOnOneTouchPlay.registerValue(HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED, 393 R.bool.config_cecTvWakeOnOneTouchPlayEnabled_allowed, 394 R.bool.config_cecTvWakeOnOneTouchPlayEnabled_default); 395 tvWakeOnOneTouchPlay.registerValue(HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_DISABLED, 396 R.bool.config_cecTvWakeOnOneTouchPlayDisabled_allowed, 397 R.bool.config_cecTvWakeOnOneTouchPlayDisabled_default); 398 399 Setting tvSendStandbyOnSleep = registerSetting( 400 HdmiControlManager.CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP, 401 R.bool.config_cecTvSendStandbyOnSleep_userConfigurable); 402 tvSendStandbyOnSleep.registerValue(HdmiControlManager.TV_SEND_STANDBY_ON_SLEEP_ENABLED, 403 R.bool.config_cecTvSendStandbyOnSleepEnabled_allowed, 404 R.bool.config_cecTvSendStandbyOnSleepEnabled_default); 405 tvSendStandbyOnSleep.registerValue(HdmiControlManager.TV_SEND_STANDBY_ON_SLEEP_DISABLED, 406 R.bool.config_cecTvSendStandbyOnSleepDisabled_allowed, 407 R.bool.config_cecTvSendStandbyOnSleepDisabled_default); 408 409 Setting setMenuLanguage = registerSetting( 410 HdmiControlManager.CEC_SETTING_NAME_SET_MENU_LANGUAGE, 411 R.bool.config_cecSetMenuLanguage_userConfigurable); 412 setMenuLanguage.registerValue(HdmiControlManager.SET_MENU_LANGUAGE_ENABLED, 413 R.bool.config_cecSetMenuLanguageEnabled_allowed, 414 R.bool.config_cecSetMenuLanguageEnabled_default); 415 setMenuLanguage.registerValue(HdmiControlManager.SET_MENU_LANGUAGE_DISABLED, 416 R.bool.config_cecSetMenuLanguageDisabled_allowed, 417 R.bool.config_cecSetMenuLanguageDisabled_default); 418 419 Setting rcProfileTv = registerSetting( 420 HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_TV, 421 R.bool.config_cecRcProfileTv_userConfigurable); 422 rcProfileTv.registerValue(HdmiControlManager.RC_PROFILE_TV_NONE, 423 R.bool.config_cecRcProfileTvNone_allowed, 424 R.bool.config_cecRcProfileTvNone_default); 425 rcProfileTv.registerValue(HdmiControlManager.RC_PROFILE_TV_ONE, 426 R.bool.config_cecRcProfileTvOne_allowed, 427 R.bool.config_cecRcProfileTvOne_default); 428 rcProfileTv.registerValue(HdmiControlManager.RC_PROFILE_TV_TWO, 429 R.bool.config_cecRcProfileTvTwo_allowed, 430 R.bool.config_cecRcProfileTvTwo_default); 431 rcProfileTv.registerValue(HdmiControlManager.RC_PROFILE_TV_THREE, 432 R.bool.config_cecRcProfileTvThree_allowed, 433 R.bool.config_cecRcProfileTvThree_default); 434 rcProfileTv.registerValue(HdmiControlManager.RC_PROFILE_TV_FOUR, 435 R.bool.config_cecRcProfileTvFour_allowed, 436 R.bool.config_cecRcProfileTvFour_default); 437 438 Setting rcProfileSourceRootMenu = registerSetting( 439 HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU, 440 R.bool.config_cecRcProfileSourceRootMenu_userConfigurable); 441 rcProfileSourceRootMenu.registerValue( 442 HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED, 443 R.bool.config_cecRcProfileSourceRootMenuHandled_allowed, 444 R.bool.config_cecRcProfileSourceRootMenuHandled_default); 445 rcProfileSourceRootMenu.registerValue( 446 HdmiControlManager.RC_PROFILE_SOURCE_MENU_NOT_HANDLED, 447 R.bool.config_cecRcProfileSourceRootMenuNotHandled_allowed, 448 R.bool.config_cecRcProfileSourceRootMenuNotHandled_default); 449 450 Setting rcProfileSourceSetupMenu = registerSetting( 451 HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU, 452 R.bool.config_cecRcProfileSourceSetupMenu_userConfigurable); 453 rcProfileSourceSetupMenu.registerValue( 454 HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED, 455 R.bool.config_cecRcProfileSourceSetupMenuHandled_allowed, 456 R.bool.config_cecRcProfileSourceSetupMenuHandled_default); 457 rcProfileSourceSetupMenu.registerValue( 458 HdmiControlManager.RC_PROFILE_SOURCE_MENU_NOT_HANDLED, 459 R.bool.config_cecRcProfileSourceSetupMenuNotHandled_allowed, 460 R.bool.config_cecRcProfileSourceSetupMenuNotHandled_default); 461 462 Setting rcProfileSourceContentsMenu = registerSetting( 463 HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU, 464 R.bool.config_cecRcProfileSourceContentsMenu_userConfigurable); 465 rcProfileSourceContentsMenu.registerValue( 466 HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED, 467 R.bool.config_cecRcProfileSourceContentsMenuHandled_allowed, 468 R.bool.config_cecRcProfileSourceContentsMenuHandled_default); 469 rcProfileSourceContentsMenu.registerValue( 470 HdmiControlManager.RC_PROFILE_SOURCE_MENU_NOT_HANDLED, 471 R.bool.config_cecRcProfileSourceContentsMenuNotHandled_allowed, 472 R.bool.config_cecRcProfileSourceContentsMenuNotHandled_default); 473 474 Setting rcProfileSourceTopMenu = registerSetting( 475 HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU, 476 R.bool.config_cecRcProfileSourceTopMenu_userConfigurable); 477 rcProfileSourceTopMenu.registerValue( 478 HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED, 479 R.bool.config_cecRcProfileSourceTopMenuHandled_allowed, 480 R.bool.config_cecRcProfileSourceTopMenuHandled_default); 481 rcProfileSourceTopMenu.registerValue( 482 HdmiControlManager.RC_PROFILE_SOURCE_MENU_NOT_HANDLED, 483 R.bool.config_cecRcProfileSourceTopMenuNotHandled_allowed, 484 R.bool.config_cecRcProfileSourceTopMenuNotHandled_default); 485 486 Setting rcProfileSourceMediaContextSensitiveMenu = registerSetting( 487 HdmiControlManager 488 .CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU, 489 R.bool.config_cecRcProfileSourceMediaContextSensitiveMenu_userConfigurable); 490 rcProfileSourceMediaContextSensitiveMenu.registerValue( 491 HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED, 492 R.bool.config_cecRcProfileSourceMediaContextSensitiveMenuHandled_allowed, 493 R.bool.config_cecRcProfileSourceMediaContextSensitiveMenuHandled_default); 494 rcProfileSourceMediaContextSensitiveMenu.registerValue( 495 HdmiControlManager.RC_PROFILE_SOURCE_MENU_NOT_HANDLED, 496 R.bool.config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_allowed, 497 R.bool.config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_default); 498 499 Setting querySadLpcm = registerSetting( 500 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_LPCM, 501 R.bool.config_cecQuerySadLpcm_userConfigurable); 502 querySadLpcm.registerValue( 503 HdmiControlManager.QUERY_SAD_ENABLED, 504 R.bool.config_cecQuerySadLpcmEnabled_allowed, 505 R.bool.config_cecQuerySadLpcmEnabled_default); 506 querySadLpcm.registerValue( 507 HdmiControlManager.QUERY_SAD_DISABLED, 508 R.bool.config_cecQuerySadLpcmDisabled_allowed, 509 R.bool.config_cecQuerySadLpcmDisabled_default); 510 511 Setting querySadDd = registerSetting( 512 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DD, 513 R.bool.config_cecQuerySadDd_userConfigurable); 514 querySadDd.registerValue( 515 HdmiControlManager.QUERY_SAD_ENABLED, 516 R.bool.config_cecQuerySadDdEnabled_allowed, 517 R.bool.config_cecQuerySadDdEnabled_default); 518 querySadDd.registerValue( 519 HdmiControlManager.QUERY_SAD_DISABLED, 520 R.bool.config_cecQuerySadDdDisabled_allowed, 521 R.bool.config_cecQuerySadDdDisabled_default); 522 523 Setting querySadMpeg1 = registerSetting( 524 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG1, 525 R.bool.config_cecQuerySadMpeg1_userConfigurable); 526 querySadMpeg1.registerValue( 527 HdmiControlManager.QUERY_SAD_ENABLED, 528 R.bool.config_cecQuerySadMpeg1Enabled_allowed, 529 R.bool.config_cecQuerySadMpeg1Enabled_default); 530 querySadMpeg1.registerValue( 531 HdmiControlManager.QUERY_SAD_DISABLED, 532 R.bool.config_cecQuerySadMpeg1Disabled_allowed, 533 R.bool.config_cecQuerySadMpeg1Disabled_default); 534 535 Setting querySadMp3 = registerSetting( 536 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MP3, 537 R.bool.config_cecQuerySadMp3_userConfigurable); 538 querySadMp3.registerValue( 539 HdmiControlManager.QUERY_SAD_ENABLED, 540 R.bool.config_cecQuerySadMp3Enabled_allowed, 541 R.bool.config_cecQuerySadMp3Enabled_default); 542 querySadMp3.registerValue( 543 HdmiControlManager.QUERY_SAD_DISABLED, 544 R.bool.config_cecQuerySadMp3Disabled_allowed, 545 R.bool.config_cecQuerySadMp3Disabled_default); 546 547 Setting querySadMpeg2 = registerSetting( 548 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG2, 549 R.bool.config_cecQuerySadMpeg2_userConfigurable); 550 querySadMpeg2.registerValue( 551 HdmiControlManager.QUERY_SAD_ENABLED, 552 R.bool.config_cecQuerySadMpeg2Enabled_allowed, 553 R.bool.config_cecQuerySadMpeg2Enabled_default); 554 querySadMpeg2.registerValue( 555 HdmiControlManager.QUERY_SAD_DISABLED, 556 R.bool.config_cecQuerySadMpeg2Disabled_allowed, 557 R.bool.config_cecQuerySadMpeg2Disabled_default); 558 559 Setting querySadAac = registerSetting( 560 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_AAC, 561 R.bool.config_cecQuerySadAac_userConfigurable); 562 querySadAac.registerValue( 563 HdmiControlManager.QUERY_SAD_ENABLED, 564 R.bool.config_cecQuerySadAacEnabled_allowed, 565 R.bool.config_cecQuerySadAacEnabled_default); 566 querySadAac.registerValue( 567 HdmiControlManager.QUERY_SAD_DISABLED, 568 R.bool.config_cecQuerySadAacDisabled_allowed, 569 R.bool.config_cecQuerySadAacDisabled_default); 570 571 Setting querySadDts = registerSetting( 572 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DTS, 573 R.bool.config_cecQuerySadDts_userConfigurable); 574 querySadDts.registerValue( 575 HdmiControlManager.QUERY_SAD_ENABLED, 576 R.bool.config_cecQuerySadDtsEnabled_allowed, 577 R.bool.config_cecQuerySadDtsEnabled_default); 578 querySadDts.registerValue( 579 HdmiControlManager.QUERY_SAD_DISABLED, 580 R.bool.config_cecQuerySadDtsDisabled_allowed, 581 R.bool.config_cecQuerySadDtsDisabled_default); 582 583 Setting querySadAtrac = registerSetting( 584 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_ATRAC, 585 R.bool.config_cecQuerySadAtrac_userConfigurable); 586 querySadAtrac.registerValue( 587 HdmiControlManager.QUERY_SAD_ENABLED, 588 R.bool.config_cecQuerySadAtracEnabled_allowed, 589 R.bool.config_cecQuerySadAtracEnabled_default); 590 querySadAtrac.registerValue( 591 HdmiControlManager.QUERY_SAD_DISABLED, 592 R.bool.config_cecQuerySadAtracDisabled_allowed, 593 R.bool.config_cecQuerySadAtracDisabled_default); 594 595 Setting querySadOnebitaudio = registerSetting( 596 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO, 597 R.bool.config_cecQuerySadOnebitaudio_userConfigurable); 598 querySadOnebitaudio.registerValue( 599 HdmiControlManager.QUERY_SAD_ENABLED, 600 R.bool.config_cecQuerySadOnebitaudioEnabled_allowed, 601 R.bool.config_cecQuerySadOnebitaudioEnabled_default); 602 querySadOnebitaudio.registerValue( 603 HdmiControlManager.QUERY_SAD_DISABLED, 604 R.bool.config_cecQuerySadOnebitaudioDisabled_allowed, 605 R.bool.config_cecQuerySadOnebitaudioDisabled_default); 606 607 Setting querySadDdp = registerSetting( 608 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DDP, 609 R.bool.config_cecQuerySadDdp_userConfigurable); 610 querySadDdp.registerValue( 611 HdmiControlManager.QUERY_SAD_ENABLED, 612 R.bool.config_cecQuerySadDdpEnabled_allowed, 613 R.bool.config_cecQuerySadDdpEnabled_default); 614 querySadDdp.registerValue( 615 HdmiControlManager.QUERY_SAD_DISABLED, 616 R.bool.config_cecQuerySadDdpDisabled_allowed, 617 R.bool.config_cecQuerySadDdpDisabled_default); 618 619 Setting querySadDtshd = registerSetting( 620 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DTSHD, 621 R.bool.config_cecQuerySadDtshd_userConfigurable); 622 querySadDtshd.registerValue( 623 HdmiControlManager.QUERY_SAD_ENABLED, 624 R.bool.config_cecQuerySadDtshdEnabled_allowed, 625 R.bool.config_cecQuerySadDtshdEnabled_default); 626 querySadDtshd.registerValue( 627 HdmiControlManager.QUERY_SAD_DISABLED, 628 R.bool.config_cecQuerySadDtshdDisabled_allowed, 629 R.bool.config_cecQuerySadDtshdDisabled_default); 630 631 Setting querySadTruehd = registerSetting( 632 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_TRUEHD, 633 R.bool.config_cecQuerySadTruehd_userConfigurable); 634 querySadTruehd.registerValue( 635 HdmiControlManager.QUERY_SAD_ENABLED, 636 R.bool.config_cecQuerySadTruehdEnabled_allowed, 637 R.bool.config_cecQuerySadTruehdEnabled_default); 638 querySadTruehd.registerValue( 639 HdmiControlManager.QUERY_SAD_DISABLED, 640 R.bool.config_cecQuerySadTruehdDisabled_allowed, 641 R.bool.config_cecQuerySadTruehdDisabled_default); 642 643 Setting querySadDst = registerSetting( 644 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DST, 645 R.bool.config_cecQuerySadDst_userConfigurable); 646 querySadDst.registerValue( 647 HdmiControlManager.QUERY_SAD_ENABLED, 648 R.bool.config_cecQuerySadDstEnabled_allowed, 649 R.bool.config_cecQuerySadDstEnabled_default); 650 querySadDst.registerValue( 651 HdmiControlManager.QUERY_SAD_DISABLED, 652 R.bool.config_cecQuerySadDstDisabled_allowed, 653 R.bool.config_cecQuerySadDstDisabled_default); 654 655 Setting querySadWmapro = registerSetting( 656 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_WMAPRO, 657 R.bool.config_cecQuerySadWmapro_userConfigurable); 658 querySadWmapro.registerValue( 659 HdmiControlManager.QUERY_SAD_ENABLED, 660 R.bool.config_cecQuerySadWmaproEnabled_allowed, 661 R.bool.config_cecQuerySadWmaproEnabled_default); 662 querySadWmapro.registerValue( 663 HdmiControlManager.QUERY_SAD_DISABLED, 664 R.bool.config_cecQuerySadWmaproDisabled_allowed, 665 R.bool.config_cecQuerySadWmaproDisabled_default); 666 667 Setting querySadMax = registerSetting( 668 HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MAX, 669 R.bool.config_cecQuerySadMax_userConfigurable); 670 querySadMax.registerValue( 671 HdmiControlManager.QUERY_SAD_ENABLED, 672 R.bool.config_cecQuerySadMaxEnabled_allowed, 673 R.bool.config_cecQuerySadMaxEnabled_default); 674 querySadMax.registerValue( 675 HdmiControlManager.QUERY_SAD_DISABLED, 676 R.bool.config_cecQuerySadMaxDisabled_allowed, 677 R.bool.config_cecQuerySadMaxDisabled_default); 678 679 Setting earcEnabled = registerSetting( 680 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 681 R.bool.config_earcEnabled_userConfigurable); 682 earcEnabled.registerValue(HdmiControlManager.EARC_FEATURE_ENABLED, 683 R.bool.config_earcFeatureEnabled_allowed, 684 R.bool.config_earcFeatureEnabled_default); 685 earcEnabled.registerValue(HdmiControlManager.EARC_FEATURE_DISABLED, 686 R.bool.config_earcFeatureDisabled_allowed, 687 R.bool.config_earcFeatureDisabled_default); 688 689 verifySettings(); 690 } 691 HdmiCecConfig(@onNull Context context)692 HdmiCecConfig(@NonNull Context context) { 693 this(context, new StorageAdapter(context)); 694 } 695 registerSetting(@onNull @ettingName String name, int userConfResId)696 private Setting registerSetting(@NonNull @SettingName String name, 697 int userConfResId) { 698 Setting setting = new Setting(mContext, name, userConfResId); 699 mSettings.put(name, setting); 700 return setting; 701 } 702 verifySettings()703 private void verifySettings() { 704 for (Setting setting: mSettings.values()) { 705 // This will throw an exception when a setting 706 // doesn't have a default value assigned. 707 setting.getDefaultValue(); 708 getStorage(setting); 709 getStorageKey(setting); 710 } 711 } 712 713 @Nullable getSetting(@onNull String name)714 private Setting getSetting(@NonNull String name) { 715 return mSettings.containsKey(name) ? mSettings.get(name) : null; 716 } 717 718 @Storage getStorage(@onNull Setting setting)719 private int getStorage(@NonNull Setting setting) { 720 switch (setting.getName()) { 721 case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED: 722 return STORAGE_SHARED_PREFS; 723 case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION: 724 return STORAGE_SHARED_PREFS; 725 case HdmiControlManager.CEC_SETTING_NAME_ROUTING_CONTROL: 726 return STORAGE_SHARED_PREFS; 727 case HdmiControlManager.CEC_SETTING_NAME_SOUNDBAR_MODE: 728 return STORAGE_SHARED_PREFS; 729 case HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE: 730 return STORAGE_SHARED_PREFS; 731 case HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE: 732 return STORAGE_SHARED_PREFS; 733 case HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST: 734 return STORAGE_SHARED_PREFS; 735 case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL: 736 return STORAGE_SHARED_PREFS; 737 case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING: 738 return STORAGE_SHARED_PREFS; 739 case HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY: 740 return STORAGE_SHARED_PREFS; 741 case HdmiControlManager.CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP: 742 return STORAGE_SHARED_PREFS; 743 case HdmiControlManager.CEC_SETTING_NAME_SET_MENU_LANGUAGE: 744 return STORAGE_SHARED_PREFS; 745 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_TV: 746 return STORAGE_SHARED_PREFS; 747 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU: 748 return STORAGE_SHARED_PREFS; 749 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU: 750 return STORAGE_SHARED_PREFS; 751 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU: 752 return STORAGE_SHARED_PREFS; 753 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU: 754 return STORAGE_SHARED_PREFS; 755 case HdmiControlManager 756 .CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU: 757 return STORAGE_SHARED_PREFS; 758 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_LPCM: 759 return STORAGE_SHARED_PREFS; 760 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DD: 761 return STORAGE_SHARED_PREFS; 762 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG1: 763 return STORAGE_SHARED_PREFS; 764 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MP3: 765 return STORAGE_SHARED_PREFS; 766 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG2: 767 return STORAGE_SHARED_PREFS; 768 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_AAC: 769 return STORAGE_SHARED_PREFS; 770 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DTS: 771 return STORAGE_SHARED_PREFS; 772 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_ATRAC: 773 return STORAGE_SHARED_PREFS; 774 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO: 775 return STORAGE_SHARED_PREFS; 776 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DDP: 777 return STORAGE_SHARED_PREFS; 778 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DTSHD: 779 return STORAGE_SHARED_PREFS; 780 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_TRUEHD: 781 return STORAGE_SHARED_PREFS; 782 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DST: 783 return STORAGE_SHARED_PREFS; 784 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_WMAPRO: 785 return STORAGE_SHARED_PREFS; 786 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MAX: 787 return STORAGE_SHARED_PREFS; 788 case HdmiControlManager.SETTING_NAME_EARC_ENABLED: 789 return STORAGE_SHARED_PREFS; 790 default: 791 throw new VerificationException("Invalid CEC setting '" + setting.getName() 792 + "' storage."); 793 } 794 } 795 getStorageKey(@onNull Setting setting)796 private String getStorageKey(@NonNull Setting setting) { 797 switch (setting.getName()) { 798 case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED: 799 return setting.getName(); 800 case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION: 801 return setting.getName(); 802 case HdmiControlManager.CEC_SETTING_NAME_ROUTING_CONTROL: 803 return setting.getName(); 804 case HdmiControlManager.CEC_SETTING_NAME_SOUNDBAR_MODE: 805 return setting.getName(); 806 case HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE: 807 return setting.getName(); 808 case HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE: 809 return setting.getName(); 810 case HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST: 811 return setting.getName(); 812 case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL: 813 return setting.getName(); 814 case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING: 815 return setting.getName(); 816 case HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY: 817 return setting.getName(); 818 case HdmiControlManager.CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP: 819 return setting.getName(); 820 case HdmiControlManager.CEC_SETTING_NAME_SET_MENU_LANGUAGE: 821 return setting.getName(); 822 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_TV: 823 return setting.getName(); 824 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU: 825 return setting.getName(); 826 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU: 827 return setting.getName(); 828 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU: 829 return setting.getName(); 830 case HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU: 831 return setting.getName(); 832 case HdmiControlManager 833 .CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU: 834 return setting.getName(); 835 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_LPCM: 836 return setting.getName(); 837 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DD: 838 return setting.getName(); 839 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG1: 840 return setting.getName(); 841 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MP3: 842 return setting.getName(); 843 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG2: 844 return setting.getName(); 845 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_AAC: 846 return setting.getName(); 847 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DTS: 848 return setting.getName(); 849 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_ATRAC: 850 return setting.getName(); 851 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO: 852 return setting.getName(); 853 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DDP: 854 return setting.getName(); 855 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DTSHD: 856 return setting.getName(); 857 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_TRUEHD: 858 return setting.getName(); 859 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DST: 860 return setting.getName(); 861 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_WMAPRO: 862 return setting.getName(); 863 case HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MAX: 864 return setting.getName(); 865 case HdmiControlManager.SETTING_NAME_EARC_ENABLED: 866 return setting.getName(); 867 default: 868 throw new VerificationException("Invalid CEC setting '" + setting.getName() 869 + "' storage key."); 870 } 871 } 872 retrieveValue(@onNull Setting setting, @NonNull String defaultValue)873 protected String retrieveValue(@NonNull Setting setting, @NonNull String defaultValue) { 874 @Storage int storage = getStorage(setting); 875 String storageKey = getStorageKey(setting); 876 if (storage == STORAGE_SYSPROPS) { 877 HdmiLogger.debug("Reading '" + storageKey + "' sysprop."); 878 return mStorageAdapter.retrieveSystemProperty(storageKey, defaultValue); 879 } else if (storage == STORAGE_GLOBAL_SETTINGS) { 880 HdmiLogger.debug("Reading '" + storageKey + "' global setting."); 881 return mStorageAdapter.retrieveGlobalSetting(storageKey, defaultValue); 882 } else if (storage == STORAGE_SHARED_PREFS) { 883 HdmiLogger.debug("Reading '" + storageKey + "' shared preference."); 884 return mStorageAdapter.retrieveSharedPref(storageKey, defaultValue); 885 } 886 return null; 887 } 888 storeValue(@onNull Setting setting, @NonNull String value)889 protected void storeValue(@NonNull Setting setting, @NonNull String value) { 890 @Storage int storage = getStorage(setting); 891 String storageKey = getStorageKey(setting); 892 if (storage == STORAGE_SYSPROPS) { 893 HdmiLogger.debug("Setting '" + storageKey + "' sysprop."); 894 mStorageAdapter.storeSystemProperty(storageKey, value); 895 } else if (storage == STORAGE_GLOBAL_SETTINGS) { 896 HdmiLogger.debug("Setting '" + storageKey + "' global setting."); 897 mStorageAdapter.storeGlobalSetting(storageKey, value); 898 } else if (storage == STORAGE_SHARED_PREFS) { 899 HdmiLogger.debug("Setting '" + storageKey + "' shared pref."); 900 mStorageAdapter.storeSharedPref(storageKey, value); 901 notifySettingChanged(setting); 902 } 903 } 904 notifySettingChanged(@onNull Setting setting)905 protected void notifySettingChanged(@NonNull Setting setting) { 906 synchronized (mLock) { 907 ArrayMap<SettingChangeListener, Executor> listeners = 908 mSettingChangeListeners.get(setting); 909 if (listeners == null) { 910 return; // No listeners registered, do nothing. 911 } 912 for (Entry<SettingChangeListener, Executor> entry: listeners.entrySet()) { 913 SettingChangeListener listener = entry.getKey(); 914 Executor executor = entry.getValue(); 915 executor.execute(new Runnable() { 916 @Override 917 public void run() { 918 listener.onChange(setting.getName()); 919 } 920 }); 921 } 922 } 923 } 924 925 /** 926 * Register change listener for a given setting name using DirectExecutor. 927 */ registerChangeListener(@onNull @ettingName String name, SettingChangeListener listener)928 public void registerChangeListener(@NonNull @SettingName String name, 929 SettingChangeListener listener) { 930 registerChangeListener(name, listener, ConcurrentUtils.DIRECT_EXECUTOR); 931 } 932 933 /** 934 * Register change listener for a given setting name and executor. 935 */ registerChangeListener(@onNull @ettingName String name, SettingChangeListener listener, Executor executor)936 public void registerChangeListener(@NonNull @SettingName String name, 937 SettingChangeListener listener, 938 Executor executor) { 939 Setting setting = getSetting(name); 940 if (setting == null) { 941 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 942 } 943 @Storage int storage = getStorage(setting); 944 if (storage != STORAGE_GLOBAL_SETTINGS && storage != STORAGE_SHARED_PREFS) { 945 throw new IllegalArgumentException("Change listeners for setting '" + name 946 + "' not supported."); 947 } 948 synchronized (mLock) { 949 if (!mSettingChangeListeners.containsKey(setting)) { 950 mSettingChangeListeners.put(setting, new ArrayMap<>()); 951 } 952 mSettingChangeListeners.get(setting).put(listener, executor); 953 } 954 } 955 956 /** 957 * Remove change listener for a given setting name. 958 */ removeChangeListener(@onNull @ettingName String name, SettingChangeListener listener)959 public void removeChangeListener(@NonNull @SettingName String name, 960 SettingChangeListener listener) { 961 Setting setting = getSetting(name); 962 if (setting == null) { 963 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 964 } 965 synchronized (mLock) { 966 if (mSettingChangeListeners.containsKey(setting)) { 967 ArrayMap<SettingChangeListener, Executor> listeners = 968 mSettingChangeListeners.get(setting); 969 listeners.remove(listener); 970 if (listeners.isEmpty()) { 971 mSettingChangeListeners.remove(setting); 972 } 973 } 974 } 975 } 976 977 /** 978 * Returns a list of all settings based on the XML metadata. 979 */ getAllSettings()980 public @SettingName List<String> getAllSettings() { 981 return new ArrayList<>(mSettings.keySet()); 982 } 983 984 /** 985 * Returns a list of user-modifiable settings based on the XML metadata. 986 */ getUserSettings()987 public @SettingName List<String> getUserSettings() { 988 List<String> settings = new ArrayList<>(); 989 for (Setting setting: mSettings.values()) { 990 if (setting.getUserConfigurable()) { 991 settings.add(setting.getName()); 992 } 993 } 994 return settings; 995 } 996 997 /** 998 * For a given setting name returns true if and only if the value type of that 999 * setting is a string. 1000 */ isStringValueType(@onNull @ettingName String name)1001 public boolean isStringValueType(@NonNull @SettingName String name) { 1002 Setting setting = getSetting(name); 1003 if (setting == null) { 1004 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1005 } 1006 return getSetting(name).getValueType().equals(VALUE_TYPE_STRING); 1007 } 1008 1009 /** 1010 * For a given setting name returns true if and only if the value type of that 1011 * setting is an int. 1012 */ isIntValueType(@onNull @ettingName String name)1013 public boolean isIntValueType(@NonNull @SettingName String name) { 1014 Setting setting = getSetting(name); 1015 if (setting == null) { 1016 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1017 } 1018 return getSetting(name).getValueType().equals(VALUE_TYPE_INT); 1019 } 1020 1021 /** 1022 * For a given setting name returns values that are allowed for that setting (string). 1023 */ getAllowedStringValues(@onNull @ettingName String name)1024 public List<String> getAllowedStringValues(@NonNull @SettingName String name) { 1025 Setting setting = getSetting(name); 1026 if (setting == null) { 1027 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1028 } 1029 if (!setting.getValueType().equals(VALUE_TYPE_STRING)) { 1030 throw new IllegalArgumentException("Setting '" + name 1031 + "' is not a string-type setting."); 1032 } 1033 List<String> allowedValues = new ArrayList<String>(); 1034 for (Value allowedValue : setting.getAllowedValues()) { 1035 allowedValues.add(allowedValue.getStringValue()); 1036 } 1037 return allowedValues; 1038 } 1039 1040 /** 1041 * For a given setting name returns values that are allowed for that setting (string). 1042 */ getAllowedIntValues(@onNull @ettingName String name)1043 public List<Integer> getAllowedIntValues(@NonNull @SettingName String name) { 1044 Setting setting = getSetting(name); 1045 if (setting == null) { 1046 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1047 } 1048 if (!setting.getValueType().equals(VALUE_TYPE_INT)) { 1049 throw new IllegalArgumentException("Setting '" + name 1050 + "' is not a string-type setting."); 1051 } 1052 List<Integer> allowedValues = new ArrayList<Integer>(); 1053 for (Value allowedValue : setting.getAllowedValues()) { 1054 allowedValues.add(allowedValue.getIntValue()); 1055 } 1056 return allowedValues; 1057 } 1058 1059 /** 1060 * For a given setting name returns the default value for that setting (string). 1061 */ getDefaultStringValue(@onNull @ettingName String name)1062 public String getDefaultStringValue(@NonNull @SettingName String name) { 1063 Setting setting = getSetting(name); 1064 if (setting == null) { 1065 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1066 } 1067 if (!setting.getValueType().equals(VALUE_TYPE_STRING)) { 1068 throw new IllegalArgumentException("Setting '" + name 1069 + "' is not a string-type setting."); 1070 } 1071 return getSetting(name).getDefaultValue().getStringValue(); 1072 } 1073 1074 /** 1075 * For a given setting name returns the default value for that setting (int). 1076 */ getDefaultIntValue(@onNull @ettingName String name)1077 public int getDefaultIntValue(@NonNull @SettingName String name) { 1078 Setting setting = getSetting(name); 1079 if (setting == null) { 1080 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1081 } 1082 if (!setting.getValueType().equals(VALUE_TYPE_INT)) { 1083 throw new IllegalArgumentException("Setting '" + name 1084 + "' is not a string-type setting."); 1085 } 1086 return getSetting(name).getDefaultValue().getIntValue(); 1087 } 1088 1089 /** 1090 * For a given setting name returns the current value of that setting (string). 1091 */ getStringValue(@onNull @ettingName String name)1092 public String getStringValue(@NonNull @SettingName String name) { 1093 Setting setting = getSetting(name); 1094 if (setting == null) { 1095 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1096 } 1097 if (!setting.getValueType().equals(VALUE_TYPE_STRING)) { 1098 throw new IllegalArgumentException("Setting '" + name 1099 + "' is not a string-type setting."); 1100 } 1101 HdmiLogger.debug("Getting CEC setting value '" + name + "'."); 1102 return retrieveValue(setting, setting.getDefaultValue().getStringValue()); 1103 } 1104 1105 /** 1106 * For a given setting name returns the current value of that setting (int). 1107 */ getIntValue(@onNull @ettingName String name)1108 public int getIntValue(@NonNull @SettingName String name) { 1109 Setting setting = getSetting(name); 1110 if (setting == null) { 1111 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1112 } 1113 if (!setting.getValueType().equals(VALUE_TYPE_INT)) { 1114 throw new IllegalArgumentException("Setting '" + name 1115 + "' is not a int-type setting."); 1116 } 1117 HdmiLogger.debug("Getting CEC setting value '" + name + "'."); 1118 String defaultValue = Integer.toString(setting.getDefaultValue().getIntValue()); 1119 String value = retrieveValue(setting, defaultValue); 1120 return Integer.parseInt(value); 1121 } 1122 1123 /** 1124 * For a given setting name and value sets the current value of that setting (string). 1125 */ setStringValue(@onNull @ettingName String name, @NonNull String value)1126 public void setStringValue(@NonNull @SettingName String name, @NonNull String value) { 1127 Setting setting = getSetting(name); 1128 if (setting == null) { 1129 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1130 } 1131 if (!setting.getUserConfigurable()) { 1132 throw new IllegalArgumentException("Updating CEC setting '" + name + "' prohibited."); 1133 } 1134 if (!setting.getValueType().equals(VALUE_TYPE_STRING)) { 1135 throw new IllegalArgumentException("Setting '" + name 1136 + "' is not a string-type setting."); 1137 } 1138 if (!getAllowedStringValues(name).contains(value)) { 1139 throw new IllegalArgumentException("Invalid CEC setting '" + name 1140 + "' value: '" + value + "'."); 1141 } 1142 HdmiLogger.debug("Updating CEC setting '" + name + "' to '" + value + "'."); 1143 storeValue(setting, value); 1144 } 1145 1146 /** 1147 * For a given setting name and value sets the current value of that setting (int). 1148 */ setIntValue(@onNull @ettingName String name, int value)1149 public void setIntValue(@NonNull @SettingName String name, int value) { 1150 Setting setting = getSetting(name); 1151 if (setting == null) { 1152 throw new IllegalArgumentException("Setting '" + name + "' does not exist."); 1153 } 1154 if (!setting.getUserConfigurable()) { 1155 throw new IllegalArgumentException("Updating CEC setting '" + name + "' prohibited."); 1156 } 1157 if (!setting.getValueType().equals(VALUE_TYPE_INT)) { 1158 throw new IllegalArgumentException("Setting '" + name 1159 + "' is not a int-type setting."); 1160 } 1161 if (!getAllowedIntValues(name).contains(value)) { 1162 throw new IllegalArgumentException("Invalid CEC setting '" + name 1163 + "' value: '" + value + "'."); 1164 } 1165 HdmiLogger.debug("Updating CEC setting '" + name + "' to '" + value + "'."); 1166 storeValue(setting, Integer.toString(value)); 1167 } 1168 } 1169