Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ca6c6f6 authored by jiabin's avatar jiabin
Browse files

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
parent be4c6404
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -295,6 +295,7 @@ status_t AudioPolicyMixCollection::getOutputForAttr(
    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 @@ status_t AudioPolicyMixCollection::getOutputForAttr(
            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 @@ status_t AudioPolicyMixCollection::getOutputForAttr(
            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 @@ status_t AudioPolicyMixCollection::getOutputForAttr(
                      "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;
            }
        }
+3 −1
Original line number Diff line number Diff line
@@ -2001,7 +2001,9 @@ INSTANTIATE_TEST_SUITE_P(
                                        /*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> {