[CEC Configuration] Add CEC Configuration APIs
Bug: 166426337 Bug: 169144568 Test: atest HdmiCecConfigTest Change-Id: I7f109027103e73955d09b251a7a94aee9beded67
This commit is contained in:
@@ -319,6 +319,29 @@ public final class HdmiControlManager {
|
||||
/** The HdmiControlService will be disabled to standby. */
|
||||
public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3;
|
||||
|
||||
// -- Whether the HDMI CEC is enabled or disabled.
|
||||
/**
|
||||
* HDMI CEC enabled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String HDMI_CEC_CONTROL_ENABLED = "1";
|
||||
/**
|
||||
* HDMI CEC disabled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String HDMI_CEC_CONTROL_DISABLED = "0";
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@StringDef({
|
||||
HDMI_CEC_CONTROL_ENABLED,
|
||||
HDMI_CEC_CONTROL_DISABLED
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface HdmiCecControl {}
|
||||
|
||||
// -- Which devices the playback device can send a <Standby> message to upon going to sleep.
|
||||
/**
|
||||
* Send <Standby> to TV only.
|
||||
@@ -347,8 +370,90 @@ public final class HdmiControlManager {
|
||||
SEND_STANDBY_ON_SLEEP_NONE
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface StandbyBehavior {
|
||||
}
|
||||
public @interface StandbyBehavior {}
|
||||
|
||||
// -- Which power state action should be taken when Active Source is lost.
|
||||
/**
|
||||
* No action to be taken.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE = "none";
|
||||
/**
|
||||
* Go to standby immediately.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW = "standby_now";
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@StringDef({
|
||||
POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE,
|
||||
POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ActiveSourceLostBehavior {}
|
||||
|
||||
// -- Whether System Audio Mode muting is enabled or disabled.
|
||||
/**
|
||||
* System Audio Mode muting enabled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String SYSTEM_AUDIO_MODE_MUTING_ENABLED = "1";
|
||||
/**
|
||||
* System Audio Mode muting disabled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String SYSTEM_AUDIO_MODE_MUTING_DISABLED = "0";
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@StringDef({
|
||||
SYSTEM_AUDIO_MODE_MUTING_ENABLED,
|
||||
SYSTEM_AUDIO_MODE_MUTING_DISABLED
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface SystemAudioModeMuting {}
|
||||
|
||||
// -- Settings available in the CEC Configuration.
|
||||
/**
|
||||
* Name of a setting deciding whether the CEC is enabled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String SETTING_NAME_HDMI_CEC_ENABLED = "hdmi_cec_enabled";
|
||||
/**
|
||||
* Name of a setting deciding on the Standby message behaviour on sleep.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String SETTING_NAME_SEND_STANDBY_ON_SLEEP = "send_standby_on_sleep";
|
||||
/**
|
||||
* Name of a setting deciding on power state action when losing Active Source.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST =
|
||||
"power_state_change_on_active_source_lost";
|
||||
/**
|
||||
* Name of a setting deciding whether System Audio Muting is allowed.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING = "system_audio_mode_muting";
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@StringDef({
|
||||
SETTING_NAME_HDMI_CEC_ENABLED,
|
||||
SETTING_NAME_SEND_STANDBY_ON_SLEEP,
|
||||
SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
|
||||
SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
|
||||
})
|
||||
public @interface SettingName {}
|
||||
|
||||
// True if we have a logical device of type playback hosted in the system.
|
||||
private final boolean mHasPlaybackDevice;
|
||||
@@ -1186,4 +1291,233 @@ public final class HdmiControlManager {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of user-modifiable settings.
|
||||
*
|
||||
* @return a set of user-modifiable settings.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public List<String> getAvailableCecSettings() {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
return mService.getAvailableCecSettings();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of allowed values for a settings.
|
||||
*
|
||||
* @param name name of the setting
|
||||
* @return a set of allowed values for a settings. {@code null} on failure.
|
||||
* @throws IllegalArgumentException when setting {@code name} does not exist.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public List<String> getAllowedCecSettingValues(@NonNull String name) {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
return mService.getAllowedCecSettingValues(name);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'hdmi_cec_enabled' option.
|
||||
*
|
||||
* @param value the desired value
|
||||
* @throws IllegalArgumentException when the new value is not allowed.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public void setHdmiCecEnabled(@NonNull @HdmiCecControl String value) {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
mService.setCecSettingValue(SETTING_NAME_HDMI_CEC_ENABLED, value);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of 'hdmi_cec_enabled' option.
|
||||
*
|
||||
* @return the current value.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@HdmiCecControl
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public String getHdmiCecEnabled() {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
return mService.getCecSettingValue(SETTING_NAME_HDMI_CEC_ENABLED);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'send_standby_on_sleep' option.
|
||||
*
|
||||
* @param value the desired value
|
||||
* @throws IllegalArgumentException when the new value is not allowed.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public void setSendStandbyOnSleep(@NonNull @StandbyBehavior String value) {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
mService.setCecSettingValue(SETTING_NAME_SEND_STANDBY_ON_SLEEP, value);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of 'send_standby_on_sleep' option.
|
||||
*
|
||||
* @return the current value.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@StandbyBehavior
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public String getSendStandbyOnSleep() {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
return mService.getCecSettingValue(SETTING_NAME_SEND_STANDBY_ON_SLEEP);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'power_state_change_on_active_source_lost' option.
|
||||
*
|
||||
* @param value the desired value
|
||||
* @throws IllegalArgumentException when the new value is not allowed
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public void setPowerStateChangeOnActiveSourceLost(
|
||||
@NonNull @ActiveSourceLostBehavior String value) {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
mService.setCecSettingValue(
|
||||
SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, value);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of 'power_state_change_on_active_source_lost' option.
|
||||
*
|
||||
* @return the current value.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@ActiveSourceLostBehavior
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public String getPowerStateChangeOnActiveSourceLost() {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
return mService.getCecSettingValue(
|
||||
SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'system_audio_mode_muting' option.
|
||||
*
|
||||
* @param value the desired value
|
||||
* @throws IllegalArgumentException when the new value is not allowed.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public void setSystemAudioModeMuting(@NonNull @SystemAudioModeMuting String value) {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
mService.setCecSettingValue(SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, value);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of 'system_audio_mode_muting' option.
|
||||
*
|
||||
* @return the current value.
|
||||
* @throws RuntimeException when the HdmiControlService is not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@SystemAudioModeMuting
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public String getSystemAudioModeMuting() {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
return mService.getCecSettingValue(SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.BinderThread;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.TestApi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -293,6 +294,26 @@ public final class HdmiControlServiceWrapper {
|
||||
IHdmiCecVolumeControlFeatureListener listener) {
|
||||
HdmiControlServiceWrapper.this.removeHdmiCecVolumeControlFeatureListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAvailableCecSettings() {
|
||||
return HdmiControlServiceWrapper.this.getAvailableCecSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllowedCecSettingValues(String name) {
|
||||
return HdmiControlServiceWrapper.this.getAllowedCecSettingValues(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCecSettingValue(String name) {
|
||||
return HdmiControlServiceWrapper.this.getCecSettingValue(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCecSettingValue(String name, String value) {
|
||||
HdmiControlServiceWrapper.this.setCecSettingValue(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
@BinderThread
|
||||
@@ -466,4 +487,22 @@ public final class HdmiControlServiceWrapper {
|
||||
/** @hide */
|
||||
public void removeHdmiCecVolumeControlFeatureListener(
|
||||
IHdmiCecVolumeControlFeatureListener listener) {}
|
||||
|
||||
/** @hide */
|
||||
public List<String> getAvailableCecSettings() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public List<String> getAllowedCecSettingValues(String name) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public String getCecSettingValue(String name) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setCecSettingValue(String name, String value) {}
|
||||
}
|
||||
|
||||
@@ -87,4 +87,8 @@ interface IHdmiControlService {
|
||||
boolean isHdmiCecVolumeControlEnabled();
|
||||
void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
|
||||
void setSystemAudioModeOnForAudioOnlySource();
|
||||
List<String> getAvailableCecSettings();
|
||||
List<String> getAllowedCecSettingValues(String name);
|
||||
String getCecSettingValue(String name);
|
||||
void setCecSettingValue(String name, String value);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -373,6 +374,25 @@ public class HdmiAudioSystemClientTest {
|
||||
public void removeHdmiCecVolumeControlFeatureListener(
|
||||
IHdmiCecVolumeControlFeatureListener listener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAvailableCecSettings() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllowedCecSettingValues(String name) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCecSettingValue(String name) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCecSettingValue(String name, String value) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
320
services/core/java/com/android/server/hdmi/HdmiCecConfig.java
Normal file
320
services/core/java/com/android/server/hdmi/HdmiCecConfig.java
Normal file
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.os.Environment;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.Settings.Global;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.hdmi.cec.config.CecSettings;
|
||||
import com.android.server.hdmi.cec.config.Setting;
|
||||
import com.android.server.hdmi.cec.config.Value;
|
||||
import com.android.server.hdmi.cec.config.XmlParser;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.datatype.DatatypeConfigurationException;
|
||||
|
||||
/**
|
||||
* The {@link HdmiCecConfig} class is used for getting information about
|
||||
* available HDMI CEC settings.
|
||||
*/
|
||||
public class HdmiCecConfig {
|
||||
private static final String TAG = "HdmiCecConfig";
|
||||
|
||||
private static final String ETC_DIR = "etc";
|
||||
private static final String CONFIG_FILE = "cec_config.xml";
|
||||
|
||||
@Nullable private CecSettings mProductConfig = null;
|
||||
@Nullable private CecSettings mVendorOverride = null;
|
||||
@Nullable private StorageAdapter mStorageAdapter = null;
|
||||
|
||||
@IntDef({
|
||||
STORAGE_SYSPROPS,
|
||||
STORAGE_GLOBAL_SETTINGS,
|
||||
})
|
||||
private @interface Storage {}
|
||||
|
||||
private static final int STORAGE_SYSPROPS = 0;
|
||||
private static final int STORAGE_GLOBAL_SETTINGS = 1;
|
||||
|
||||
/**
|
||||
* System property key for Power State Change on Active Source Lost.
|
||||
*/
|
||||
public static final String SYSPROP_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST =
|
||||
"ro.hdmi.cec.source.power_state_change_on_active_source_lost";
|
||||
|
||||
/**
|
||||
* System property key for Audio Mode Muting.
|
||||
*/
|
||||
public static final String SYSPROP_SYSTEM_AUDIO_MODE_MUTING =
|
||||
"ro.hdmi.cec.audio.system_audio_mode_muting.enabled";
|
||||
|
||||
/**
|
||||
* Setting storage input/output helper class.
|
||||
*/
|
||||
public static class StorageAdapter {
|
||||
/**
|
||||
* Read the value from a system property.
|
||||
* Returns the given default value if the system property is not set.
|
||||
*/
|
||||
public String retrieveSystemProperty(@NonNull String storageKey,
|
||||
@NonNull String defaultValue) {
|
||||
return SystemProperties.get(storageKey, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the value to a system property.
|
||||
*/
|
||||
public void storeSystemProperty(@NonNull String storageKey,
|
||||
@NonNull String value) {
|
||||
SystemProperties.set(storageKey, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value from a global setting.
|
||||
* Returns the given default value if the system property is not set.
|
||||
*/
|
||||
public String retrieveGlobalSetting(@NonNull Context context,
|
||||
@NonNull String storageKey,
|
||||
@NonNull String defaultValue) {
|
||||
String value = Global.getString(context.getContentResolver(), storageKey);
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the value to a global setting.
|
||||
*/
|
||||
public void storeGlobalSetting(@NonNull Context context,
|
||||
@NonNull String storageKey,
|
||||
@NonNull String value) {
|
||||
Global.putString(context.getContentResolver(), storageKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
HdmiCecConfig(@Nullable CecSettings productConfig,
|
||||
@Nullable CecSettings vendorOverride,
|
||||
@Nullable StorageAdapter storageAdapter) {
|
||||
mProductConfig = productConfig;
|
||||
mVendorOverride = vendorOverride;
|
||||
mStorageAdapter = storageAdapter;
|
||||
}
|
||||
|
||||
HdmiCecConfig() {
|
||||
this(readSettingsFromFile(Environment.buildPath(Environment.getProductDirectory(),
|
||||
ETC_DIR, CONFIG_FILE)),
|
||||
readSettingsFromFile(Environment.buildPath(Environment.getVendorDirectory(),
|
||||
ETC_DIR, CONFIG_FILE)),
|
||||
new StorageAdapter());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static CecSettings readSettingsFromFile(@NonNull File file) {
|
||||
if (!file.exists()) {
|
||||
return null;
|
||||
}
|
||||
if (!file.isFile()) {
|
||||
Slog.e(TAG, "CEC configuration is not a file: " + file + ", skipping.");
|
||||
return null;
|
||||
}
|
||||
try (InputStream in = new BufferedInputStream(new FileInputStream(file))) {
|
||||
return XmlParser.read(in);
|
||||
} catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
|
||||
Slog.e(TAG, "Encountered an error while reading/parsing CEC config file: " + file, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Setting getSetting(@NonNull String name) {
|
||||
if (mVendorOverride != null) {
|
||||
// First read from the vendor override.
|
||||
for (Setting setting : mVendorOverride.getSetting()) {
|
||||
if (setting.getName().equals(name)) {
|
||||
return setting;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If not found, try the product config.
|
||||
for (Setting setting : mProductConfig.getSetting()) {
|
||||
if (setting.getName().equals(name)) {
|
||||
return setting;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Storage
|
||||
private int getStorage(@NonNull Setting setting) {
|
||||
switch (setting.getName()) {
|
||||
case HdmiControlManager.SETTING_NAME_HDMI_CEC_ENABLED:
|
||||
return STORAGE_GLOBAL_SETTINGS;
|
||||
case HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP:
|
||||
return STORAGE_GLOBAL_SETTINGS;
|
||||
case HdmiControlManager.SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST:
|
||||
return STORAGE_SYSPROPS;
|
||||
case HdmiControlManager.SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
|
||||
return STORAGE_SYSPROPS;
|
||||
default:
|
||||
throw new RuntimeException("Invalid CEC setting '" + setting.getName()
|
||||
+ "' storage.");
|
||||
}
|
||||
}
|
||||
|
||||
private String getStorageKey(@NonNull Setting setting) {
|
||||
switch (setting.getName()) {
|
||||
case HdmiControlManager.SETTING_NAME_HDMI_CEC_ENABLED:
|
||||
return Global.HDMI_CONTROL_ENABLED;
|
||||
case HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP:
|
||||
return Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP;
|
||||
case HdmiControlManager.SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST:
|
||||
return SYSPROP_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST;
|
||||
case HdmiControlManager.SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
|
||||
return SYSPROP_SYSTEM_AUDIO_MODE_MUTING;
|
||||
default:
|
||||
throw new RuntimeException("Invalid CEC setting '" + setting.getName()
|
||||
+ "' storage key.");
|
||||
}
|
||||
}
|
||||
|
||||
private String retrieveValue(@NonNull Context context, @NonNull Setting setting) {
|
||||
@Storage int storage = getStorage(setting);
|
||||
String storageKey = getStorageKey(setting);
|
||||
if (storage == STORAGE_SYSPROPS) {
|
||||
Slog.d(TAG, "Reading '" + storageKey + "' sysprop.");
|
||||
return mStorageAdapter.retrieveSystemProperty(storageKey,
|
||||
setting.getDefaultValue().getStringValue());
|
||||
} else if (storage == STORAGE_GLOBAL_SETTINGS) {
|
||||
Slog.d(TAG, "Reading '" + storageKey + "' global setting.");
|
||||
return mStorageAdapter.retrieveGlobalSetting(context, storageKey,
|
||||
setting.getDefaultValue().getStringValue());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void storeValue(@NonNull Context context, @NonNull Setting setting,
|
||||
@NonNull String value) {
|
||||
@Storage int storage = getStorage(setting);
|
||||
String storageKey = getStorageKey(setting);
|
||||
if (storage == STORAGE_SYSPROPS) {
|
||||
Slog.d(TAG, "Setting '" + storageKey + "' sysprop.");
|
||||
mStorageAdapter.storeSystemProperty(storageKey, value);
|
||||
} else if (storage == STORAGE_GLOBAL_SETTINGS) {
|
||||
Slog.d(TAG, "Setting '" + storageKey + "' global setting.");
|
||||
mStorageAdapter.storeGlobalSetting(context, storageKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of currently available settings based on the XML metadata.
|
||||
*/
|
||||
public List<String> getAvailableSettings() {
|
||||
Set<String> availableSettings = new HashSet<String>();
|
||||
// First read from the product config.
|
||||
for (Setting setting : mProductConfig.getSetting()) {
|
||||
if (setting.getUserConfigurable()) {
|
||||
availableSettings.add(setting.getName());
|
||||
}
|
||||
}
|
||||
if (mVendorOverride != null) {
|
||||
// Next either add or remove based on the vendor override.
|
||||
for (Setting setting : mVendorOverride.getSetting()) {
|
||||
if (setting.getUserConfigurable()) {
|
||||
availableSettings.add(setting.getName());
|
||||
} else {
|
||||
availableSettings.remove(setting.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayList(availableSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given setting name returns values that are allowed for that setting.
|
||||
*/
|
||||
public List<String> getAllowedValues(@NonNull String name) {
|
||||
Setting setting = getSetting(name);
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
|
||||
}
|
||||
List<String> allowedValues = new ArrayList<String>();
|
||||
for (Value allowedValue : setting.getAllowedValues().getValue()) {
|
||||
allowedValues.add(allowedValue.getStringValue());
|
||||
}
|
||||
return allowedValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given setting name returns the default value for that setting.
|
||||
*/
|
||||
public String getDefaultValue(@NonNull String name) {
|
||||
Setting setting = getSetting(name);
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
|
||||
}
|
||||
return getSetting(name).getDefaultValue().getStringValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given setting name returns the current value of that setting.
|
||||
*/
|
||||
public String getValue(@NonNull Context context, @NonNull String name) {
|
||||
Setting setting = getSetting(name);
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
|
||||
}
|
||||
Slog.d(TAG, "Getting CEC setting value '" + name + "'.");
|
||||
return retrieveValue(context, setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given setting name and value sets the current value of that setting.
|
||||
*/
|
||||
public void setValue(@NonNull Context context, @NonNull String name, @NonNull String value) {
|
||||
Setting setting = getSetting(name);
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
|
||||
}
|
||||
if (!setting.getUserConfigurable()) {
|
||||
throw new IllegalArgumentException("Updating CEC setting '" + name + "' prohibited.");
|
||||
}
|
||||
if (!getAllowedValues(name).contains(value)) {
|
||||
throw new IllegalArgumentException("Invalid CEC setting '" + name
|
||||
+ "' value: '" + value + "'.");
|
||||
}
|
||||
Slog.d(TAG, "Updating CEC setting '" + name + "' to '" + value + "'.");
|
||||
storeValue(context, setting, value);
|
||||
}
|
||||
}
|
||||
@@ -187,6 +187,9 @@ public class HdmiControlService extends SystemService {
|
||||
@GuardedBy("mLock")
|
||||
private boolean mHdmiCecVolumeControlEnabled;
|
||||
|
||||
// Make sure HdmiCecConfig is instantiated and the XMLs are read.
|
||||
private final HdmiCecConfig mHdmiCecConfig = new HdmiCecConfig();
|
||||
|
||||
/**
|
||||
* Interface to report send result.
|
||||
*/
|
||||
@@ -2329,6 +2332,50 @@ public class HdmiControlService extends SystemService {
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAvailableCecSettings() {
|
||||
enforceAccessPermission();
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return HdmiControlService.this.getHdmiCecConfig().getAvailableSettings();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllowedCecSettingValues(String name) {
|
||||
enforceAccessPermission();
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return HdmiControlService.this.getHdmiCecConfig().getAllowedValues(name);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCecSettingValue(String name) {
|
||||
enforceAccessPermission();
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return HdmiControlService.this.getHdmiCecConfig().getValue(getContext(), name);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCecSettingValue(String name, String value) {
|
||||
enforceAccessPermission();
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
HdmiControlService.this.getHdmiCecConfig().setValue(getContext(), name, value);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the source address to send out commands to devices connected to the current device
|
||||
@@ -3389,4 +3436,8 @@ public class HdmiControlService extends SystemService {
|
||||
getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
|
||||
HdmiControlService.PERMISSION);
|
||||
}
|
||||
|
||||
HdmiCecConfig getHdmiCecConfig() {
|
||||
return mHdmiCecConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.provider.Settings.Global;
|
||||
import android.sysprop.HdmiProperties;
|
||||
import android.util.Slog;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.hdmi.cec.config.CecSettings;
|
||||
import com.android.server.hdmi.cec.config.XmlParser;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.datatype.DatatypeConfigurationException;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(JUnit4.class)
|
||||
public final class HdmiCecConfigTest {
|
||||
private static final String TAG = "HdmiCecConfigTest";
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Mock private HdmiCecConfig.StorageAdapter mStorageAdapter;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = InstrumentationRegistry.getTargetContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailableCecSettings_Empty() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThat(hdmiCecConfig.getAvailableSettings()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailableCecSettings_OnlyMasterXml() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"hdmi_cec_enabled\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"0\" />"
|
||||
+ " <value string-value=\"1\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"1\" />"
|
||||
+ " </setting>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThat(hdmiCecConfig.getAvailableSettings())
|
||||
.containsExactly(HdmiControlManager.SETTING_NAME_HDMI_CEC_ENABLED,
|
||||
HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailableCecSettings_WithOverride() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"hdmi_cec_enabled\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"0\" />"
|
||||
+ " <value string-value=\"1\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"1\" />"
|
||||
+ " </setting>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>",
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"false\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>");
|
||||
assertThat(hdmiCecConfig.getAvailableSettings())
|
||||
.containsExactly(HdmiControlManager.SETTING_NAME_HDMI_CEC_ENABLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllowedValues_InvalidSetting() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> hdmiCecConfig.getAllowedValues("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllowedValues_BasicSanity() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThat(hdmiCecConfig.getAllowedValues(
|
||||
HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP))
|
||||
.containsExactly(HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV,
|
||||
HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST,
|
||||
HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDefaultValue_InvalidSetting() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> hdmiCecConfig.getDefaultValue("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDefaultValue_BasicSanity() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThat(hdmiCecConfig.getDefaultValue(
|
||||
HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP))
|
||||
.isEqualTo(HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValue_InvalidSetting() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> hdmiCecConfig.getValue(mContext, "foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValue_GlobalSetting_BasicSanity() {
|
||||
when(mStorageAdapter.retrieveGlobalSetting(mContext,
|
||||
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
|
||||
HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV))
|
||||
.thenReturn(HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThat(hdmiCecConfig.getValue(mContext,
|
||||
HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP))
|
||||
.isEqualTo(HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValue_SystemProperty_BasicSanity() {
|
||||
when(mStorageAdapter.retrieveSystemProperty(
|
||||
HdmiCecConfig.SYSPROP_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
|
||||
HdmiProperties.power_state_change_on_active_source_lost_values
|
||||
.NONE.name().toLowerCase()))
|
||||
.thenReturn(HdmiProperties.power_state_change_on_active_source_lost_values
|
||||
.STANDBY_NOW.name().toLowerCase());
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"power_state_change_on_active_source_lost\""
|
||||
+ " user-configurable=\"false\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " <value string-value=\"standby_now\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"none\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThat(hdmiCecConfig.getValue(mContext,
|
||||
HdmiControlManager.SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST))
|
||||
.isEqualTo(HdmiProperties.power_state_change_on_active_source_lost_values
|
||||
.STANDBY_NOW.name().toLowerCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setValue_InvalidSetting() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> hdmiCecConfig.setValue(mContext, "foo", "bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setValue_NotConfigurable() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"false\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> hdmiCecConfig.setValue(mContext,
|
||||
HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP,
|
||||
HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setValue_InvalidValue() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> hdmiCecConfig.setValue(mContext,
|
||||
HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP,
|
||||
"bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setValue_GlobalSetting_BasicSanity() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"send_standby_on_sleep\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"to_tv\" />"
|
||||
+ " <value string-value=\"broadcast\" />"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"to_tv\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
hdmiCecConfig.setValue(mContext,
|
||||
HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP,
|
||||
HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
|
||||
verify(mStorageAdapter).storeGlobalSetting(mContext,
|
||||
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
|
||||
HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setValue_SystemProperty_BasicSanity() {
|
||||
HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"power_state_change_on_active_source_lost\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value string-value=\"none\" />"
|
||||
+ " <value string-value=\"standby_now\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value string-value=\"none\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
hdmiCecConfig.setValue(mContext,
|
||||
HdmiControlManager.SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
|
||||
HdmiProperties.power_state_change_on_active_source_lost_values
|
||||
.STANDBY_NOW.name().toLowerCase());
|
||||
verify(mStorageAdapter).storeSystemProperty(
|
||||
HdmiCecConfig.SYSPROP_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
|
||||
HdmiProperties.power_state_change_on_active_source_lost_values
|
||||
.STANDBY_NOW.name().toLowerCase());
|
||||
}
|
||||
|
||||
private HdmiCecConfig createHdmiCecConfig(String productConfigXml, String vendorOverrideXml) {
|
||||
CecSettings productConfig = null;
|
||||
CecSettings vendorOverride = null;
|
||||
try {
|
||||
productConfig = XmlParser.read(new ByteArrayInputStream(productConfigXml.getBytes()));
|
||||
if (vendorOverrideXml != null) {
|
||||
vendorOverride = XmlParser.read(
|
||||
new ByteArrayInputStream(vendorOverrideXml.getBytes()));
|
||||
}
|
||||
} catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
|
||||
Slog.e(TAG, "Encountered an error while reading/parsing CEC config strings", e);
|
||||
}
|
||||
return new HdmiCecConfig(productConfig, vendorOverride, mStorageAdapter);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user