Preference multichannel pcm direct output over stereo mixer

If a direct output is available for a multichannel output request,
and the mixer outputs a channel count lower than the track, try the
direct output first, and fall-back to the non-direct output if
not successful.

Bug: 238286324
Test: atest audiopolicy_tests:AudioPolicyManagerCarTest#GetOutputForAttrAtmosOutputAfterRegisteringPolicyMix
Change-Id: Ic7265bd09556ab7dd0660df5b307d151abace503
Merged-In: Ic7265bd09556ab7dd0660df5b307d151abace503
(cherry picked from commit ecbf2ee4797255fc1290b237bd9492e91269f1a8)
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 4fd750a..43b1a2a 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1733,7 +1733,7 @@
     dumpToLog();
 }
 
-TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrEncodedOutputAfterRegisteringPolicyMix) {
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrAtmosOutputAfterRegisteringPolicyMix) {
     status_t ret;
     audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
     const std::string kTestBusMediaOutput = "bus0_media_out";
@@ -1752,6 +1752,18 @@
     ASSERT_EQ(AUDIO_FORMAT_E_AC3_JOC, outDesc->getFormat());
     ASSERT_EQ(AUDIO_CHANNEL_OUT_5POINT1, outDesc->getChannelMask());
     ASSERT_EQ(k48000SamplingRate, outDesc->getSamplingRate());
+
+    selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+    output = AUDIO_IO_HANDLE_NONE;
+    portId = AUDIO_PORT_HANDLE_NONE;
+    getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_7POINT1POINT4,
+            k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId);
+    ASSERT_NE(AUDIO_PORT_HANDLE_NONE, selectedDeviceId);
+    outDesc = mManager->getOutputs().valueFor(output);
+    ASSERT_NE(nullptr, outDesc.get());
+    ASSERT_EQ(AUDIO_FORMAT_PCM_16_BIT, outDesc->getFormat());
+    ASSERT_EQ(AUDIO_CHANNEL_OUT_7POINT1POINT4, outDesc->getChannelMask());
+    ASSERT_EQ(k48000SamplingRate, outDesc->getSamplingRate());
 }
 
 class AudioPolicyManagerTVTest : public AudioPolicyManagerTestWithConfigurationFile {
diff --git a/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml b/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml
index e3b2838..d131ed8 100644
--- a/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml
@@ -55,6 +55,12 @@
                              samplingRates="48000"
                              channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1"/>
                 </mixPort>
+                <mixPort name="mixport_bus0_media_out_atmos_pcm" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
+                </mixPort>
                 <mixPort name="mixport_bus1_navigation_out" role="source">
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000"
@@ -129,6 +135,8 @@
                     <profile name="" format="AUDIO_FORMAT_E_AC3_JOC"
                             samplingRates="48000"
                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
                     <gains>
                         <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                 minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
@@ -276,7 +284,7 @@
             <!-- route declaration, i.e. list all available sources for a given sink -->
             <routes>
                 <route type="mix" sink="bus0_media_out"
-                        sources="mixport_bus0_media_out,mixport_bus0_media_out_atmos"/>
+                        sources="mixport_bus0_media_out,mixport_bus0_media_out_atmos,mixport_bus0_media_out_atmos_pcm"/>
                 <route type="mix" sink="bus1_navigation_out" sources="mixport_bus1_navigation_out"/>
                 <route type="mix" sink="bus2_voice_command_out"
                         sources="mixport_bus2_voice_command_out"/>