Loading services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java +20 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,10 @@ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { private int mInitialAudioStatusRetriesLeft = 2; // Flag to notify AudioService of the next audio status reported, // regardless of whether the audio status changed. private boolean mForceNextAudioStatusUpdate = false; private static final int STATE_WAIT_FOR_INITIAL_AUDIO_STATUS = 1; private static final int STATE_MONITOR_AUDIO_STATUS = 2; Loading Loading @@ -70,6 +74,17 @@ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { return false; } /** * If AVB has been enabled, send <Give Audio Status> and notify AudioService of the response. */ void requestAndUpdateAudioStatus() { if (mState == STATE_MONITOR_AUDIO_STATUS) { mForceNextAudioStatusUpdate = true; sendGiveAudioStatus(); } } private boolean handleReportAudioStatus(HdmiCecMessage cmd) { if (mTargetAddress != cmd.getSource() || cmd.getParams().length == 0) { return false; Loading @@ -89,12 +104,15 @@ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { localDevice().getService().enableAbsoluteVolumeBehavior(audioStatus); mState = STATE_MONITOR_AUDIO_STATUS; } else if (mState == STATE_MONITOR_AUDIO_STATUS) { if (audioStatus.getVolume() != mLastAudioStatus.getVolume()) { if (mForceNextAudioStatusUpdate || audioStatus.getVolume() != mLastAudioStatus.getVolume()) { localDevice().getService().notifyAvbVolumeChange(audioStatus.getVolume()); } if (audioStatus.getMute() != mLastAudioStatus.getMute()) { if (mForceNextAudioStatusUpdate || audioStatus.getMute() != mLastAudioStatus.getMute()) { localDevice().getService().notifyAvbMuteChange(audioStatus.getMute()); } mForceNextAudioStatusUpdate = false; } mLastAudioStatus = audioStatus; Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +13 −0 Original line number Diff line number Diff line Loading @@ -1047,6 +1047,19 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice { } } /** * If AVB has been enabled, request the System Audio device's audio status and notify * AudioService of its response. */ @ServiceThreadOnly void requestAndUpdateAvbAudioStatus() { assertRunOnServiceThread(); for (AbsoluteVolumeAudioStatusAction action : getActions(AbsoluteVolumeAudioStatusAction.class)) { action.requestAndUpdateAudioStatus(); } } /** * Determines whether {@code targetAddress} supports <Set Audio Volume Level>. Does two things * in parallel: send <Give Features> (to get <Report Features> in response), Loading services/core/java/com/android/server/hdmi/HdmiControlService.java +7 −0 Original line number Diff line number Diff line Loading @@ -4661,6 +4661,13 @@ public class HdmiControlService extends SystemService { // same keycode for all three mute options. keyCode = KeyEvent.KEYCODE_VOLUME_MUTE; break; case AudioManager.ADJUST_SAME: // Query the current audio status of the Audio System and display UI for it // Only for TVs, because Playback devices don't display UI when using AVB if (tv() != null) { tv().requestAndUpdateAvbAudioStatus(); } return; default: return; } Loading services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java +5 −3 Original line number Diff line number Diff line Loading @@ -92,11 +92,11 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { // Default Audio Status given by the System Audio device in its initial <Report Audio Status> // that triggers AVB being enabled private static final AudioStatus INITIAL_SYSTEM_AUDIO_DEVICE_STATUS = protected static final AudioStatus INITIAL_SYSTEM_AUDIO_DEVICE_STATUS = new AudioStatus(50, false); // VolumeInfo passed to AudioDeviceVolumeManager#setDeviceAbsoluteVolumeBehavior to enable AVB private static final VolumeInfo ENABLE_AVB_VOLUME_INFO = protected static final VolumeInfo ENABLE_AVB_VOLUME_INFO = new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) .setMuted(INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute()) .setVolumeIndex(INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume()) Loading @@ -106,6 +106,8 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { private static final int EMPTY_FLAGS = 0; protected static final int STREAM_MUSIC_MAX_VOLUME = 25; protected abstract HdmiCecLocalDevice createLocalDevice(HdmiControlService hdmiControlService); protected abstract int getPhysicalAddress(); Loading Loading @@ -201,7 +203,7 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { Collections.singletonList(getAudioOutputDevice())); // Max volume of STREAM_MUSIC mAudioFramework.setStreamMaxVolume(AudioManager.STREAM_MUSIC, 25); mAudioFramework.setStreamMaxVolume(AudioManager.STREAM_MUSIC, STREAM_MUSIC_MAX_VOLUME); // Receive messages from devices to make sure they're registered in HdmiCecNetwork mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildGiveDevicePowerStatus( Loading services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java +94 −0 Original line number Diff line number Diff line Loading @@ -321,4 +321,98 @@ public class TvToAudioSystemAvbTest extends BaseAbsoluteVolumeBehaviorTest { getLogicalAddress(), getSystemAudioDeviceLogicalAddress(), Constants.AUDIO_VOLUME_STATUS_UNKNOWN)); } /** * Tests that a volume adjustment command with direction ADJUST_SAME causes HdmiControlService * to request the System Audio device's audio status, and notify AudioService of the * audio status. */ @Test public void avbEnabled_audioDeviceVolumeAdjusted_adjustSame_updatesAudioService() { enableAbsoluteVolumeBehavior(); mNativeWrapper.clearResultMessages(); // HdmiControlService receives a volume adjustment with direction ADJUST_SAME mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeAdjusted( getAudioOutputDevice(), ENABLE_AVB_VOLUME_INFO, AudioManager.ADJUST_SAME, AudioDeviceVolumeManager.ADJUST_MODE_NORMAL ); mTestLooper.dispatchAll(); // Device sends <Give Audio Status> assertThat(mNativeWrapper.getResultMessages()).contains( HdmiCecMessageBuilder.buildGiveAudioStatus(getLogicalAddress(), getSystemAudioDeviceLogicalAddress())); clearInvocations(mAudioManager); // Device receives <Report Audio Status> with a new volume and mute state mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildReportAudioStatus( getSystemAudioDeviceLogicalAddress(), getLogicalAddress(), 80, true)); mTestLooper.dispatchAll(); // HdmiControlService calls setStreamVolume and adjustStreamVolume to trigger volume UI verify(mAudioManager).setStreamVolume( eq(AudioManager.STREAM_MUSIC), // Volume level is rescaled to the max volume of STREAM_MUSIC eq(80 * STREAM_MUSIC_MAX_VOLUME / AudioStatus.MAX_VOLUME), eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); verify(mAudioManager).adjustStreamVolume( eq(AudioManager.STREAM_MUSIC), eq(AudioManager.ADJUST_MUTE), eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); } /** * Tests that a volume adjustment command with direction ADJUST_SAME causes HdmiControlService * to request the System Audio device's audio status, and notify AudioService of the * audio status, even if it's unchanged from the previous one. */ @Test public void avbEnabled_audioDeviceVolumeAdjusted_adjustSame_noChange_updatesAudioService() { enableAbsoluteVolumeBehavior(); mNativeWrapper.clearResultMessages(); // HdmiControlService receives a volume adjustment with direction ADJUST_SAME mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeAdjusted( getAudioOutputDevice(), ENABLE_AVB_VOLUME_INFO, AudioManager.ADJUST_SAME, AudioDeviceVolumeManager.ADJUST_MODE_NORMAL ); mTestLooper.dispatchAll(); // Device sends <Give Audio Status> assertThat(mNativeWrapper.getResultMessages()).contains( HdmiCecMessageBuilder.buildGiveAudioStatus(getLogicalAddress(), getSystemAudioDeviceLogicalAddress())); clearInvocations(mAudioManager); // Device receives <Report Audio Status> with the same volume level and mute state that // as when AVB was enabled mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildReportAudioStatus( getSystemAudioDeviceLogicalAddress(), getLogicalAddress(), INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume(), INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute())); mTestLooper.dispatchAll(); // HdmiControlService calls setStreamVolume and adjustStreamVolume to trigger volume UI verify(mAudioManager).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)); verify(mAudioManager).adjustStreamVolume( eq(AudioManager.STREAM_MUSIC), eq(AudioManager.ADJUST_UNMUTE), eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); } } Loading
services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java +20 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,10 @@ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { private int mInitialAudioStatusRetriesLeft = 2; // Flag to notify AudioService of the next audio status reported, // regardless of whether the audio status changed. private boolean mForceNextAudioStatusUpdate = false; private static final int STATE_WAIT_FOR_INITIAL_AUDIO_STATUS = 1; private static final int STATE_MONITOR_AUDIO_STATUS = 2; Loading Loading @@ -70,6 +74,17 @@ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { return false; } /** * If AVB has been enabled, send <Give Audio Status> and notify AudioService of the response. */ void requestAndUpdateAudioStatus() { if (mState == STATE_MONITOR_AUDIO_STATUS) { mForceNextAudioStatusUpdate = true; sendGiveAudioStatus(); } } private boolean handleReportAudioStatus(HdmiCecMessage cmd) { if (mTargetAddress != cmd.getSource() || cmd.getParams().length == 0) { return false; Loading @@ -89,12 +104,15 @@ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { localDevice().getService().enableAbsoluteVolumeBehavior(audioStatus); mState = STATE_MONITOR_AUDIO_STATUS; } else if (mState == STATE_MONITOR_AUDIO_STATUS) { if (audioStatus.getVolume() != mLastAudioStatus.getVolume()) { if (mForceNextAudioStatusUpdate || audioStatus.getVolume() != mLastAudioStatus.getVolume()) { localDevice().getService().notifyAvbVolumeChange(audioStatus.getVolume()); } if (audioStatus.getMute() != mLastAudioStatus.getMute()) { if (mForceNextAudioStatusUpdate || audioStatus.getMute() != mLastAudioStatus.getMute()) { localDevice().getService().notifyAvbMuteChange(audioStatus.getMute()); } mForceNextAudioStatusUpdate = false; } mLastAudioStatus = audioStatus; Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +13 −0 Original line number Diff line number Diff line Loading @@ -1047,6 +1047,19 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice { } } /** * If AVB has been enabled, request the System Audio device's audio status and notify * AudioService of its response. */ @ServiceThreadOnly void requestAndUpdateAvbAudioStatus() { assertRunOnServiceThread(); for (AbsoluteVolumeAudioStatusAction action : getActions(AbsoluteVolumeAudioStatusAction.class)) { action.requestAndUpdateAudioStatus(); } } /** * Determines whether {@code targetAddress} supports <Set Audio Volume Level>. Does two things * in parallel: send <Give Features> (to get <Report Features> in response), Loading
services/core/java/com/android/server/hdmi/HdmiControlService.java +7 −0 Original line number Diff line number Diff line Loading @@ -4661,6 +4661,13 @@ public class HdmiControlService extends SystemService { // same keycode for all three mute options. keyCode = KeyEvent.KEYCODE_VOLUME_MUTE; break; case AudioManager.ADJUST_SAME: // Query the current audio status of the Audio System and display UI for it // Only for TVs, because Playback devices don't display UI when using AVB if (tv() != null) { tv().requestAndUpdateAvbAudioStatus(); } return; default: return; } Loading
services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java +5 −3 Original line number Diff line number Diff line Loading @@ -92,11 +92,11 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { // Default Audio Status given by the System Audio device in its initial <Report Audio Status> // that triggers AVB being enabled private static final AudioStatus INITIAL_SYSTEM_AUDIO_DEVICE_STATUS = protected static final AudioStatus INITIAL_SYSTEM_AUDIO_DEVICE_STATUS = new AudioStatus(50, false); // VolumeInfo passed to AudioDeviceVolumeManager#setDeviceAbsoluteVolumeBehavior to enable AVB private static final VolumeInfo ENABLE_AVB_VOLUME_INFO = protected static final VolumeInfo ENABLE_AVB_VOLUME_INFO = new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) .setMuted(INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute()) .setVolumeIndex(INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume()) Loading @@ -106,6 +106,8 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { private static final int EMPTY_FLAGS = 0; protected static final int STREAM_MUSIC_MAX_VOLUME = 25; protected abstract HdmiCecLocalDevice createLocalDevice(HdmiControlService hdmiControlService); protected abstract int getPhysicalAddress(); Loading Loading @@ -201,7 +203,7 @@ public abstract class BaseAbsoluteVolumeBehaviorTest { Collections.singletonList(getAudioOutputDevice())); // Max volume of STREAM_MUSIC mAudioFramework.setStreamMaxVolume(AudioManager.STREAM_MUSIC, 25); mAudioFramework.setStreamMaxVolume(AudioManager.STREAM_MUSIC, STREAM_MUSIC_MAX_VOLUME); // Receive messages from devices to make sure they're registered in HdmiCecNetwork mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildGiveDevicePowerStatus( Loading
services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java +94 −0 Original line number Diff line number Diff line Loading @@ -321,4 +321,98 @@ public class TvToAudioSystemAvbTest extends BaseAbsoluteVolumeBehaviorTest { getLogicalAddress(), getSystemAudioDeviceLogicalAddress(), Constants.AUDIO_VOLUME_STATUS_UNKNOWN)); } /** * Tests that a volume adjustment command with direction ADJUST_SAME causes HdmiControlService * to request the System Audio device's audio status, and notify AudioService of the * audio status. */ @Test public void avbEnabled_audioDeviceVolumeAdjusted_adjustSame_updatesAudioService() { enableAbsoluteVolumeBehavior(); mNativeWrapper.clearResultMessages(); // HdmiControlService receives a volume adjustment with direction ADJUST_SAME mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeAdjusted( getAudioOutputDevice(), ENABLE_AVB_VOLUME_INFO, AudioManager.ADJUST_SAME, AudioDeviceVolumeManager.ADJUST_MODE_NORMAL ); mTestLooper.dispatchAll(); // Device sends <Give Audio Status> assertThat(mNativeWrapper.getResultMessages()).contains( HdmiCecMessageBuilder.buildGiveAudioStatus(getLogicalAddress(), getSystemAudioDeviceLogicalAddress())); clearInvocations(mAudioManager); // Device receives <Report Audio Status> with a new volume and mute state mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildReportAudioStatus( getSystemAudioDeviceLogicalAddress(), getLogicalAddress(), 80, true)); mTestLooper.dispatchAll(); // HdmiControlService calls setStreamVolume and adjustStreamVolume to trigger volume UI verify(mAudioManager).setStreamVolume( eq(AudioManager.STREAM_MUSIC), // Volume level is rescaled to the max volume of STREAM_MUSIC eq(80 * STREAM_MUSIC_MAX_VOLUME / AudioStatus.MAX_VOLUME), eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); verify(mAudioManager).adjustStreamVolume( eq(AudioManager.STREAM_MUSIC), eq(AudioManager.ADJUST_MUTE), eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); } /** * Tests that a volume adjustment command with direction ADJUST_SAME causes HdmiControlService * to request the System Audio device's audio status, and notify AudioService of the * audio status, even if it's unchanged from the previous one. */ @Test public void avbEnabled_audioDeviceVolumeAdjusted_adjustSame_noChange_updatesAudioService() { enableAbsoluteVolumeBehavior(); mNativeWrapper.clearResultMessages(); // HdmiControlService receives a volume adjustment with direction ADJUST_SAME mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeAdjusted( getAudioOutputDevice(), ENABLE_AVB_VOLUME_INFO, AudioManager.ADJUST_SAME, AudioDeviceVolumeManager.ADJUST_MODE_NORMAL ); mTestLooper.dispatchAll(); // Device sends <Give Audio Status> assertThat(mNativeWrapper.getResultMessages()).contains( HdmiCecMessageBuilder.buildGiveAudioStatus(getLogicalAddress(), getSystemAudioDeviceLogicalAddress())); clearInvocations(mAudioManager); // Device receives <Report Audio Status> with the same volume level and mute state that // as when AVB was enabled mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildReportAudioStatus( getSystemAudioDeviceLogicalAddress(), getLogicalAddress(), INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume(), INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute())); mTestLooper.dispatchAll(); // HdmiControlService calls setStreamVolume and adjustStreamVolume to trigger volume UI verify(mAudioManager).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)); verify(mAudioManager).adjustStreamVolume( eq(AudioManager.STREAM_MUSIC), eq(AudioManager.ADJUST_UNMUTE), eq(AudioManager.FLAG_ABSOLUTE_VOLUME | AudioManager.FLAG_SHOW_UI)); } }