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

Commit 45d5095e authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "audio policy: output selection upon dynamic policy registration" into rvc-dev

parents 385d3352 c209fe49
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@

namespace android {

class AudioPolicyMix;
class DeviceDescriptor;
class HwAudioOutputDescriptor;
class SwAudioOutputDescriptor;
@@ -90,11 +91,12 @@ public:
                          product_strategy_t strategy, VolumeSource volumeSource,
                          audio_output_flags_t flags,
                          bool isPreferredDeviceForExclusiveUse,
                          std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs) :
                          std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs,
                          wp<AudioPolicyMix> primaryMix) :
        ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId,
                         isPreferredDeviceForExclusiveUse),
        mStream(stream), mStrategy(strategy), mVolumeSource(volumeSource), mFlags(flags),
        mSecondaryOutputs(std::move(secondaryOutputs)) {}
        mSecondaryOutputs(std::move(secondaryOutputs)), mPrimaryMix(primaryMix) {}
    ~TrackClientDescriptor() override = default;

    using ClientDescriptor::dump;
@@ -108,6 +110,9 @@ public:
        return mSecondaryOutputs;
    };
    VolumeSource volumeSource() const { return mVolumeSource; }
    const sp<AudioPolicyMix> getPrimaryMix() const {
        return mPrimaryMix.promote();
    };

    void setActive(bool active) override
    {
@@ -136,7 +141,7 @@ private:
    const VolumeSource mVolumeSource;
    const audio_output_flags_t mFlags;
    const std::vector<wp<SwAudioOutputDescriptor>> mSecondaryOutputs;

    const wp<AudioPolicyMix> mPrimaryMix;
    /**
     * required for duplicating thread, prevent from removing active client from an output
     * involved in a duplication.
+4 −1
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ namespace android {

void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const
{
    dst->appendFormat("%*sAudio Policy Mix %d:\n", spaces, "", index + 1);
    dst->appendFormat("%*sAudio Policy Mix %d (%p):\n", spaces, "", index + 1, this);
    std::string mixTypeLiteral;
    if (!MixTypeConverter::toString(mMixType, mixTypeLiteral)) {
        ALOGE("%s: failed to convert mix type %d", __FUNCTION__, mMixType);
@@ -44,6 +44,9 @@ void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const

    dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.string());

    dst->appendFormat("%*s- output: %d\n", spaces, "",
            mOutput == nullptr ? 0 : mOutput->mIoHandle);

    int indexCriterion = 0;
    for (const auto &criterion : mCriteria) {
        dst->appendFormat("%*s- Criterion %d: ", spaces + 2, "", indexCriterion++);
+8 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <TypeConverter.h>
#include "AudioOutputDescriptor.h"
#include "AudioPatch.h"
#include "AudioPolicyMix.h"
#include "ClientDescriptor.h"
#include "DeviceDescriptor.h"
#include "HwModule.h"
@@ -55,6 +56,12 @@ void TrackClientDescriptor::dump(String8 *dst, int spaces, int index) const
    ClientDescriptor::dump(dst, spaces, index);
    dst->appendFormat("%*s- Stream: %d flags: %08x\n", spaces, "", mStream, mFlags);
    dst->appendFormat("%*s- Refcount: %d\n", spaces, "", mActivityCount);
    dst->appendFormat("%*s- DAP Primary Mix: %p\n", spaces, "", mPrimaryMix.promote().get());
    dst->appendFormat("%*s- DAP Secondary Outputs:\n", spaces, "");
    for (auto desc : mSecondaryOutputs) {
        dst->appendFormat("%*s  - %d\n", spaces, "",
                desc.promote() == nullptr ? 0 : desc.promote()->mIoHandle);
    }
}

std::string TrackClientDescriptor::toShortString() const
@@ -88,7 +95,7 @@ SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t
    TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes,
        {config.sample_rate, config.channel_mask, config.format}, AUDIO_PORT_HANDLE_NONE,
        stream, strategy, volumeSource, AUDIO_OUTPUT_FLAG_NONE, false,
        {} /* Sources do not support secondary outputs*/), mSrcDevice(srcDevice)
        {} /* Sources do not support secondary outputs*/, nullptr), mSrcDevice(srcDevice)
{
}

+42 −23
Original line number Diff line number Diff line
@@ -1102,14 +1102,15 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
    };
    *portId = PolicyAudioPort::getNextUniqueId();

    sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
    sp<TrackClientDescriptor> clientDesc =
        new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
                                  sanitizedRequestedPortId, *stream,
                                  mEngine->getProductStrategyForAttributes(resultAttr),
                                  toVolumeSource(resultAttr),
                                  *flags, isRequestedDeviceForExclusiveUse,
                                  std::move(weakSecondaryOutputDescs));
    sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
                                  std::move(weakSecondaryOutputDescs),
                                  outputDesc->mPolicyMix);
    outputDesc->addClient(clientDesc);

    ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__,
@@ -2877,7 +2878,7 @@ status_t AudioPolicyManager::registerPolicyMixes(const Vector<AudioMix>& mixes)
{
    ALOGV("registerPolicyMixes() %zu mix(es)", mixes.size());
    status_t res = NO_ERROR;

    bool checkOutputs = false;
    sp<HwModule> rSubmixModule;
    // examine each mix's route type
    for (size_t i = 0; i < mixes.size(); i++) {
@@ -2996,11 +2997,16 @@ status_t AudioPolicyManager::registerPolicyMixes(const Vector<AudioMix>& mixes)
                        i, type, address.string());
                res = INVALID_OPERATION;
                break;
            } else {
                checkOutputs = true;
            }
        }
    }
    if (res != NO_ERROR) {
        unregisterPolicyMixes(mixes);
    } else if (checkOutputs) {
        checkForDeviceAndOutputChanges();
        updateCallAndOutputRouting();
    }
    return res;
}
@@ -3009,6 +3015,7 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes)
{
    ALOGV("unregisterPolicyMixes() num mixes %zu", mixes.size());
    status_t res = NO_ERROR;
    bool checkOutputs = false;
    sp<HwModule> rSubmixModule;
    // examine each mix's route type
    for (const auto& mix : mixes) {
@@ -3049,9 +3056,15 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes)
            if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
                res = INVALID_OPERATION;
                continue;
            } else {
                checkOutputs = true;
            }
        }
    }
    if (res == NO_ERROR && checkOutputs) {
        checkForDeviceAndOutputChanges();
        updateCallAndOutputRouting();
    }
    return res;
}

@@ -5226,32 +5239,38 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr
    SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevices(oldDevices, mPreviousOutputs);
    SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs);

    // also take into account external policy-related changes: add all outputs which are
    // associated with policies in the "before" and "after" output vectors
    ALOGVV("%s(): policy related outputs", __func__);
    bool hasDynamicPolicy = false;
    for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) {
        const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i);
        if (desc != 0 && desc->mPolicyMix != NULL) {
            srcOutputs.add(desc->mIoHandle);
            hasDynamicPolicy = true;
            ALOGVV(" previous outputs: adding %d", desc->mIoHandle);
    uint32_t maxLatency = 0;
    bool invalidate = false;
    // take into account dynamic audio policies related changes: if a client is now associated
    // to a different policy mix than at creation time, invalidate corresponding stream
    for (size_t i = 0; i < mPreviousOutputs.size() && !invalidate; i++) {
        const sp<SwAudioOutputDescriptor>& desc = mPreviousOutputs.valueAt(i);
        if (desc->isDuplicated()) {
            continue;
        }
        for (const sp<TrackClientDescriptor>& client : desc->getClientIterable()) {
            if (mEngine->getProductStrategyForAttributes(client->attributes()) != psId) {
                continue;
            }
            sp<AudioPolicyMix> primaryMix;
            status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(),
                    client->flags(), primaryMix, nullptr);
            if (status != OK) {
                continue;
            }
            if (client->getPrimaryMix() != primaryMix) {
                invalidate = true;
                if (desc->isStrategyActive(psId)) {
                    maxLatency = desc->latency();
                }
                break;
            }
    for (size_t i = 0 ; i < mOutputs.size() ; i++) {
        const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
        if (desc != 0 && desc->mPolicyMix != NULL) {
            dstOutputs.add(desc->mIoHandle);
            hasDynamicPolicy = true;
            ALOGVV(" new outputs: adding %d", desc->mIoHandle);
        }
    }

    if (srcOutputs != dstOutputs) {
    if (srcOutputs != dstOutputs || invalidate) {
        // get maximum latency of all source outputs to determine the minimum mute time guaranteeing
        // audio from invalidated tracks will be rendered when unmuting
        uint32_t maxLatency = 0;
        bool invalidate = hasDynamicPolicy;
        for (audio_io_handle_t srcOut : srcOutputs) {
            sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
            if (desc == nullptr) continue;