summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yan Han <yanha@google.com> 2023-12-14 12:27:41 +0100
committer Yan Han <yanha@google.com> 2023-12-19 11:40:15 +0100
commita7d5914203096cef196d6233342418fa3ffc711f (patch)
treebc2845c2cf3b4b4e5d284fbd3d7798ea31ec5acb
parent330a4fc26d4990c8994d559668cd2debbb270c4d (diff)
Disable absolute volume behavior on standby
Currently, AbsoluteVolumeAudioStatusAction is always removed on Standby, but we do not always switch away from absolute volume behavior. AVB is usually disabled on standby when System Audio Mode is disabled. However, some soundbars don't do this, creating a situation where AVB is enabled but no AbsoluteVolumeAudioStatusAction exists. This prevents AudioService from receiving volume changes and displaying UI. This CL fixes the issue by ensuring that AVB is always disabled when AbsoluteVolumeAudioStatusAction is removed. It should no longer be possible to have AVB enabled without the action existing. Bug: 312381205 Test: atest TvToAudioSystemArcAvbTest#avbEnabled_standby_avbDisabled Change-Id: Ib430b1f2f7a0683551d424084d1b038c2d23913f
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java1
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java1
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java1
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java32
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java8
5 files changed, 32 insertions, 11 deletions
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 64abb81d0e7a..81204ef5d7ed 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -1314,7 +1314,6 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice {
*/
protected void disableDevice(
boolean initiatedByCec, final PendingActionClearedCallback originalCallback) {
- removeAction(AbsoluteVolumeAudioStatusAction.class);
removeAction(SetAudioVolumeLevelDiscoveryAction.class);
removeAction(ActiveSourceAction.class);
removeAction(ResendCecCommandAction.class);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
index 7e8a2cc6d835..04977e978a7b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
@@ -307,7 +307,6 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
protected void disableDevice(boolean initiatedByCec, PendingActionClearedCallback callback) {
removeAction(OneTouchPlayAction.class);
removeAction(DevicePowerStatusAction.class);
- removeAction(AbsoluteVolumeAudioStatusAction.class);
super.disableDevice(initiatedByCec, callback);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 168715713f8d..b07ed451bcfe 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1331,7 +1331,6 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
removeAction(OneTouchRecordAction.class);
removeAction(TimerRecordingAction.class);
removeAction(NewDeviceAction.class);
- removeAction(AbsoluteVolumeAudioStatusAction.class);
// Remove pending actions.
removeAction(RequestActiveSourceAction.class);
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index b3926fd1b5ba..967edbfcd9c6 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -3792,6 +3792,11 @@ public class HdmiControlService extends SystemService {
}
}
});
+
+ // Make sure we switch away from absolute volume behavior (AVB) when entering standby.
+ // We do this because AVB should not be used unless AbsoluteVolumeAudioStatusAction exists,
+ // and the action cannot exist in standby because there are no local devices.
+ checkAndUpdateAbsoluteVolumeBehavior();
}
boolean canGoToStandby() {
@@ -4445,10 +4450,11 @@ public class HdmiControlService extends SystemService {
* This allows the volume level of the System Audio device to be tracked and set by Android.
*
* Absolute volume behavior requires the following conditions:
- * 1. If the System Audio Device is an Audio System: System Audio Mode is active
- * 2. All AVB-capable audio output devices are already using full/absolute volume behavior
- * 3. CEC volume is enabled
- * 4. The System Audio device supports the <Set Audio Volume Level> message
+ * 1. The device is not in standby or transient to standby
+ * 2. If the System Audio Device is an Audio System: System Audio Mode is active
+ * 3. All AVB-capable audio output devices are already using full/absolute volume behavior
+ * 4. CEC volume is enabled
+ * 5. The System Audio device supports the <Set Audio Volume Level> message
*
* This method enables adjust-only absolute volume behavior on TV panels when conditions
* 1, 2, and 3 are met, but condition 4 is not. This allows TVs to track the volume level of
@@ -4464,10 +4470,16 @@ public class HdmiControlService extends SystemService {
return;
}
+ // Condition 1: The device is not in standby or transient to standby
+ if (mPowerStatusController != null && isPowerStandbyOrTransient()) {
+ switchToFullVolumeBehavior();
+ return;
+ }
+
HdmiCecLocalDevice localCecDevice;
if (isTvDevice() && tv() != null) {
localCecDevice = tv();
- // Condition 1: TVs need System Audio Mode to be active
+ // Condition 2: TVs need System Audio Mode to be active
// (Doesn't apply to Playback Devices, where if SAM isn't active, we assume the
// TV is the System Audio Device instead.)
if (!isSystemAudioActivated()) {
@@ -4484,7 +4496,7 @@ public class HdmiControlService extends SystemService {
HdmiDeviceInfo systemAudioDeviceInfo = getDeviceInfo(
localCecDevice.findAudioReceiverAddress());
- // Condition 2: All AVB-capable audio outputs already use full/absolute volume behavior
+ // Condition 3: All AVB-capable audio outputs already use full/absolute volume behavior
// We only need to check the first AVB-capable audio output because only TV panels
// have more than one of them, and they always have the same volume behavior.
@AudioManager.DeviceVolumeBehavior int currentVolumeBehavior =
@@ -4492,7 +4504,7 @@ public class HdmiControlService extends SystemService {
boolean alreadyUsingFullOrAbsoluteVolume =
FULL_AND_ABSOLUTE_VOLUME_BEHAVIORS.contains(currentVolumeBehavior);
- // Condition 3: CEC volume is enabled
+ // Condition 4: CEC volume is enabled
boolean cecVolumeEnabled =
getHdmiCecVolumeControl() == HdmiControlManager.VOLUME_CONTROL_ENABLED;
@@ -4508,7 +4520,7 @@ public class HdmiControlService extends SystemService {
return;
}
- // Condition 4: The System Audio device supports <Set Audio Volume Level>
+ // Condition 5: The System Audio device supports <Set Audio Volume Level>
switch (systemAudioDeviceInfo.getDeviceFeatures().getSetAudioVolumeLevelSupport()) {
case DeviceFeatures.FEATURE_SUPPORTED:
if (currentVolumeBehavior != AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE) {
@@ -4555,6 +4567,8 @@ public class HdmiControlService extends SystemService {
* are currently used. Removes the action for handling volume updates for these behaviors.
*/
private void switchToFullVolumeBehavior() {
+ Slog.d(TAG, "Switching to full volume behavior");
+
if (playback() != null) {
playback().removeAvbAudioStatusAction();
} else if (tv() != null) {
@@ -4596,12 +4610,14 @@ public class HdmiControlService extends SystemService {
// Otherwise, enable adjust-only AVB on TVs only.
if (systemAudioDevice.getDeviceFeatures().getSetAudioVolumeLevelSupport()
== DeviceFeatures.FEATURE_SUPPORTED) {
+ Slog.d(TAG, "Enabling absolute volume behavior");
for (AudioDeviceAttributes device : getAvbCapableAudioOutputDevices()) {
getAudioDeviceVolumeManager().setDeviceAbsoluteVolumeBehavior(
device, volumeInfo, mServiceThreadExecutor,
mAbsoluteVolumeChangedListener, true);
}
} else if (tv() != null) {
+ Slog.d(TAG, "Enabling adjust-only absolute volume behavior");
for (AudioDeviceAttributes device : getAvbCapableAudioOutputDevices()) {
getAudioDeviceVolumeManager().setDeviceAbsoluteVolumeAdjustOnlyBehavior(
device, volumeInfo, mServiceThreadExecutor,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
index a63d01b6225a..e7da26ea38b1 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
@@ -456,6 +456,14 @@ public abstract class BaseAbsoluteVolumeBehaviorTest {
}
@Test
+ public void avbEnabled_standby_avbDisabled() {
+ enableAbsoluteVolumeBehavior();
+ mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF);
+ assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo(
+ AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL);
+ }
+
+ @Test
public void avbEnabled_cecVolumeDisabled_avbDisabled() {
enableAbsoluteVolumeBehavior();