Merge "Ignore select SystemUI tests on TV." into main
diff --git a/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java b/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java
index d764ec4..9172dc0 100644
--- a/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java
@@ -32,6 +32,10 @@
 
     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;
 
@@ -70,6 +74,17 @@
         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;
@@ -89,12 +104,15 @@
             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;
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 207d38e..0671464 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -1048,6 +1048,19 @@
     }
 
     /**
+     * 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),
      * and send <Set Audio Volume Level> (to see if it gets a <Feature Abort> in response).
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 5abb2b5..99fa3a3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -4661,6 +4661,13 @@
                     // 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;
             }
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 3a20cd9..f2242bf 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -2188,11 +2188,10 @@
             MediaSessionRecordImpl session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
                     : mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();
 
-            boolean preferSuggestedStream = false;
-            if (isValidLocalStreamType(suggestedStream)
-                    && AudioSystem.isStreamActive(suggestedStream, 0)) {
-                preferSuggestedStream = true;
-            }
+            boolean preferSuggestedStream =
+                    isValidLocalStreamType(suggestedStream)
+                            && AudioSystem.isStreamActive(suggestedStream, 0);
+
             if (session == null || preferSuggestedStream) {
                 if (DEBUG_KEY_EVENT) {
                     Log.d(TAG, "Adjusting suggestedStream=" + suggestedStream + " by " + direction
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 399655ffa..e6d326a 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
@@ -92,11 +92,11 @@
 
     // 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())
@@ -106,6 +106,8 @@
 
     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();
@@ -201,7 +203,7 @@
                 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(
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java b/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java
index 024e36d..86647fc 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java
@@ -321,4 +321,98 @@
                         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));
+    }
 }