From 1d5b154b3b1686bee97f094a8627a803e0f5bc63 Mon Sep 17 00:00:00 2001 From: Jan Sebechlebsky Date: Wed, 7 Jun 2023 10:42:31 +0200 Subject: [PATCH] Allow to specify remote submix device as target for RENDER AudioMix. Bug: 285091923 Test: atest AudioMixUnitTests AudioHostTest Change-Id: I8b3126073288746d73bd29523b3bb2cd04ab072f --- .../android/media/audiopolicy/AudioMix.java | 5 ++ .../audiopolicytest/AudioMixUnitTests.java | 82 +++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index 094a33f3f2bac..ed68d1eb57249 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -455,6 +455,11 @@ public class AudioMix { if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) { throw new IllegalArgumentException("Unsupported device on non-playback mix"); } + } else if (mDeviceSystemType == AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) { + if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) { + throw new IllegalArgumentException( + "DEVICE_OUT_REMOTE_SUBMIX device is not supported on non-playback mix"); + } } else { if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_RENDER) { throw new IllegalArgumentException( diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java index bbca8823dde4b..ac8a7f37c5275 100644 --- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java +++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java @@ -24,7 +24,11 @@ import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_PLAYERS; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_UID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + import android.media.AudioFormat; +import android.media.AudioSystem; import android.media.audiopolicy.AudioMix; import android.media.audiopolicy.AudioMixingRule; import android.media.audiopolicy.AudioPolicyConfig; @@ -145,6 +149,84 @@ public class AudioMixUnitTests { equalsTester.testEquals(); } + @Test + public void buildRenderToRemoteSubmix_success() { + final String deviceAddress = "address"; + final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER) + .setDevice(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, /*address=*/deviceAddress).build(); + + assertEquals(deviceAddress, audioMix.getRegistration()); + assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat()); + assertEquals(AudioMix.ROUTE_FLAG_RENDER, audioMix.getRouteFlags()); + } + + @Test + public void buildLoopbackAndRenderToRemoteSubmix_success() { + final String deviceAddress = "address"; + final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER) + .setDevice(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, /*address=*/deviceAddress).build(); + + assertEquals(deviceAddress, audioMix.getRegistration()); + assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat()); + assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER, audioMix.getRouteFlags()); + } + + @Test + public void buildRenderToSpeaker_success() { + final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER) + .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build(); + + assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat()); + assertEquals(AudioMix.ROUTE_FLAG_RENDER, audioMix.getRouteFlags()); + } + + @Test + public void buildLoopbackForPlayerMix_success() { + final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build(); + + assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat()); + assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK, audioMix.getRouteFlags()); + } + + @Test + public void buildLoopbackWithDevice_throws() { + assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder( + new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK) + .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build()); + } + + @Test + public void buildRenderWithoutDevice_throws() { + assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder( + new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER).build()); + } + + + private static AudioMix writeToAndFromParcel(AudioMix audioMix) { AudioPolicyConfig apc = new AudioPolicyConfig(new ArrayList<>(List.of(audioMix))); Parcel parcel = Parcel.obtain();