From c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29ea Mon Sep 17 00:00:00 2001 From: Donghyun Cho Date: Tue, 27 Dec 2016 18:31:09 +0900 Subject: [PATCH] CEC: Revisit the behavior of HDMI_SYSTEM_AUDIO_ENABLED Currently the system setting, HDMI_SYSTEM_AUDIO_ENABLED, is used to store the latest system audio mode status so that TV can keep this status over reboot. But because the name is a little confusing and the behavior isn't intuitive, it is likely to use this in a wrong way. This change renames this setting to HDMI_SYSTEM_AUDIO_CONTROL_ENABLED and tweak the purpose of it. Now, it will act more like a switch for System Audio Control feature, so user can disable or enable this feature entirely. With this way, implementation of audio output option will also become easier. Bug: 31449672 Test: Tested on archer Change-Id: Ice8717135272d4b86665a3452bfe7527c0d6c08b (cherry picked from commit 7b7aa8fb31ccf0cd3f36162a52f080263dd89e77) --- core/java/android/provider/Settings.java | 10 ++-- core/proto/android/providers/settings.proto | 2 +- .../android/provider/SettingsBackupTest.java | 2 +- .../settings/SettingsProtoDumpUtil.java | 4 +- .../server/hdmi/HdmiCecLocalDeviceTv.java | 57 +++++++++++++------ .../server/hdmi/HdmiControlService.java | 8 +-- .../server/hdmi/HotplugDetectionAction.java | 3 +- .../server/hdmi/SystemAudioAction.java | 2 +- .../hdmi/SystemAudioAutoInitiationAction.java | 32 +++++++---- 9 files changed, 77 insertions(+), 43 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 52aa1d58d69ce..be4802c048cdf 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7654,12 +7654,14 @@ public final class Settings { public static final String HDMI_CONTROL_ENABLED = "hdmi_control_enabled"; /** - * Whether HDMI system audio is enabled. If enabled, TV internal speaker is muted, - * and the output is redirected to AV Receiver connected via - * {@Global#HDMI_SYSTEM_AUDIO_OUTPUT}. + * Whether HDMI System Audio Control feature is enabled. If enabled, TV will try to turn on + * system audio mode if there's a connected CEC-enabled AV Receiver. Then audio stream will + * be played on AVR instead of TV spaeker. If disabled, the system audio mode will never be + * activated. * @hide */ - public static final String HDMI_SYSTEM_AUDIO_ENABLED = "hdmi_system_audio_enabled"; + public static final String HDMI_SYSTEM_AUDIO_CONTROL_ENABLED = + "hdmi_system_audio_control_enabled"; /** * Whether TV will automatically turn on upon reception of the CEC command diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto index 7eb0582a026f3..98c9e781efee4 100644 --- a/core/proto/android/providers/settings.proto +++ b/core/proto/android/providers/settings.proto @@ -97,7 +97,7 @@ message GlobalSettingsProto { SettingProto download_max_bytes_over_mobile = 52; SettingProto download_recommended_max_bytes_over_mobile = 53; SettingProto hdmi_control_enabled = 54; - SettingProto hdmi_system_audio_enabled = 55; + SettingProto hdmi_system_audio_control_enabled = 55; SettingProto hdmi_control_auto_wakeup_enabled = 56; SettingProto hdmi_control_auto_device_off_enabled = 57; SettingProto mhl_input_switching_enabled = 58; diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 903ef84df4e08..0cfdaf5d3caba 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -198,7 +198,7 @@ public class SettingsBackupTest { Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED, Settings.Global.HDMI_CONTROL_ENABLED, - Settings.Global.HDMI_SYSTEM_AUDIO_ENABLED, + Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, Settings.Global.HTTP_PROXY, Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 1fe3c48440870..4a54c0e909d2f 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -240,8 +240,8 @@ class SettingsProtoDumpUtil { Settings.Global.HDMI_CONTROL_ENABLED, GlobalSettingsProto.HDMI_CONTROL_ENABLED); dumpSetting(s, p, - Settings.Global.HDMI_SYSTEM_AUDIO_ENABLED, - GlobalSettingsProto.HDMI_SYSTEM_AUDIO_ENABLED); + Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, + GlobalSettingsProto.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED); dumpSetting(s, p, Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED, GlobalSettingsProto.HDMI_CONTROL_AUTO_WAKEUP_ENABLED); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index d81e092fa57c1..a50ec49f644bb 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -72,7 +72,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @ServiceThreadOnly private boolean mArcEstablished = false; - // Stores whether ARC feature is enabled per port. True by default for all the ARC-enabled ports. + // Stores whether ARC feature is enabled per port. + // True by default for all the ARC-enabled ports. private final SparseBooleanArray mArcFeatureEnabled = new SparseBooleanArray(); // Whether System audio mode is activated or not. @@ -80,6 +81,10 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @GuardedBy("mLock") private boolean mSystemAudioActivated = false; + // Whether the System Audio Control feature is enabled or not. True by default. + @GuardedBy("mLock") + private boolean mSystemAudioControlFeatureEnabled; + // The previous port id (input) before switching to the new one. This is remembered in order to // be able to switch to it upon receiving from currently active source. // This remains valid only when the active source was switched via one touch play operation @@ -186,6 +191,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { mAutoDeviceOff = mService.readBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, true); mAutoWakeup = mService.readBooleanSetting(Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED, true); + mSystemAudioControlFeatureEnabled = + mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true); mStandbyHandler = new HdmiCecStandbyModeHandler(service, this); } @@ -778,14 +785,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { addAndStartAction(new HotplugDetectionAction(HdmiCecLocalDeviceTv.this)); addAndStartAction(new PowerStatusMonitorAction(HdmiCecLocalDeviceTv.this)); - // If there is AVR, initiate System Audio Auto initiation action, - // which turns on and off system audio according to last system - // audio setting. HdmiDeviceInfo avr = getAvrDeviceInfo(); if (avr != null) { onNewAvrAdded(avr); } else { - setSystemAudioMode(false, true); + setSystemAudioMode(false); } } }); @@ -818,13 +822,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { void changeSystemAudioMode(boolean enabled, IHdmiControlCallback callback) { assertRunOnServiceThread(); if (!mService.isControlEnabled() || hasAction(DeviceDiscoveryAction.class)) { - setSystemAudioMode(false, true); + setSystemAudioMode(false); invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } HdmiDeviceInfo avr = getAvrDeviceInfo(); if (avr == null) { - setSystemAudioMode(false, true); + setSystemAudioMode(false); invokeCallback(callback, HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE); return; } @@ -834,12 +838,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } // # Seq 25 - void setSystemAudioMode(boolean on, boolean updateSetting) { - HdmiLogger.debug("System Audio Mode change[old:%b new:%b]", mSystemAudioActivated, on); - - if (updateSetting) { - mService.writeBooleanSetting(Global.HDMI_SYSTEM_AUDIO_ENABLED, on); + void setSystemAudioMode(boolean on) { + if (!isSystemAudioControlFeatureEnabled() && on) { + HdmiLogger.debug("Cannot turn on system audio mode " + + "because the System Audio Control feature is disabled."); + return; } + HdmiLogger.debug("System Audio Mode change[old:%b new:%b]", mSystemAudioActivated, on); updateAudioManagerForSystemAudio(on); synchronized (mLock) { if (mSystemAudioActivated != on) { @@ -863,8 +868,21 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } } - boolean getSystemAudioModeSetting() { - return mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_ENABLED, false); + @ServiceThreadOnly + void setSystemAudioControlFeatureEnabled(boolean enabled) { + assertRunOnServiceThread(); + synchronized (mLock) { + mSystemAudioControlFeatureEnabled = enabled; + } + if (hasSystemAudioDevice()) { + changeSystemAudioMode(enabled, null); + } + } + + boolean isSystemAudioControlFeatureEnabled() { + synchronized (mLock) { + return mSystemAudioControlFeatureEnabled; + } } /** @@ -1112,6 +1130,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleSetSystemAudioMode(HdmiCecMessage message) { assertRunOnServiceThread(); + boolean systemAudioStatus = HdmiUtils.parseCommandParamSystemAudioStatus(message); if (!isMessageForSystemAudio(message)) { if (getAvrDeviceInfo() == null) { // AVR may not have been discovered yet. Delay the message processing. @@ -1121,10 +1140,15 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED); } return true; + } else if (systemAudioStatus && !isSystemAudioControlFeatureEnabled()) { + HdmiLogger.debug("Ignoring message " + + "because the System Audio Control feature is disabled: %s", message); + mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED); + return true; } removeAction(SystemAudioAutoInitiationAction.class); SystemAudioActionFromAvr action = new SystemAudioActionFromAvr(this, - message.getSource(), HdmiUtils.parseCommandParamSystemAudioStatus(message), null); + message.getSource(), systemAudioStatus, null); addAndStartAction(action); return true; } @@ -1138,7 +1162,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // Ignore this message. return true; } - setSystemAudioMode(HdmiUtils.parseCommandParamSystemAudioStatus(message), true); + setSystemAudioMode(HdmiUtils.parseCommandParamSystemAudioStatus(message)); return true; } @@ -1882,6 +1906,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { pw.println("mArcFeatureEnabled: " + mArcFeatureEnabled); pw.println("mSystemAudioActivated: " + mSystemAudioActivated); pw.println("mSystemAudioMute: " + mSystemAudioMute); + pw.println("mSystemAudioControlFeatureEnabled: " + mSystemAudioControlFeatureEnabled); pw.println("mAutoDeviceOff: " + mAutoDeviceOff); pw.println("mAutoWakeup: " + mAutoWakeup); pw.println("mSkipRoutingControl: " + mSkipRoutingControl); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 89b10acd43a30..6864e1edaf08d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -486,7 +486,7 @@ public final class HdmiControlService extends SystemService { Global.HDMI_CONTROL_ENABLED, Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED, Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, - Global.HDMI_SYSTEM_AUDIO_ENABLED, + Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, Global.MHL_INPUT_SWITCHING_ENABLED, Global.MHL_POWER_CHARGE_ENABLED }; @@ -525,9 +525,9 @@ public final class HdmiControlService extends SystemService { } // No need to propagate to HAL. break; - case Global.HDMI_SYSTEM_AUDIO_ENABLED: - if (isTvDeviceEnabled() && tv().isSystemAudioActivated() != enabled) { - tv().changeSystemAudioMode(enabled, null); + case Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED: + if (isTvDeviceEnabled()) { + tv().setSystemAudioControlFeatureEnabled(enabled); } break; case Global.MHL_INPUT_SWITCHING_ENABLED: diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java index e1bcd99524579..7670dccf9c0a0 100644 --- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java +++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java @@ -262,8 +262,7 @@ final class HotplugDetectionAction extends HdmiCecFeatureAction { return; } - // Turn off system audio mode and update settings. - tv().setSystemAudioMode(false, true); + tv().setSystemAudioMode(false); if (tv().isArcEstablished()) { tv().enableAudioReturnChannel(false); addAndStartAction(new RequestArcTerminationAction(localDevice(), address)); diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java index af1a85d31443d..449b2085715ca 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java @@ -133,7 +133,7 @@ abstract class SystemAudioAction extends HdmiCecFeatureAction { } protected void setSystemAudioMode(boolean mode) { - tv().setSystemAudioMode(mode, true); + tv().setSystemAudioMode(mode); } @Override diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java index 01063b757d432..d347a9188dee1 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java @@ -50,7 +50,7 @@ final class SystemAudioAutoInitiationAction extends HdmiCecFeatureAction { @Override public void onSendCompleted(int error) { if (error != SendMessageResult.SUCCESS) { - tv().setSystemAudioMode(false, true); + tv().setSystemAudioMode(false); finish(); } } @@ -71,18 +71,24 @@ final class SystemAudioAutoInitiationAction extends HdmiCecFeatureAction { return false; } - private void handleSystemAudioModeStatusMessage(boolean isSystemAudioModeOn) { + private void handleSystemAudioModeStatusMessage(boolean currentSystemAudioMode) { if (!canChangeSystemAudio()) { HdmiLogger.debug("Cannot change system audio mode in auto initiation action."); finish(); return; } - boolean systemAudioModeSetting = tv().getSystemAudioModeSetting(); - if (systemAudioModeSetting && !isSystemAudioModeOn) { - addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, systemAudioModeSetting, null)); + // If System Audio Control feature is enabled, turn on system audio mode when new AVR is + // detected. Otherwise, turn off system audio mode. + boolean targetSystemAudioMode = tv().isSystemAudioControlFeatureEnabled(); + if (currentSystemAudioMode != targetSystemAudioMode) { + // Start System Audio Control feature actions only if necessary. + addAndStartAction( + new SystemAudioActionFromTv(tv(), mAvrAddress, targetSystemAudioMode, null)); } else { - tv().setSystemAudioMode(isSystemAudioModeOn, true); + // If AVR already has correct system audio mode, update target system audio mode + // immediately rather than starting feature action. + tv().setSystemAudioMode(targetSystemAudioMode); } finish(); } @@ -101,13 +107,15 @@ final class SystemAudioAutoInitiationAction extends HdmiCecFeatureAction { } private void handleSystemAudioModeStatusTimeout() { - if (tv().getSystemAudioModeSetting()) { - if (canChangeSystemAudio()) { - addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true, null)); - } - } else { - tv().setSystemAudioMode(false, true); + if (!canChangeSystemAudio()) { + HdmiLogger.debug("Cannot change system audio mode in auto initiation action."); + finish(); + return; } + // If we can't get the current system audio mode status, just try to turn on/off system + // audio mode according to the system audio control setting. + addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, + tv().isSystemAudioControlFeatureEnabled(), null)); finish(); }