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

Commit 12537fc8 authored by jiabin's avatar jiabin Committed by Mikhail Naganov
Browse files

APM: update logic of populating profiles for dynamic mix port.

For AIDL HAL, use getAudioPort API to query the profiles for the dynamic
mix ports.

For HIDL HAL, if the HAL supports getAudioPort API, add the profiles of
the device port that contain attributes also reported by getParameters
API. The attributes reported by getParameters API but not in device port
will also be added to mix port.

The reason of using getAudioPort API instead of getParameters is that
getAudioPort API can return well structed audio profiles, which show the
correct relationship between audio format and sample rates, channel
masks.

Test: repo steps from the bug
Test: atest audiofoundation_containers_test
Test: atest audiopolicy_tests
Bug: 284033428
Change-Id: I6d3faf49470514c05fe57be755bb868d74d74dbb
parent f591cd5c
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -898,6 +898,22 @@ status_t AudioFlingerClientAdapter::getAudioPolicyConfig(media::AudioPolicyConfi
    return NO_ERROR;
}

status_t AudioFlingerClientAdapter::getAudioMixPort(const struct audio_port_v7 *devicePort,
                                                    struct audio_port_v7 *mixPort) const {
    if (devicePort == nullptr || mixPort == nullptr) {
        return BAD_VALUE;
    }
    media::AudioPortFw devicePortAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_port_v7_AudioPortFw(*devicePort));
    media::AudioPortFw mixPortAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_port_v7_AudioPortFw(*mixPort));
    media::AudioPortFw aidlRet;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            mDelegate->getAudioMixPort(devicePortAidl, mixPortAidl, &aidlRet)));
    *mixPort = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortFw_audio_port_v7(aidlRet));
    return OK;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// AudioFlingerServerAdapter
AudioFlingerServerAdapter::AudioFlingerServerAdapter(
@@ -1444,4 +1460,16 @@ Status AudioFlingerServerAdapter::getAudioPolicyConfig(media::AudioPolicyConfig*
    return Status::fromStatusT(mDelegate->getAudioPolicyConfig(_aidl_return));
}

Status AudioFlingerServerAdapter::getAudioMixPort(const media::AudioPortFw &devicePort,
                                                  const media::AudioPortFw &mixPort,
                                                  media::AudioPortFw *_aidl_return) {
    audio_port_v7 devicePortLegacy = VALUE_OR_RETURN_BINDER(
            aidl2legacy_AudioPortFw_audio_port_v7(devicePort));
    audio_port_v7 mixPortLegacy = VALUE_OR_RETURN_BINDER(
            aidl2legacy_AudioPortFw_audio_port_v7(mixPort));
    RETURN_BINDER_IF_ERROR(mDelegate->getAudioMixPort(&devicePortLegacy, &mixPortLegacy));
    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_port_v7_AudioPortFw(mixPortLegacy));
    return Status::ok();
}

} // namespace android
+5 −0
Original line number Diff line number Diff line
@@ -288,6 +288,11 @@ interface IAudioFlingerService {
     */
    AudioPolicyConfig getAudioPolicyConfig();

    /**
     * Get the attributes of the mix port when connecting to the given device port.
     */
    AudioPortFw getAudioMixPort(in AudioPortFw devicePort, in AudioPortFw mixPort);

    // When adding a new method, please review and update
    // IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
    // AudioFlinger.cpp AudioFlinger::onTransactWrapper()
+9 −0
Original line number Diff line number Diff line
@@ -384,6 +384,9 @@ public:
    virtual status_t supportsBluetoothVariableLatency(bool* support) const = 0;

    virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) = 0;

    virtual status_t getAudioMixPort(const struct audio_port_v7 *devicePort,
                                     struct audio_port_v7 *mixPort) const = 0;
};

/**
@@ -498,6 +501,8 @@ public:
                                   sp<media::ISoundDose>* soundDose) const override;
    status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
    status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) override;
    status_t getAudioMixPort(const struct audio_port_v7 *devicePort,
                             struct audio_port_v7 *mixPort) const override;

private:
    const sp<media::IAudioFlingerService> mDelegate;
@@ -599,6 +604,7 @@ public:
            INVALIDATE_TRACKS = media::BnAudioFlingerService::TRANSACTION_invalidateTracks,
            GET_AUDIO_POLICY_CONFIG =
                    media::BnAudioFlingerService::TRANSACTION_getAudioPolicyConfig,
            GET_AUDIO_MIX_PORT = media::BnAudioFlingerService::TRANSACTION_getAudioMixPort,
        };

    protected:
@@ -732,6 +738,9 @@ public:
                                 sp<media::ISoundDose>* _aidl_return) override;
    Status invalidateTracks(const std::vector<int32_t>& portIds) override;
    Status getAudioPolicyConfig(media::AudioPolicyConfig* _aidl_return) override;
    Status getAudioMixPort(const media::AudioPortFw& devicePort,
                           const media::AudioPortFw& mixPort,
                           media::AudioPortFw* _aidl_return) override;
private:
    const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
};
+100 −0
Original line number Diff line number Diff line
@@ -130,4 +130,104 @@ std::string dumpMixerBehaviors(const MixerBehaviorSet& mixerBehaviors) {
    return ss.str();
}

AudioProfileAttributesMultimap createAudioProfilesAttrMap(audio_profile profiles[],
                                                          uint32_t first,
                                                          uint32_t last) {
    AudioProfileAttributesMultimap result;
    for (uint32_t i = first; i < last; ++i) {
        SampleRateSet sampleRates(profiles[i].sample_rates,
                                  profiles[i].sample_rates + profiles[i].num_sample_rates);
        ChannelMaskSet channelMasks(profiles[i].channel_masks,
                                    profiles[i].channel_masks + profiles[i].num_channel_masks);
        result.emplace(profiles[i].format, std::make_pair(sampleRates, channelMasks));
    }
    return result;
}

namespace {

void populateAudioProfile(audio_format_t format,
                          const ChannelMaskSet& channelMasks,
                          const SampleRateSet& samplingRates,
                          audio_profile* profile) {
    profile->format = format;
    profile->num_channel_masks = 0;
    for (auto it = channelMasks.begin();
         it != channelMasks.end() && profile->num_channel_masks < AUDIO_PORT_MAX_CHANNEL_MASKS;
         ++it) {
        profile->channel_masks[profile->num_channel_masks++] = *it;
    }
    profile->num_sample_rates = 0;
    for (auto it = samplingRates.begin();
         it != samplingRates.end() && profile->num_sample_rates < AUDIO_PORT_MAX_SAMPLING_RATES;
         ++it) {
        profile->sample_rates[profile->num_sample_rates++] = *it;
    }
}

} // namespace

void populateAudioProfiles(const AudioProfileAttributesMultimap& profileAttrs,
                           audio_format_t format,
                           ChannelMaskSet allChannelMasks,
                           SampleRateSet allSampleRates,
                           audio_profile audioProfiles[],
                           uint32_t* numAudioProfiles,
                           uint32_t maxAudioProfiles) {
    if (*numAudioProfiles >= maxAudioProfiles) {
        return;
    }

    const auto lower= profileAttrs.lower_bound(format);
    const auto upper = profileAttrs.upper_bound(format);
    SampleRateSet sampleRatesPresent;
    ChannelMaskSet channelMasksPresent;
    for (auto it = lower; it != upper && *numAudioProfiles < maxAudioProfiles; ++it) {
        SampleRateSet srs;
        std::set_intersection(it->second.first.begin(), it->second.first.end(),
                              allSampleRates.begin(), allSampleRates.end(),
                              std::inserter(srs, srs.begin()));
        if (srs.empty()) {
            continue;
        }
        ChannelMaskSet cms;
        std::set_intersection(it->second.second.begin(), it->second.second.end(),
                              allChannelMasks.begin(), allChannelMasks.end(),
                              std::inserter(cms, cms.begin()));
        if (cms.empty()) {
            continue;
        }
        sampleRatesPresent.insert(srs.begin(), srs.end());
        channelMasksPresent.insert(cms.begin(), cms.end());
        populateAudioProfile(it->first, cms, srs,
                             &audioProfiles[(*numAudioProfiles)++]);
    }
    if (*numAudioProfiles >= maxAudioProfiles) {
        ALOGW("%s, too many audio profiles", __func__);
        return;
    }

    SampleRateSet srs;
    std::set_difference(allSampleRates.begin(), allSampleRates.end(),
                        sampleRatesPresent.begin(), sampleRatesPresent.end(),
                        std::inserter(srs, srs.begin()));
    if (!srs.empty()) {
        populateAudioProfile(format, allChannelMasks, srs,
                             &audioProfiles[(*numAudioProfiles)++]);
    }
    if (*numAudioProfiles >= maxAudioProfiles) {
        ALOGW("%s, too many audio profiles", __func__);
        return;
    }
    ChannelMaskSet cms;
    std::set_difference(allChannelMasks.begin(), allChannelMasks.end(),
                        channelMasksPresent.begin(), channelMasksPresent.end(),
                        std::inserter(cms, cms.begin()));
    if (!cms.empty()) {
        populateAudioProfile(format, cms, allSampleRates,
                             &audioProfiles[(*numAudioProfiles)++]);
    }

}

} // namespace android
+10 −0
Original line number Diff line number Diff line
@@ -383,6 +383,16 @@ void AudioProfileVector::addAllValidProfiles(const AudioProfileVector& audioProf
    }
}

ChannelMaskSet AudioProfileVector::getSupportedChannelMasks() const {
    ChannelMaskSet channelMasks;
    for (const auto& profile : *this) {
        if (profile->isValid()) {
            channelMasks.insert(profile->getChannels().begin(), profile->getChannels().end());
        }
    }
    return channelMasks;
}

ConversionResult<AudioProfileVector>
aidl2legacy_AudioProfileVector(const AudioProfileVector::Aidl& aidl, bool isInput) {
    return convertContainers<AudioProfileVector>(aidl.first, aidl.second,
Loading