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

Commit 85732f41 authored by Eric Laurent's avatar Eric Laurent
Browse files

audio policy: fix mmap stream invalidation logic

Implement a MMAP stream invalidation logic consistent with AAudio
disconnect callback policy.

- When a MMAP stream is opened with a preferred device selection:
  Invalidate the stream only when the preferred device becomes unavailable,
  either because disconnected or not selectable by highest priority use case.
- When a MMAP stream is opened without explicit device selection:
  Invalidate the stream when current device selection changes due to the
  routing rules applicable to the stream's audio attributes (attributes
  of first client on that stream).

Bug: 144020984
Test: OboeTester > TEST DISCONNECT

Change-Id: I70fde0bc8ab9d544b8d3badb713e6239d792cbdb
parent f57740fc
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -41,12 +41,25 @@ sp<DeviceDescriptor> findPreferredDevice(
        IoDescriptor& desc, Filter filter, bool& active, const DeviceVector& devices)
{
    auto activeClients = desc->clientsList(true /*activeOnly*/);
    active = activeClients.size() > 0;

    if (active) {
        // On MMAP IOs, the preferred device is selected by the first client (virtual client
        // created when the mmap stream is opened). This client is never active.
        // On non MMAP IOs, the preferred device is honored only if all active clients have
        // a preferred device in which case the first client drives the selection.
        if (desc->getPolicyAudioPort()->isMmap()) {
            // The client list is never empty on a MMAP IO
            return devices.getDeviceFromId(
                    desc->clientsList(false /*activeOnly*/)[0]->preferredDeviceId());
        } else {
            auto activeClientsWithRoute =
                desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/);
    active = activeClients.size() > 0;
    if (active && activeClients.size() == activeClientsWithRoute.size()) {
            if (activeClients.size() == activeClientsWithRoute.size()) {
                return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId());
            }
        }
    }
    return nullptr;
}

+9 −0
Original line number Diff line number Diff line
@@ -107,6 +107,15 @@ public:
                (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
    }

    inline bool isMmap() const
    {
        return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX)
                && (((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
                        ((mFlags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0))
                    || ((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SINK) &&
                        ((mFlags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)));
    }

    void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
    const AudioRouteVector &getRoutes() const { return mRoutes; }

+1 −3
Original line number Diff line number Diff line
@@ -2406,9 +2406,7 @@ void AudioPolicyManager::checkCloseInputs() {
    for (size_t i = 0; i < mInputs.size(); i++) {
        const sp<AudioInputDescriptor> input = mInputs.valueAt(i);
        if (input->clientsList().size() == 0
                || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())
                || (input->getPolicyAudioPort()->getFlags()
                        & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
                || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) {
            inputsToClose.push_back(mInputs.keyAt(i));
        } else {
            bool close = false;