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

Commit f615203d authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12623742 from 432d3f55 to 25Q1-release

Change-Id: I77d25507c0441a5f2321ac3c774ef8ce567081bd
parents 98d943e7 432d3f55
Loading
Loading
Loading
Loading
+24 −17
Original line number Diff line number Diff line
@@ -69,29 +69,36 @@ ConversionResult<AudioHalCapRule::CriterionRule> convertCriterionRuleToAidl(
    std::string criterionName = xsdcRule.getSelectionCriterion();
    std::string criterionValue = xsdcRule.getValue();
    if (iequals(criterionName, toString(Tag::availableInputDevices))) {
        rule.criterion = AudioHalCapCriterionV2::make<Tag::availableInputDevices>();
        rule.criterionTypeValue =
                VALUE_OR_RETURN(convertDeviceTypeToAidl(gLegacyInputDevicePrefix + criterionValue));
        AudioHalCapCriterionV2::AvailableDevices value;
        value.values.emplace_back(VALUE_OR_RETURN(
                convertDeviceTypeToAidl(gLegacyInputDevicePrefix + criterionValue)));
        rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::availableInputDevices>(value);

    } else if (iequals(criterionName, toString(Tag::availableOutputDevices))) {
        rule.criterion = AudioHalCapCriterionV2::make<Tag::availableOutputDevices>();
        rule.criterionTypeValue = VALUE_OR_RETURN(
                convertDeviceTypeToAidl(gLegacyOutputDevicePrefix + criterionValue));
        AudioHalCapCriterionV2::AvailableDevices value;
        value.values.emplace_back(VALUE_OR_RETURN(
                convertDeviceTypeToAidl(gLegacyOutputDevicePrefix + criterionValue)));
        rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::availableOutputDevices>(value);
    } else if (iequals(criterionName, toString(Tag::availableInputDevicesAddresses))) {
        rule.criterion = AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>();
        rule.criterionTypeValue =
                AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(criterionValue);
        AudioHalCapCriterionV2::AvailableDevicesAddresses value;
        value.values.emplace_back(criterionValue);
        rule.criterionAndValue =
                AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>(value);
    } else if (iequals(criterionName, toString(Tag::availableOutputDevicesAddresses))) {
        rule.criterion = AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>();
        rule.criterionTypeValue =
                AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(criterionValue);
        AudioHalCapCriterionV2::AvailableDevicesAddresses value;
        value.values.emplace_back(criterionValue);
        rule.criterionAndValue =
                AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>(value);
    } else if (iequals(criterionName, toString(Tag::telephonyMode))) {
        rule.criterion = AudioHalCapCriterionV2::make<Tag::telephonyMode>();
        rule.criterionTypeValue = VALUE_OR_RETURN(convertTelephonyModeToAidl(criterionValue));
        AudioHalCapCriterionV2::TelephonyMode value;
        value.values.emplace_back(VALUE_OR_RETURN(convertTelephonyModeToAidl(criterionValue)));
        rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::telephonyMode>(value);
    } else if (!fastcmp<strncmp>(criterionName.c_str(), kXsdcForceConfigForUse,
            strlen(kXsdcForceConfigForUse))) {
        rule.criterion = AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(
                VALUE_OR_RETURN(convertForceUseCriterionToAidl(criterionName)));
        rule.criterionTypeValue = VALUE_OR_RETURN(convertForcedConfigToAidl(criterionValue));
        AudioHalCapCriterionV2::ForceConfigForUse value;
        value.forceUse = VALUE_OR_RETURN(convertForceUseCriterionToAidl(criterionName));
        value.values.emplace_back(VALUE_OR_RETURN(convertForcedConfigToAidl(criterionValue)));
        rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(value);
    } else {
        LOG(ERROR) << __func__ << " unrecognized criterion " << criterionName;
        return unexpected(BAD_VALUE);
+107 −33
Original line number Diff line number Diff line
@@ -467,58 +467,132 @@ ndk::ScopedAStatus Module::updateStreamsConnectedState(const AudioPatch& oldPatc
            fillConnectionsHelper(connections, patch.sinkPortConfigIds, patch.sourcePortConfigIds);
        }  // Otherwise, there are no streams to notify.
    };
    auto restoreOldConnections = [&](const std::set<int32_t>& mixPortIds,
                                     const bool continueWithEmptyDevices) {
        for (const auto mixPort : mixPortIds) {
            if (auto it = oldConnections.find(mixPort);
                continueWithEmptyDevices || it != oldConnections.end()) {
                const std::vector<AudioDevice> d =
                        it != oldConnections.end() ? getDevicesFromDevicePortConfigIds(it->second)
                                                   : std::vector<AudioDevice>();
                if (auto status = mStreams.setStreamConnectedDevices(mixPort, d); status.isOk()) {
                    LOG(WARNING) << ":updateStreamsConnectedState: rollback: mix port config:"
                                 << mixPort
                                 << (d.empty() ? "; not connected"
                                               : std::string("; connected to ") +
                                                         ::android::internal::ToString(d));
                } else {
                    // can't do much about rollback failures
                    LOG(ERROR)
                            << ":updateStreamsConnectedState: rollback: failed for mix port config:"
                            << mixPort;
                }
            }
        }
    };
    fillConnections(oldConnections, oldPatch);
    fillConnections(newConnections, newPatch);
    /**
     * Illustration of oldConnections and newConnections
     *
     * oldConnections {
     * a : {A,B,C},
     * b : {D},
     * d : {H,I,J},
     * e : {N,O,P},
     * f : {Q,R},
     * g : {T,U,V},
     * }
     *
     * newConnections {
     * a : {A,B,C},
     * c : {E,F,G},
     * d : {K,L,M},
     * e : {N,P},
     * f : {Q,R,S},
     * g : {U,V,W},
     * }
     *
     * Expected routings:
     *      'a': is ignored both in disconnect step and connect step,
     *           due to same devices both in oldConnections and newConnections.
     *      'b': handled only in disconnect step with empty devices because 'b' is only present
     *           in oldConnections.
     *      'c': handled only in connect step with {E,F,G} devices because 'c' is only present
     *           in newConnections.
     *      'd': handled only in connect step with {K,L,M} devices because 'd' is also present
     *           in newConnections and it is ignored in disconnected step.
     *      'e': handled only in connect step with {N,P} devices because 'e' is also present
     *           in newConnections and it is ignored in disconnect step. please note that there
     *           is no exclusive disconnection for device {O}.
     *      'f': handled only in connect step with {Q,R,S} devices because 'f' is also present
     *           in newConnections and it is ignored in disconnect step. Even though stream is
     *           already connected with {Q,R} devices and connection happens with {Q,R,S}.
     *      'g': handled only in connect step with {U,V,W} devices because 'g' is also present
     *           in newConnections and it is ignored in disconnect step. There is no exclusive
     *           disconnection with devices {T,U,V}.
     *
     *       If, any failure, will lead to restoreOldConnections (rollback).
     *       The aim of the restoreOldConnections is to make connections back to oldConnections.
     *       Failures in restoreOldConnections aren't handled.
     */

    std::for_each(oldConnections.begin(), oldConnections.end(), [&](const auto& connectionPair) {
        const int32_t mixPortConfigId = connectionPair.first;
        if (auto it = newConnections.find(mixPortConfigId);
            it == newConnections.end() || it->second != connectionPair.second) {
            if (auto status = mStreams.setStreamConnectedDevices(mixPortConfigId, {});
    std::set<int32_t> idsToConnectBackOnFailure;
    // disconnection step
    for (const auto& [oldMixPortConfigId, oldDevicePortConfigIds] : oldConnections) {
        if (auto it = newConnections.find(oldMixPortConfigId); it == newConnections.end()) {
            idsToConnectBackOnFailure.insert(oldMixPortConfigId);
            if (auto status = mStreams.setStreamConnectedDevices(oldMixPortConfigId, {});
                status.isOk()) {
                LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
                           << mixPortConfigId << " has been disconnected";
                LOG(DEBUG) << __func__ << ": The stream on port config id " << oldMixPortConfigId
                           << " has been disconnected";
            } else {
                // Disconnection is tricky to roll back, just register a failure.
                maybeFailure = std::move(status);
                // proceed to rollback even on one failure
                break;
            }
        }
    });
    if (!maybeFailure.isOk()) return maybeFailure;
    std::set<int32_t> idsToDisconnectOnFailure;
    std::for_each(newConnections.begin(), newConnections.end(), [&](const auto& connectionPair) {
        const int32_t mixPortConfigId = connectionPair.first;
        if (auto it = oldConnections.find(mixPortConfigId);
            it == oldConnections.end() || it->second != connectionPair.second) {
            const auto connectedDevices = getDevicesFromDevicePortConfigIds(connectionPair.second);
    }

    if (!maybeFailure.isOk()) {
        restoreOldConnections(idsToConnectBackOnFailure, false /*continueWithEmptyDevices*/);
        LOG(WARNING) << __func__ << ": failed to disconnect from old patch. attempted rollback";
        return maybeFailure;
    }

    std::set<int32_t> idsToRollbackOnFailure;
    // connection step
    for (const auto& [newMixPortConfigId, newDevicePortConfigIds] : newConnections) {
        if (auto it = oldConnections.find(newMixPortConfigId);
            it == oldConnections.end() || it->second != newDevicePortConfigIds) {
            const auto connectedDevices = getDevicesFromDevicePortConfigIds(newDevicePortConfigIds);
            idsToRollbackOnFailure.insert(newMixPortConfigId);
            if (connectedDevices.empty()) {
                // This is important as workers use the vector size to derive the connection status.
                LOG(FATAL) << "updateStreamsConnectedState: No connected devices found for port "
                              "config id "
                           << mixPortConfigId;
                LOG(FATAL) << __func__ << ": No connected devices found for port config id "
                           << newMixPortConfigId;
            }
            if (auto status = mStreams.setStreamConnectedDevices(mixPortConfigId, connectedDevices);
            if (auto status =
                        mStreams.setStreamConnectedDevices(newMixPortConfigId, connectedDevices);
                status.isOk()) {
                LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
                           << mixPortConfigId << " has been connected to: "
                LOG(DEBUG) << __func__ << ": The stream on port config id " << newMixPortConfigId
                           << " has been connected to: "
                           << ::android::internal::ToString(connectedDevices);
            } else {
                maybeFailure = std::move(status);
                idsToDisconnectOnFailure.insert(mixPortConfigId);
                // proceed to rollback even on one failure
                break;
            }
        }
    });
    }

    if (!maybeFailure.isOk()) {
        LOG(WARNING) << __func__ << ": " << mType
                     << ": Due to a failure, disconnecting streams on port config ids "
                     << ::android::internal::ToString(idsToDisconnectOnFailure);
        std::for_each(idsToDisconnectOnFailure.begin(), idsToDisconnectOnFailure.end(),
                      [&](const auto& portConfigId) {
                          auto status = mStreams.setStreamConnectedDevices(portConfigId, {});
                          (void)status.isOk();  // Can't do much about a failure here.
                      });
        restoreOldConnections(idsToConnectBackOnFailure, false /*continueWithEmptyDevices*/);
        restoreOldConnections(idsToRollbackOnFailure, true /*continueWithEmptyDevices*/);
        LOG(WARNING) << __func__ << ": failed to connect for new patch. attempted rollback";
        return maybeFailure;
    }

    return ndk::ScopedAStatus::ok();
}

+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ cc_defaults {
    ],
    header_libs: [
        "libaudioaidl_headers",
        "libaudioutils_headers",
        "libexpectedutils_headers",
    ],
    cflags: [
+13 −4
Original line number Diff line number Diff line
@@ -429,19 +429,28 @@ class EffectHelper {
        }
    }

    // Generate multitone input between -1 to +1 using testFrequencies
    void generateMultiTone(const std::vector<int>& testFrequencies, std::vector<float>& input,
                           const int samplingFrequency) {
    // Generate multitone input between -amplitude to +amplitude using testFrequencies
    // All test frequencies are considered having the same amplitude
    void generateSineWave(const std::vector<int>& testFrequencies, std::vector<float>& input,
                          const float amplitude = 1.0,
                          const int samplingFrequency = kSamplingFrequency) {
        for (size_t i = 0; i < input.size(); i++) {
            input[i] = 0;

            for (size_t j = 0; j < testFrequencies.size(); j++) {
                input[i] += sin(2 * M_PI * testFrequencies[j] * i / samplingFrequency);
            }
            input[i] /= testFrequencies.size();
            input[i] *= amplitude / testFrequencies.size();
        }
    }

    // Generate single tone input between -amplitude to +amplitude using testFrequency
    void generateSineWave(const int testFrequency, std::vector<float>& input,
                          const float amplitude = 1.0,
                          const int samplingFrequency = kSamplingFrequency) {
        generateSineWave(std::vector<int>{testFrequency}, input, amplitude, samplingFrequency);
    }

    // Use FFT transform to convert the buffer to frequency domain
    // Compute its magnitude at binOffsets
    std::vector<float> calculateMagnitude(const std::vector<float>& buffer,
+33 −19
Original line number Diff line number Diff line
@@ -355,7 +355,6 @@ class AudioCoreConfig : public testing::TestWithParam<std::string> {
            const AudioHalCapRule& rule,
            const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
        const auto& compoundRule = rule.compoundRule;
        using TypeTag = AudioHalCapCriterionV2::Type::Tag;
        if (rule.nestedRules.empty() && rule.criterionRules.empty()) {
            EXPECT_EQ(compoundRule, AudioHalCapRule::CompoundRule::ALL);
        }
@@ -365,8 +364,8 @@ class AudioCoreConfig : public testing::TestWithParam<std::string> {
            ValidateAudioHalConfigurationRule(nestedRule, criteria);
        }
        for (const auto& criterionRule : rule.criterionRules) {
            auto selectionCriterion = criterionRule.criterion;
            auto criterionValue = criterionRule.criterionTypeValue;
            auto selectionCriterion = criterionRule.criterionAndValue;
            auto criterionValue = criterionRule.criterionAndValue;
            auto matchesWhen = criterionRule.matchingRule;
            auto criteriaIt = find_if(criteria.begin(), criteria.end(), [&](const auto& criterion) {
                return criterion.has_value() &&
@@ -377,50 +376,65 @@ class AudioCoreConfig : public testing::TestWithParam<std::string> {
            AudioHalCapCriterionV2 matchingCriterion = (*criteriaIt).value();
            switch (selectionCriterion.getTag()) {
                case AudioHalCapCriterionV2::availableInputDevices: {
                    EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesType);
                    const auto& values =
                            criterionValue.get<AudioHalCapCriterionV2::availableInputDevices>()
                                    .values;
                    ASSERT_FALSE(values.empty());
                    validateAudioHalCapRule(
                            matchingCriterion.get<AudioHalCapCriterionV2::availableInputDevices>(),
                            criterionValue.get<TypeTag::availableDevicesType>(), matchesWhen);
                            values[0], matchesWhen);
                    break;
                }
                case AudioHalCapCriterionV2::availableOutputDevices: {
                    EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesType);
                    const auto& values =
                            criterionValue.get<AudioHalCapCriterionV2::availableOutputDevices>()
                                    .values;
                    ASSERT_FALSE(values.empty());
                    validateAudioHalCapRule(
                            matchingCriterion.get<AudioHalCapCriterionV2::availableOutputDevices>(),
                            criterionValue.get<TypeTag::availableDevicesType>(), matchesWhen);
                            values[0], matchesWhen);
                    break;
                }
                case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
                    EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesAddressesType);
                    const auto& values =
                            criterionValue
                                    .get<AudioHalCapCriterionV2::availableInputDevicesAddresses>()
                                    .values;
                    ASSERT_FALSE(values.empty());
                    validateAudioHalCapRule(
                            matchingCriterion
                                    .get<AudioHalCapCriterionV2::availableInputDevicesAddresses>(),
                            criterionValue.get<TypeTag::availableDevicesAddressesType>(),
                            matchesWhen);
                            values[0], matchesWhen);
                    break;
                }
                case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
                    EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesAddressesType);
                    const auto& values =
                            criterionValue
                                    .get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>()
                                    .values;
                    ASSERT_FALSE(values.empty());
                    validateAudioHalCapRule(
                            matchingCriterion
                                    .get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>(),
                            criterionValue.get<TypeTag::availableDevicesAddressesType>(),
                            matchesWhen);
                            values[0], matchesWhen);
                    break;
                }
                case AudioHalCapCriterionV2::telephonyMode: {
                    EXPECT_EQ(criterionValue.getTag(), TypeTag::telephonyModeType);
                    const auto& values =
                            criterionValue.get<AudioHalCapCriterionV2::telephonyMode>().values;
                    ASSERT_FALSE(values.empty());
                    validateAudioHalCapRule(
                            matchingCriterion.get<AudioHalCapCriterionV2::telephonyMode>(),
                            criterionValue.get<TypeTag::telephonyModeType>(), matchesWhen);
                            values[0], matchesWhen);
                    break;
                }
                case AudioHalCapCriterionV2::forceConfigForUse: {
                    EXPECT_EQ(criterionValue.getTag(), TypeTag::forcedConfigType);
                    const auto& values =
                            criterionValue.get<AudioHalCapCriterionV2::forceConfigForUse>().values;
                    ASSERT_FALSE(values.empty());
                    validateAudioHalCapRule(
                            matchingCriterion
                                    .get<AudioHalCapCriterionV2::forceConfigForUse>(),
                            criterionValue.get<TypeTag::forcedConfigType>(), matchesWhen);
                            matchingCriterion.get<AudioHalCapCriterionV2::forceConfigForUse>(),
                            values[0], matchesWhen);
                    break;
                }
                default:
Loading