APM: update the logic of querying dynamic policy with requesting mmap.

1. Do not allow loopback render when mmap is requested. The reason is
   that currently there is no way to identify the request is shared or
   exclusive.
2. Do not allow dynamic policy if the mix device is selected. The reason
   is that AudioPolicyMixCollection is not aware of if the mix device
   supports mmap or not.

Bug: 300121986
Test: atest audiopolicy_tests AudioPlaybackCaptureTest
Test: screen recording when requesting mmap stream
Change-Id: Iae536704f32eebc44bfb824a25d3a6acf2ddb0c8
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 83e0108..7ee75c7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -295,6 +295,7 @@
     ALOGV("getOutputForAttr() querying %zu mixes:", size());
     primaryMix.clear();
     bool mixesDisallowsRequestedDevice = false;
+    const bool isMmapRequested = (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ);
     for (size_t i = 0; i < size(); i++) {
         sp<AudioPolicyMix> policyMix = itemAt(i);
         const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
@@ -305,6 +306,17 @@
             mixesDisallowsRequestedDevice = true;
         }
 
+        if (!primaryOutputMix && isMmapRequested) {
+            // AAudio does not support MMAP_NO_IRQ loopback render, and there is no way with
+            // the current MmapStreamInterface::start to reject a specific client added to a shared
+            // mmap stream.
+            // As a result all MMAP_NOIRQ requests have to be rejected when an loopback render
+            // policy is present. That ensures no shared mmap stream is used when an loopback
+            // render policy is registered.
+            ALOGD("%s: Rejecting MMAP_NOIRQ request due to LOOPBACK|RENDER mix present.", __func__);
+            return INVALID_OPERATION;
+        }
+
         if (primaryOutputMix && primaryMix != nullptr) {
             ALOGV("%s: Skiping %zu: Primary output already found", __func__, i);
             continue; // Primary output already found
@@ -315,7 +327,7 @@
             continue; // skip the mix
         }
 
-        if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
+        if (isMmapRequested) {
             if (is_mix_loopback(policyMix->mRouteFlags)) {
                 // AAudio MMAP_NOIRQ streams cannot be routed to loopback/loopback+render
                 // using dynamic audio policy.
@@ -323,10 +335,11 @@
                       "audio policy mix.", __func__);
                 return INVALID_OPERATION;
             }
-            if (mixDevice != nullptr && !mixDevice->isMmap()) {
+            if (mixDevice != nullptr) {
+                // TODO(b/301619865): Only disallow the device that doesn't support MMAP.
                 ALOGD("%s: Rejecting MMAP_NOIRQ request matched to dynamic audio policy "
-                      "mix pointing to device %s which doesn't support mmap", __func__,
-                      mixDevice->toString(false).c_str());
+                      "mix pointing to device %s which the mmap support is unknown at this moment",
+                      __func__, mixDevice->toString(false).c_str());
                 return INVALID_OPERATION;
             }
         }
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 110e6bf..6eb59ad 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -2001,7 +2001,9 @@
                                         /*deviceAddress=*/"remote_submix_media"),
                         DPMmapTestParam(MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER,
                                         AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                                        /*deviceAddress=*/"remote_submix_media")));
+                                        /*deviceAddress=*/"remote_submix_media"),
+                        DPMmapTestParam(MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_SPEAKER,
+                                        /*deviceAddress=*/"")));
 
 class AudioPolicyManagerTestDPMixRecordInjection : public AudioPolicyManagerTestDynamicPolicy,
         public testing::WithParamInterface<DPTestParam> {