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

Commit 8932a7dd authored by Eric Laurent's avatar Eric Laurent Committed by Automerger Merge Worker
Browse files

Merge "[BUG] AudioPolicy: fix AudioDeviceCallback" into tm-qpr-dev am: 25c68079

parents 3775b96a 25c68079
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -239,12 +239,13 @@ public:
    }
    void setUseSwBridge() { mUseSwBridge = true; }
    bool useSwBridge() const { return mUseSwBridge; }
    bool canCloseOutput() const { return mCloseOutput; }
    bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; }
    audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }
    sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; }
    sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; }
    wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; }
    void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput);
    void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput, bool closeOutput = false);
    wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; }
    void setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput);

@@ -258,6 +259,15 @@ public:
    wp<SwAudioOutputDescriptor> mSwOutput;
    wp<HwAudioOutputDescriptor> mHwOutput;
    bool mUseSwBridge = false;
    /**
     * For either HW bridge associated to a SwOutput for activity / volume or SwBridge for also
     * sample rendering / activity & volume, an existing playback thread may be reused (e.g.
     * not already opened at APM startup or Direct Output).
     * If reusing an already opened output, when this output is not used anymore, the AudioFlinger
     * patch must be updated to refine the output device(s) information and ensure the right
     * behavior of AudioDeviceCallback.
     */
    bool mCloseOutput = false;
};

/**
+3 −1
Original line number Diff line number Diff line
@@ -105,9 +105,11 @@ SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t
{
}

void SourceClientDescriptor::setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput)
void SourceClientDescriptor::setSwOutput(
        const sp<SwAudioOutputDescriptor>& swOutput, bool closeOutput)
{
    mSwOutput = swOutput;
    mCloseOutput = closeOutput;
}

void SourceClientDescriptor::setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput)
+26 −13
Original line number Diff line number Diff line
@@ -4568,7 +4568,8 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
                        ALOGE("%s output is duplicated", __func__);
                        return INVALID_OPERATION;
                    }
                    sourceDesc->setSwOutput(outputDesc);
                    bool closeOutput = outputDesc->mDirectOpenCount != 0;
                    sourceDesc->setSwOutput(outputDesc, closeOutput);
                } else {
                    // Same for "raw patches" aka created from createAudioPatch API
                    SortedVector<audio_io_handle_t> outputs =
@@ -4587,7 +4588,7 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
                              __func__, sinkDevice->toString().c_str());
                        return INVALID_OPERATION;
                    }
                    sourceDesc->setSwOutput(outputDesc);
                    sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false);
                }
                // create a software bridge in PatchPanel if:
                // - source and sink devices are on different HW modules OR
@@ -4717,17 +4718,29 @@ status_t AudioPolicyManager::releaseAudioPatchInternal(audio_patch_handle_t hand
                // releaseOutput has already called closeOutput in case of direct output
                return NO_ERROR;
            }
            if (!outputDesc->isActive() && !sourceDesc->useSwBridge()) {
                resetOutputDevice(outputDesc);
            } else {
                // Reuse patch handle if still valid / do not force rerouting if still routed
            patchHandle = outputDesc->getPatchHandle();
            // When a Sw bridge is released, the mixer used by this bridge will release its
            // patch at AudioFlinger side. Hence, the mixer audio patch must be recreated
            // Reuse patch handle to force audio flinger removing initial mixer patch removal
            // updating hal patch handle (prevent leaks).
            // While using a HwBridge, force reconsidering device only if not reusing an existing
            // output and no more activity on output (will force to close).
            bool force = sourceDesc->useSwBridge() ||
                    (sourceDesc->canCloseOutput() && !outputDesc->isActive());
            // APM pattern is to have always outputs opened / patch realized for reachable devices.
            // Update device may result to NONE (empty), coupled with force, it releases the patch.
            // Reconsider device only for cases:
            //      1 / Active Output
            //      2 / Inactive Output previously hosting HwBridge
            //      3 / Inactive Output previously hosting SwBridge that can be closed.
            bool updateDevice = outputDesc->isActive() || !sourceDesc->useSwBridge() ||
                    sourceDesc->canCloseOutput();
            setOutputDevices(outputDesc,
                                 getNewOutputDevices(outputDesc, true /*fromCache*/),
                                 patchHandle == AUDIO_PATCH_HANDLE_NONE, /*force*/
                             updateDevice ? getNewOutputDevices(outputDesc, true /*fromCache*/) :
                                            outputDesc->devices(),
                             force,
                             0,
                             patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle);
            }
        } else {
            return BAD_VALUE;
        }