APC: Disable MMAP when a stream is to be captured

As MMAP does not support APC, it is disabled when a render loopback
policy is installed.

Test: adb shell write_sine_callback -pl # mmap is used
      adb shell audiorecorder  --target /data/file1.raw &
      adb shell write_sine_callback -pl # mmap is NOT used
Bug: 129948989
Change-Id: Ia90c24953890de7e19fd99485bf760788f81126d
Signed-off-by: Kevin Rocard <krocard@google.com>
(cherry picked from commit c1dde631401a9cda122cf3058a99e36274906801)
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 7a9c26e..f2b51d9 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -65,10 +65,13 @@
      * @param[in] attributes to consider fowr the research of output descriptor.
      * @param[out] desc to return if an primary output could be found.
      * @param[out] secondaryDesc other desc that the audio should be routed to.
+     * @return OK if the request is valid
+     *         otherwise if the request is not supported
      */
     status_t getOutputForAttr(const audio_attributes_t& attributes, uid_t uid,
-                sp<SwAudioOutputDescriptor> &primaryDesc,
-                std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs);
+                              audio_output_flags_t flags,
+                              sp<SwAudioOutputDescriptor> &primaryDesc,
+                              std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs);
 
     sp<DeviceDescriptor> getDeviceAndMixForInputSource(audio_source_t inputSource,
                                                        const DeviceVector &availableDeviceTypes,
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 1b812c0..26bb354 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -126,21 +126,33 @@
 }
 
 status_t AudioPolicyMixCollection::getOutputForAttr(
-        const audio_attributes_t& attributes, uid_t uid, sp<SwAudioOutputDescriptor> &primaryDesc,
+        const audio_attributes_t& attributes, uid_t uid,
+        audio_output_flags_t flags,
+        sp<SwAudioOutputDescriptor> &primaryDesc,
         std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs)
 {
     ALOGV("getOutputForAttr() querying %zu mixes:", size());
     primaryDesc = 0;
     for (size_t i = 0; i < size(); i++) {
         sp<AudioPolicyMix> policyMix = valueAt(i);
+        const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
+        if (!primaryOutputMix && (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) {
+            // 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;
+        }
+
         sp<SwAudioOutputDescriptor> policyDesc = policyMix->getOutput();
         if (!policyDesc) {
             ALOGV("%s: Skiping %zu: Mix has no output", __func__, i);
             continue;
         }
 
-        const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
-
         if (primaryOutputMix && primaryDesc != 0) {
             ALOGV("%s: Skiping %zu: Primary output already found", __func__, i);
             continue; // Primary output already found
@@ -170,7 +182,7 @@
             }
         }
     }
-    return (primaryDesc == nullptr && secondaryDescs->empty()) ? BAD_VALUE : NO_ERROR;
+    return NO_ERROR;
 }
 
 AudioPolicyMixCollection::MixMatchStatus AudioPolicyMixCollection::mixMatch(
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index bd53f0f..4d121a0 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -963,10 +963,11 @@
     //       otherwise, fallback to the dynamic policies, if none match, query the engine.
     // Secondary outputs are always found by dynamic policies as the engine do not support them
     sp<SwAudioOutputDescriptor> policyDesc;
-    if (mPolicyMixes.getOutputForAttr(*resultAttr, uid, policyDesc, secondaryDescs) != NO_ERROR) {
-        policyDesc = nullptr; // reset getOutputForAttr in case of failure
-        secondaryDescs->clear();
+    status = mPolicyMixes.getOutputForAttr(*resultAttr, uid, *flags, policyDesc, secondaryDescs);
+    if (status != OK) {
+        return status;
     }
+
     // Explicit routing is higher priority then any dynamic policy primary output
     bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && policyDesc != nullptr;
 
@@ -5064,12 +5065,12 @@
     for (size_t i = 0; i < mOutputs.size(); i++) {
         const sp<SwAudioOutputDescriptor>& outputDescriptor = mOutputs[i];
         for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) {
-            // FIXME code duplicated from getOutputForAttrInt
             sp<SwAudioOutputDescriptor> desc;
             std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs;
-            mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(), desc,
-                                          &secondaryDescs);
-            if (!std::equal(client->getSecondaryOutputs().begin(),
+            status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(),
+                                                            client->flags(), desc, &secondaryDescs);
+            if (status != OK ||
+                !std::equal(client->getSecondaryOutputs().begin(),
                             client->getSecondaryOutputs().end(),
                             secondaryDescs.begin(), secondaryDescs.end())) {
                 streamsToInvalidate.insert(client->stream());