diff options
3 files changed, 38 insertions, 32 deletions
diff --git a/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java b/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java index 82786001ab68..202c8941c154 100644 --- a/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java +++ b/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java @@ -98,18 +98,21 @@ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { localDevice().getService().enableAbsoluteVolumeBehavior(audioStatus); mState = STATE_MONITOR_AUDIO_STATUS; } else if (mState == STATE_MONITOR_AUDIO_STATUS) { - // On TV panels, we notify AudioService even if neither volume nor mute state changed. - // This ensures that the user sees volume UI if they tried to adjust the AVR's volume, - // even if the new volume level is the same as the previous one. - boolean notifyAvbVolumeToShowUi = localDevice().getService().isTvDevice() - && audioStatus.equals(mLastAudioStatus); - - if (audioStatus.getVolume() != mLastAudioStatus.getVolume() - || notifyAvbVolumeToShowUi) { + // Update volume in AudioService if it has changed since the last <Report Audio Status> + boolean updateVolume = audioStatus.getVolume() != mLastAudioStatus.getVolume(); + if (updateVolume) { localDevice().getService().notifyAvbVolumeChange(audioStatus.getVolume()); } - if (audioStatus.getMute() != mLastAudioStatus.getMute()) { + // Update mute in AudioService if any of the following conditions are met: + // - The mute status changed + // - The volume changed - we need to make sure mute is set correctly afterwards, since + // setting volume can affect mute status as well as a side effect. + // - We're a TV panel - we want to trigger volume UI on TV panels, so that the user + // always gets visual feedback when they attempt to adjust the AVR's volume/mute. + if ((audioStatus.getMute() != mLastAudioStatus.getMute()) + || updateVolume + || localDevice().getService().isTvDevice()) { localDevice().getService().notifyAvbMuteChange(audioStatus.getMute()); } } 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 e7da26ea38b1..98789ac96e98 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java @@ -519,11 +519,12 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { eq(AudioManager.ADJUST_MUTE), anyInt()); clearInvocations(mAudioManager); - // New volume only: sets volume only + // New volume only: sets both volume and mute. + // Volume changes can affect mute status; we need to set mute afterwards to undo this. receiveReportAudioStatus(32, true); verify(mAudioManager).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), anyInt()); - verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + verify(mAudioManager).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(AudioManager.ADJUST_MUTE), anyInt()); clearInvocations(mAudioManager); @@ -536,17 +537,17 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { clearInvocations(mAudioManager); // Repeat of earlier message: sets neither volume nor mute - // Exception: On TV, volume is set to ensure that UI is shown + // Exception: On TV, mute is set to ensure that UI is shown receiveReportAudioStatus(32, false); + verify(mAudioManager, never()).setStreamVolume(eq(AudioManager.STREAM_MUSIC), + eq(32), anyInt()); if (getDeviceType() == HdmiDeviceInfo.DEVICE_TV) { - verify(mAudioManager).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), - anyInt()); + verify(mAudioManager).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + eq(AudioManager.ADJUST_UNMUTE), anyInt()); } else { - verify(mAudioManager, never()).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), - anyInt()); + verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + eq(AudioManager.ADJUST_UNMUTE), anyInt()); } - verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), - eq(AudioManager.ADJUST_UNMUTE), anyInt()); clearInvocations(mAudioManager); // Volume not within range [0, 100]: sets neither volume nor mute @@ -570,7 +571,8 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { receiveReportAudioStatus(32, false); verify(mAudioManager).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), anyInt()); - verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + // Update mute status because we updated volume + verify(mAudioManager).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(AudioManager.ADJUST_UNMUTE), anyInt()); } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java index a410702e202d..9ad2652e9c63 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java @@ -174,11 +174,12 @@ public abstract class BaseTvToAudioSystemAvbTest extends BaseAbsoluteVolumeBehav eq(AudioManager.ADJUST_MUTE), anyInt()); clearInvocations(mAudioManager); - // New volume only: sets volume only + // New volume only: sets both volume and mute. + // Volume changes can affect mute status; we need to set mute afterwards to undo this. receiveReportAudioStatus(32, true); verify(mAudioManager).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), anyInt()); - verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + verify(mAudioManager).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(AudioManager.ADJUST_MUTE), anyInt()); clearInvocations(mAudioManager); @@ -190,11 +191,11 @@ public abstract class BaseTvToAudioSystemAvbTest extends BaseAbsoluteVolumeBehav eq(AudioManager.ADJUST_UNMUTE), anyInt()); clearInvocations(mAudioManager); - // Repeat of earlier message: sets volume only (to ensure volume UI is shown) + // Repeat of earlier message: sets mute only (to ensure volume UI is shown) receiveReportAudioStatus(32, false); - verify(mAudioManager).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), + verify(mAudioManager, never()).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), anyInt()); - verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + verify(mAudioManager).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(AudioManager.ADJUST_UNMUTE), anyInt()); clearInvocations(mAudioManager); @@ -392,18 +393,18 @@ public abstract class BaseTvToAudioSystemAvbTest extends BaseAbsoluteVolumeBehav INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute())); mTestLooper.dispatchAll(); - // HdmiControlService calls setStreamVolume to trigger volume UI - verify(mAudioManager).setStreamVolume( + // HdmiControlService calls adjustStreamVolume to trigger volume UI + verify(mAudioManager).adjustStreamVolume( + eq(AudioManager.STREAM_MUSIC), + eq(AudioManager.ADJUST_UNMUTE), + eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); + // setStreamVolume is not called because volume didn't change, + // and adjustStreamVolume is sufficient to show volume UI + verify(mAudioManager, never()).setStreamVolume( eq(AudioManager.STREAM_MUSIC), // Volume level is rescaled to the max volume of STREAM_MUSIC eq(INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume() * STREAM_MUSIC_MAX_VOLUME / AudioStatus.MAX_VOLUME), eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); - // adjustStreamVolume is not called because mute status didn't change, - // and setStreamVolume is sufficient to show volume UI - verify(mAudioManager, never()).adjustStreamVolume( - eq(AudioManager.STREAM_MUSIC), - eq(AudioManager.ADJUST_UNMUTE), - eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); } } |