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

Commit 2248fa1b authored by jiabin's avatar jiabin Committed by Cherrypicker Worker
Browse files

libaudiohal: fix device connection issues.

1. Use the requested config to create port config instead of default
   config when there is not an active one. The reason is that the HAL,
   such as AOSP USB HAL, may require exactly match on the
   configuration when creating patch. The default one may be different
   from the requested one.
2. Reset all unused patches and configs when calling prepareToOpenStream.
   The reason is that the stream may be closed without resetting patch
   and config. Leaving the unused patches and configs may result in
   unable to create new config and patch.
3. When resetting unused port configs, do not reset the initial configs.
   The initial configs work as template config. They should be always
   cached by libaudiohal.
4. Make bit-prefect output flag as an optional flag. When requesting
   without bit-perfect output flag, it should be able to use the mix
   port that has bit-prefect output flag if all other requested flags
   are matched.

Bug: 277955540
Test: make, manully
(cherry picked from https://android-review.googlesource.com/q/commit:28de9b6ead040310c46af53405522e7f5c097cec)
Merged-In: I043d69022d05e154b273492e0729eb45ffa8efad
Change-Id: I043d69022d05e154b273492e0729eb45ffa8efad
parent 40079052
Loading
Loading
Loading
Loading
+44 −6
Original line number Diff line number Diff line
@@ -204,6 +204,9 @@ status_t DeviceHalAidl::initCheck() {
    std::transform(portConfigs.begin(), portConfigs.end(),
            std::inserter(mPortConfigs, mPortConfigs.end()),
            [](const auto& p) { return std::make_pair(p.id, p); });
    std::transform(mPortConfigs.begin(), mPortConfigs.end(),
            std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
            [](const auto& pcPair) { return pcPair.first; });
    std::vector<AudioPatch> patches;
    RETURN_STATUS_IF_ERROR(
            statusTFromBinderStatus(mModule->getAudioPatches(&patches)));  // OK if empty
@@ -357,12 +360,14 @@ status_t DeviceHalAidl::prepareToOpenStream(
            this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
            aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
            aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
    resetUnusedPatchesAndPortConfigs();
    const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
    // Find / create AudioPortConfigs for the device port and the mix port,
    // then find / create a patch between them, and open a stream on the mix port.
    AudioPortConfig devicePortConfig;
    bool created = false;
    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
                                                  &devicePortConfig, &created));
    if (created) {
        cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
    }
@@ -1109,7 +1114,7 @@ status_t DeviceHalAidl::findOrCreatePatch(
    return OK;
}

status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
        AudioPortConfig* portConfig, bool* created) {
    auto portConfigIt = findPortConfig(device);
    if (portConfigIt == mPortConfigs.end()) {
@@ -1121,6 +1126,9 @@ status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
        }
        AudioPortConfig requestedPortConfig;
        requestedPortConfig.portId = portsIt->first;
        if (config != nullptr) {
            setPortConfigFromConfig(&requestedPortConfig, *config);
        }
        RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
                created));
    } else {
@@ -1223,7 +1231,8 @@ status_t DeviceHalAidl::findOrCreatePortConfig(
                portConfig, created);
    } else if (requestedPortConfig.ext.getTag() == Tag::device) {
        return findOrCreatePortConfig(
                requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
                requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
                portConfig, created);
    }
    ALOGW("%s: unsupported audio port config: %s",
            __func__, requestedPortConfig.toString().c_str());
@@ -1252,7 +1261,6 @@ DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device
            [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
}


DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
            const AudioConfig& config, const AudioIoFlags& flags,
            const std::set<int32_t>& destinationPortIds) {
@@ -1265,10 +1273,20 @@ DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
                        std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
                                config.base.sampleRate) != prof.sampleRates.end());
    };
    static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
    int optionalFlags = 0;
    auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
        // Ports should be able to match if the optional flags are not requested.
        return portFlags == flags ||
               (portFlags.getTag() == AudioIoFlags::Tag::output &&
                        AudioIoFlags::make<AudioIoFlags::Tag::output>(
                                portFlags.get<AudioIoFlags::Tag::output>() &
                                        ~optionalFlags) == flags);
    };
    auto matcher = [&](const auto& pair) {
        const auto& p = pair.second;
        return p.ext.getTag() == AudioPortExt::Tag::mix &&
                p.flags == flags &&
                flagMatches(p.flags) &&
                (destinationPortIds.empty() ||
                        std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
                                [&](const int32_t destId) { return mRoutingMatrix.count(
@@ -1276,7 +1294,24 @@ DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
                (p.profiles.empty() ||
                        std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
                        p.profiles.end()); };
    return std::find_if(mPorts.begin(), mPorts.end(), matcher);
    auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
    if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
        auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
        while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
            if (isBitPositionFlagSet(
                        flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
                // If the flag is set by the request, it must be matched.
                ++optionalOutputFlagsIt;
                continue;
            }
            optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
            result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
            ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
                  "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
                    flags.toString().c_str(), mInstance.c_str(), optionalFlags);
        }
    }
    return result;
}

DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
@@ -1358,6 +1393,9 @@ void DeviceHalAidl::resetUnusedPortConfigs() {
        for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
        for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
    }
    for (int32_t id : mInitialPortConfigIds) {
        portConfigIds.erase(id);
    }
    for (int32_t id : portConfigIds) resetPortConfig(id);
}

+2 −0
Original line number Diff line number Diff line
@@ -215,6 +215,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
        ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
    status_t findOrCreatePortConfig(
            const ::aidl::android::media::audio::common::AudioDevice& device,
            const ::aidl::android::media::audio::common::AudioConfig* config,
            ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
            bool* created);
    status_t findOrCreatePortConfig(
@@ -284,6 +285,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
    int32_t mDefaultInputPortId = -1;
    int32_t mDefaultOutputPortId = -1;
    PortConfigs mPortConfigs;
    std::set<int32_t> mInitialPortConfigIds;
    Patches mPatches;
    RoutingMatrix mRoutingMatrix;
    Streams mStreams;