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

Commit 555530ab authored by Eric Laurent's avatar Eric Laurent
Browse files

audio: several concurrent capture fixes

Make sure AudioRecord clients are invalidated synchronously
when closing an input stream instead of when the capture thread
exits.

Fix AudioPolicyManager::getInputForDevice() logic to make sure that
not only the first opened input encountered is considered when looking
for a compatible input to reuse for concurrent capture.

Bug: 22702906
Test: run CTS test
Change-Id: I7f69609d4ee70a37ab06753ff970b12df17d885b
parent c96fc852
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -5976,6 +5976,18 @@ void AudioFlinger::RecordThread::onFirstRef()
    run(mThreadName, PRIORITY_URGENT_AUDIO);
}

void AudioFlinger::RecordThread::preExit()
{
    ALOGV("  preExit()");
    Mutex::Autolock _l(mLock);
    for (size_t i = 0; i < mTracks.size(); i++) {
        sp<RecordTrack> track = mTracks[i];
        track->invalidate();
    }
    mActiveTracks.clear();
    mStartStopCond.broadcast();
}

bool AudioFlinger::RecordThread::threadLoop()
{
    nsecs_t lastWarning = 0;
+1 −0
Original line number Diff line number Diff line
@@ -1346,6 +1346,7 @@ public:

    // Thread virtuals
    virtual bool        threadLoop();
    virtual void        preExit();

    // RefBase
    virtual void        onFirstRef();
+22 −14
Original line number Diff line number Diff line
@@ -1631,8 +1631,8 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
                                                              isSoundTrigger,
                                                              policyMix, mpClientInterface);


    // reuse an open input if possible
    sp<AudioInputDescriptor> reusedInputDesc;
    for (size_t i = 0; i < mInputs.size(); i++) {
        sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
        // reuse input if:
@@ -1656,28 +1656,27 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
                } else {
                    ALOGW("getInputForDevice() record with different attributes"
                          " exists for session %d", session);
                    break;
                    continue;
                }
            } else if (isSoundTrigger) {
                break;
                continue;
            }

            // force close input if current source is now the highest priority request on this input
            // and current input properties are not exactly as requested.
            if (!isConcurrentSource(inputSource) && !isConcurrentSource(desc->inputSource()) &&
            // Reuse the already opened input stream on this profile if:
            // - the new capture source is background OR
            // - the path requested configurations match OR
            // - the new source priority is less than the highest source priority on this input
            // If the input stream cannot be reused, close it before opening a new stream
            // on the same profile for the new client so that the requested path configuration
            // can be selected.
            if (!isConcurrentSource(inputSource) &&
                    ((desc->mSamplingRate != samplingRate ||
                    desc->mChannelMask != channelMask ||
                    !audio_formats_match(desc->mFormat, format)) &&
                    (source_priority(desc->getHighestPrioritySource(false /*activeOnly*/)) <
                     source_priority(inputSource)))) {
                ALOGV("%s: ", __FUNCTION__);
                AudioSessionCollection sessions = desc->getAudioSessions(false /*activeOnly*/);
                for (size_t j = 0; j < sessions.size(); j++) {
                    audio_session_t currentSession = sessions.keyAt(j);
                    stopInput(desc->mIoHandle, currentSession);
                    releaseInput(desc->mIoHandle, currentSession);
                }
                break;
                reusedInputDesc = desc;
                continue;
            } else {
                desc->addAudioSession(session, audioSession);
                ALOGV("%s: reusing input %d", __FUNCTION__, mInputs.keyAt(i));
@@ -1686,6 +1685,15 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
        }
    }

    if (reusedInputDesc != 0) {
        AudioSessionCollection sessions = reusedInputDesc->getAudioSessions(false /*activeOnly*/);
        for (size_t j = 0; j < sessions.size(); j++) {
            audio_session_t currentSession = sessions.keyAt(j);
            stopInput(reusedInputDesc->mIoHandle, currentSession);
            releaseInput(reusedInputDesc->mIoHandle, currentSession);
        }
    }

    audio_config_t config = AUDIO_CONFIG_INITIALIZER;
    config.sample_rate = profileSamplingRate;
    config.channel_mask = profileChannelMask;