diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e430a575a1e21..e531af24fb709 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -3298,6 +3298,7 @@ package android.hardware.hdmi { method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public String getPowerControlMode(); method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public String getPowerStateChangeOnActiveSourceLost(); method @Nullable public android.hardware.hdmi.HdmiSwitchClient getSwitchClient(); + method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getSystemAudioControl(); method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getSystemAudioModeMuting(); method @Nullable public android.hardware.hdmi.HdmiTvClient getTvClient(); method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getTvSendStandbyOnSleep(); @@ -3314,6 +3315,7 @@ package android.hardware.hdmi { method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setPowerControlMode(@NonNull String); method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setPowerStateChangeOnActiveSourceLost(@NonNull String); method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setStandbyMode(boolean); + method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setSystemAudioControl(@NonNull int); method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setSystemAudioModeMuting(@NonNull int); method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setTvSendStandbyOnSleep(@NonNull int); method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setTvWakeOnOneTouchPlay(@NonNull int); @@ -3323,6 +3325,7 @@ package android.hardware.hdmi { field public static final String CEC_SETTING_NAME_HDMI_CEC_VERSION = "hdmi_cec_version"; field public static final String CEC_SETTING_NAME_POWER_CONTROL_MODE = "power_control_mode"; field public static final String CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST = "power_state_change_on_active_source_lost"; + field public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL = "system_audio_control"; field public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING = "system_audio_mode_muting"; field public static final String CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP = "tv_send_standby_on_sleep"; field public static final String CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY = "tv_wake_on_one_touch_play"; @@ -3396,6 +3399,8 @@ package android.hardware.hdmi { field public static final int RESULT_SUCCESS = 0; // 0x0 field public static final int RESULT_TARGET_NOT_AVAILABLE = 3; // 0x3 field public static final int RESULT_TIMEOUT = 1; // 0x1 + field public static final int SYSTEM_AUDIO_CONTROL_DISABLED = 0; // 0x0 + field public static final int SYSTEM_AUDIO_CONTROL_ENABLED = 1; // 0x1 field public static final int SYSTEM_AUDIO_MODE_MUTING_DISABLED = 0; // 0x0 field public static final int SYSTEM_AUDIO_MODE_MUTING_ENABLED = 1; // 0x1 field public static final int TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED = 3; // 0x3 diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java index 4c4deaa528612..985c53e9dc8e1 100644 --- a/core/java/android/hardware/hdmi/HdmiControlManager.java +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java @@ -449,6 +449,31 @@ public final class HdmiControlManager { @Retention(RetentionPolicy.SOURCE) public @interface ActiveSourceLostBehavior {} + // -- Whether System Audio Control is enabled or disabled. + /** + * System Audio Control enabled. + * + * @hide + */ + @SystemApi + public static final int SYSTEM_AUDIO_CONTROL_ENABLED = 1; + /** + * System Audio Control disabled. + * + * @hide + */ + @SystemApi + public static final int SYSTEM_AUDIO_CONTROL_DISABLED = 0; + /** + * @hide + */ + @IntDef(prefix = { "SYSTEM_AUDIO_CONTROL_" }, value = { + SYSTEM_AUDIO_CONTROL_ENABLED, + SYSTEM_AUDIO_CONTROL_DISABLED + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SystemAudioControl {} + // -- Whether System Audio Mode muting is enabled or disabled. /** * System Audio Mode muting enabled. @@ -744,6 +769,14 @@ public final class HdmiControlManager { @SystemApi public static final String CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST = "power_state_change_on_active_source_lost"; + /** + * Name of a setting deciding whether System Audio Control is enabled. + * + * @hide + */ + @SystemApi + public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL = + "system_audio_control"; /** * Name of a setting deciding whether System Audio Muting is allowed. * @@ -862,6 +895,7 @@ public final class HdmiControlManager { CEC_SETTING_NAME_HDMI_CEC_VERSION, CEC_SETTING_NAME_POWER_CONTROL_MODE, CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, + CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, CEC_SETTING_NAME_VOLUME_CONTROL_MODE, CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY, @@ -2133,6 +2167,58 @@ public final class HdmiControlManager { } } + /** + * Set the current status of System Audio Control. + * + *

Sets whether HDMI System Audio Control feature is enabled. If enabled, + * TV or Audio System will try to turn on the System Audio Mode if there's a + * connected CEC-enabled AV Receiver. Then an audio stream will be played on + * the AVR instead of TV speaker or Audio System speakers. If disabled, the + * System Audio Mode will never be activated. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.HDMI_CEC) + public void setSystemAudioControl(@NonNull @SystemAudioControl int value) { + if (mService == null) { + Log.e(TAG, "HdmiControlService is not available"); + throw new RuntimeException("HdmiControlService is not available"); + } + try { + mService.setCecSettingIntValue(CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, value); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get the current status of System Audio Control. + * + *

Reflects whether HDMI System Audio Control feature is enabled. If enabled, + * TV or Audio System will try to turn on the System Audio Mode if there's a + * connected CEC-enabled AV Receiver. Then an audio stream will be played on + * the AVR instead of TV speaker or Audio System speakers. If disabled, the + * System Audio Mode will never be activated. + * + * @hide + */ + @SystemApi + @NonNull + @SystemAudioControl + @RequiresPermission(android.Manifest.permission.HDMI_CEC) + public int getSystemAudioControl() { + if (mService == null) { + Log.e(TAG, "HdmiControlService is not available"); + throw new RuntimeException("HdmiControlService is not available"); + } + try { + return mService.getCecSettingIntValue(CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Set the current status of System Audio Mode muting. * diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 3528b057b4a2b..6cac1c7f7fd29 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4870,6 +4870,12 @@ true false + true + true + true + true + false + true true true diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index fa5108d909d72..185f7730b3ee2 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4307,6 +4307,12 @@ + + + + + + diff --git a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java index ff820268dfd89..54bcc95858870 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java @@ -345,6 +345,16 @@ public class HdmiCecConfig { R.bool.config_cecPowerStateChangeOnActiveSourceLostStandbyNow_allowed, R.bool.config_cecPowerStateChangeOnActiveSourceLostStandbyNow_default); + Setting systemAudioControl = registerSetting( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, + R.bool.config_cecSystemAudioControl_userConfigurable); + systemAudioControl.registerValue(HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED, + R.bool.config_cecSystemAudioControlEnabled_allowed, + R.bool.config_cecSystemAudioControlEnabled_default); + systemAudioControl.registerValue(HdmiControlManager.SYSTEM_AUDIO_CONTROL_DISABLED, + R.bool.config_cecSystemAudioControlDisabled_allowed, + R.bool.config_cecSystemAudioControlDisabled_default); + Setting systemAudioModeMuting = registerSetting( HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, R.bool.config_cecSystemAudioModeMuting_userConfigurable); @@ -507,6 +517,8 @@ public class HdmiCecConfig { return STORAGE_GLOBAL_SETTINGS; case HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST: return STORAGE_SHARED_PREFS; + case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL: + return STORAGE_GLOBAL_SETTINGS; case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING: return STORAGE_SHARED_PREFS; case HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY: @@ -544,6 +556,8 @@ public class HdmiCecConfig { return Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED; case HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST: return setting.getName(); + case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL: + return Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED; case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING: return setting.getName(); case HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY: diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 0bb128536b42b..a9fcce48b0244 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -110,8 +110,9 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { super(service, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); mRoutingControlFeatureEnabled = mService.readBooleanSetting(Global.HDMI_CEC_SWITCH_ENABLED, false); - mSystemAudioControlFeatureEnabled = - mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true); + mSystemAudioControlFeatureEnabled = mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL) + == HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED; } private static final String SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH = "/vendor/etc/sadConfig.xml"; @@ -857,7 +858,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { HdmiLogger.debug("[A]UpdateSystemAudio mode[on=%b] output=[%X]", on, device); } - void onSystemAduioControlFeatureSupportChanged(boolean enabled) { + void onSystemAudioControlFeatureSupportChanged(boolean enabled) { setSystemAudioControlFeatureEnabled(enabled); if (enabled) { addAndStartAction(new SystemAudioInitiationActionFromAvr(this)); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index ce5bf089a1c63..a887463802e2a 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -42,7 +42,6 @@ import android.media.AudioManager; import android.media.AudioSystem; import android.media.tv.TvInputInfo; import android.media.tv.TvInputManager.TvInputCallback; -import android.provider.Settings.Global; import android.util.Slog; import android.util.SparseBooleanArray; @@ -155,8 +154,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { HdmiCecLocalDeviceTv(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_TV); mPrevPortId = Constants.INVALID_PORT_ID; - mSystemAudioControlFeatureEnabled = - mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true); + mSystemAudioControlFeatureEnabled = service.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL) + == HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED; mStandbyHandler = new HdmiCecStandbyModeHandler(service, this); } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 9164e7c4e17b6..de60be81f604a 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -618,6 +618,27 @@ public class HdmiControlService extends SystemService { initializeCec(INITIATED_BY_ENABLE_CEC); } }, mServiceThreadExecutor); + mHdmiCecConfig.registerChangeListener( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, + new HdmiCecConfig.SettingChangeListener() { + @Override + public void onChange(String setting) { + boolean enabled = mHdmiCecConfig.getIntValue( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL) + == HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED; + if (isTvDeviceEnabled()) { + tv().setSystemAudioControlFeatureEnabled(enabled); + } + if (isAudioSystemDevice()) { + if (audioSystem() == null) { + Slog.e(TAG, "Audio System device has not registered yet." + + " Can't turn system audio mode on."); + } else { + audioSystem().onSystemAudioControlFeatureSupportChanged(enabled); + } + } + } + }, mServiceThreadExecutor); mHdmiCecConfig.registerChangeListener( HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY, new HdmiCecConfig.SettingChangeListener() { @@ -758,7 +779,6 @@ public class HdmiControlService extends SystemService { ContentResolver resolver = getContext().getContentResolver(); String[] settings = new String[] { Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, - Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, Global.MHL_INPUT_SWITCHING_ENABLED, Global.MHL_POWER_CHARGE_ENABLED, Global.HDMI_CEC_SWITCH_ENABLED, @@ -785,19 +805,6 @@ public class HdmiControlService extends SystemService { setHdmiCecVolumeControlEnabledInternal(getHdmiCecConfig().getIntValue( HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)); break; - case Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED: - if (isTvDeviceEnabled()) { - tv().setSystemAudioControlFeatureEnabled(enabled); - } - if (isAudioSystemDevice()) { - if (audioSystem() == null) { - Slog.e(TAG, "Audio System device has not registered yet." - + " Can't turn system audio mode on."); - break; - } - audioSystem().onSystemAduioControlFeatureSupportChanged(enabled); - } - break; case Global.HDMI_CEC_SWITCH_ENABLED: if (isAudioSystemDevice()) { if (audioSystem() == null) { diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java index f82b245a12dc6..7fa6a46315bed 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java @@ -98,6 +98,17 @@ final class FakeHdmiCecConfig extends HdmiCecConfig { doReturn(false).when(resources).getBoolean( R.bool.config_cecPowerStateChangeOnActiveSourceLostStandbyNow_default); + doReturn(true).when(resources).getBoolean( + R.bool.config_cecSystemAudioControl_userConfigurable); + doReturn(true).when(resources).getBoolean( + R.bool.config_cecSystemAudioControlEnabled_allowed); + doReturn(true).when(resources).getBoolean( + R.bool.config_cecSystemAudioControlEnabled_default); + doReturn(true).when(resources).getBoolean( + R.bool.config_cecSystemAudioControlDisabled_allowed); + doReturn(false).when(resources).getBoolean( + R.bool.config_cecSystemAudioControlDisabled_default); + doReturn(true).when(resources).getBoolean( R.bool.config_cecSystemAudioModeMuting_userConfigurable); doReturn(true).when(resources).getBoolean( diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java index 1c4e63edad552..d3287b3a57cca 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java @@ -84,6 +84,7 @@ public final class HdmiCecConfigTest { HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE, HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY, @@ -105,6 +106,7 @@ public final class HdmiCecConfigTest { HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE, HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY, @@ -126,6 +128,7 @@ public final class HdmiCecConfigTest { .containsExactly(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE, HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,