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

Commit bada1f5e authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

Fix parsing of legacy engine config XML files

The change aosp/3020124 adds a requirement for having
an 'id' field for product strategies. However, legacy
XML configuration files lack it. In order to preserve
compatibility, attempt to parse the string name of
the strategy in order to assign it the corresponding id.

Bug: 376030167
Test: atest audiopolicy_tests
Change-Id: I57a69f0507ef0bd4d06957e69b3fbe81b7febf40
parent 5d1e90cd
Loading
Loading
Loading
Loading
+59 −13
Original line number Diff line number Diff line
@@ -22,30 +22,76 @@

#include <media/AudioContainers.h>

#include <string.h>

namespace android {

using StreamTypeVector = std::vector<audio_stream_type_t>;

#define AUDIO_ENUM_QUOTE(x) #x
#define AUDIO_ENUM_STRINGIFY(x) AUDIO_ENUM_QUOTE(x)
#define AUDIO_DEFINE_ENUM_SYMBOL_V(symbol, value) symbol = value,
#define AUDIO_DEFINE_STRINGIFY_CASE_V(symbol, _) case symbol: return AUDIO_ENUM_STRINGIFY(symbol);
#define AUDIO_DEFINE_PARSE_CASE_V(symbol, _) \
    if (strcmp(s, AUDIO_ENUM_STRINGIFY(symbol)) == 0) { *t = symbol; return true; } else
#define AUDIO_DEFINE_MAP_ENTRY_V(symbol, _) { AUDIO_ENUM_STRINGIFY(symbol), symbol },

/**
 * Legacy audio policy product strategies IDs. These strategies are supported by the default
 * policy engine.
 * IMPORTANT NOTE: the order of this enum is important as it determines the priority
 * between active strategies for routing decisions: lower enum value => higher prioriy
 * between active strategies for routing decisions: lower enum value => higher priority
 */
#define AUDIO_LEGACY_STRATEGY_LIST_DEF(V)      \
    V(STRATEGY_NONE, -1)                       \
    V(STRATEGY_PHONE, 0)                       \
    V(STRATEGY_SONIFICATION, 1)                \
    V(STRATEGY_ENFORCED_AUDIBLE, 2)            \
    V(STRATEGY_ACCESSIBILITY, 3)               \
    V(STRATEGY_SONIFICATION_RESPECTFUL, 4)     \
    V(STRATEGY_MEDIA, 5)                       \
    V(STRATEGY_DTMF, 6)                        \
    V(STRATEGY_CALL_ASSISTANT, 7)              \
    V(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, 8) \
    V(STRATEGY_REROUTING, 9)                   \
    V(STRATEGY_PATCH, 10)

enum legacy_strategy {
    STRATEGY_NONE = -1,
    STRATEGY_PHONE,
    STRATEGY_SONIFICATION,
    STRATEGY_ENFORCED_AUDIBLE,
    STRATEGY_ACCESSIBILITY,
    STRATEGY_SONIFICATION_RESPECTFUL,
    STRATEGY_MEDIA,
    STRATEGY_DTMF,
    STRATEGY_CALL_ASSISTANT,
    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
    STRATEGY_REROUTING,
    STRATEGY_PATCH,
    AUDIO_LEGACY_STRATEGY_LIST_DEF(AUDIO_DEFINE_ENUM_SYMBOL_V)
};

inline const char* legacy_strategy_to_string(legacy_strategy t) {
    switch (t) {
    AUDIO_LEGACY_STRATEGY_LIST_DEF(AUDIO_DEFINE_STRINGIFY_CASE_V)
    }
    return "";
}

inline bool legacy_strategy_from_string(const char* s, legacy_strategy* t) {
    AUDIO_LEGACY_STRATEGY_LIST_DEF(AUDIO_DEFINE_PARSE_CASE_V)
    return false;
}

namespace audio_policy {

struct legacy_strategy_map { const char *name; legacy_strategy id; };

inline std::vector<legacy_strategy_map> getLegacyStrategyMap() {
    return std::vector<legacy_strategy_map> {
    AUDIO_LEGACY_STRATEGY_LIST_DEF(AUDIO_DEFINE_MAP_ENTRY_V)
    };
}

}  // namespace audio_policy

#undef AUDIO_LEGACY_STRATEGY_LIST_DEF

#undef AUDIO_DEFINE_MAP_ENTRY_V
#undef AUDIO_DEFINE_PARSE_CASE_V
#undef AUDIO_DEFINE_STRINGIFY_CASE_V
#undef AUDIO_DEFINE_ENUM_SYMBOL_V
#undef AUDIO_ENUM_STRINGIFY
#undef AUDIO_ENUM_QUOTE

static const audio_attributes_t defaultAttr = AUDIO_ATTRIBUTES_INITIALIZER;

+3 −2
Original line number Diff line number Diff line
@@ -117,9 +117,10 @@ public:
            AudioDeviceTypeAddrVector &devices) const override;

    engineConfig::ParsingResult loadAudioPolicyEngineConfig(
            const media::audio::common::AudioHalEngineConfig& aidlConfig);
            const media::audio::common::AudioHalEngineConfig& aidlConfig, bool);

    engineConfig::ParsingResult loadAudioPolicyEngineConfig(const std::string& xmlFilePath = "");
    engineConfig::ParsingResult loadAudioPolicyEngineConfig(
            const std::string& xmlFilePath = "", bool isConfigurable = false);

    const ProductStrategyMap &getProductStrategies() const { return mProductStrategies; }

+4 −3
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ std::string EngineBase::getProductStrategyName(product_strategy_t id) const {
}

engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
        const media::audio::common::AudioHalEngineConfig& aidlConfig)
        const media::audio::common::AudioHalEngineConfig& aidlConfig, bool)
{
    engineConfig::ParsingResult result = engineConfig::convert(aidlConfig);
    if (result.parsedConfig == nullptr) {
@@ -141,7 +141,8 @@ engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
    return processParsingResult(std::move(result));
}

engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
        const std::string& xmlFilePath, bool isConfigurable)
{
    auto fileExists = [](const char* path) {
        struct stat fileStat;
@@ -150,7 +151,7 @@ engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::s
    const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
    engineConfig::ParsingResult result =
            fileExists(filePath.c_str()) ?
            engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
            engineConfig::parse(filePath.c_str(), isConfigurable) : engineConfig::ParsingResult{};
    if (result.parsedConfig == nullptr) {
        ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
        engineConfig::Config config = gDefaultEngineConfig;
+1 −1
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ struct ParsingResult {
/** Parses the provided audio policy usage configuration.
 * @return audio policy usage @see Config
 */
ParsingResult parse(const char* path = DEFAULT_PATH);
ParsingResult parse(const char* path = DEFAULT_PATH, bool isConfigurable = false);
android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups);
ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig);
// Exposed for testing.
+13 −3
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ static const char *const gReferenceAttributeName = "name";

namespace {

static bool gIsConfigurableEngine = false;

ConversionResult<std::string> aidl2legacy_AudioHalProductStrategy_ProductStrategyType(int id) {
    using AudioProductStrategyType = media::audio::common::AudioProductStrategyType;

@@ -547,9 +549,16 @@ status_t ProductStrategyTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
        if (!convertTo(idLiteral, id)) {
            return BAD_VALUE;
        }
        ALOGV("%s: %s, %s = %d", __FUNCTION__, name.c_str(), Attributes::id, id);
    } else {
        legacy_strategy legacyId;
        if (legacy_strategy_from_string(name.c_str(), &legacyId)) {
            id = legacyId;
        } else if (!gIsConfigurableEngine) {
            return BAD_VALUE;
        }
    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
        // With a configurable engine it can be a vendor-provided strategy name.
    }
    ALOGV("%s: %s, %s = %d", __FUNCTION__, name.c_str(), Attributes::id, id);

    size_t skipped = 0;
    AttributesGroups attrGroups;
@@ -776,7 +785,7 @@ private:

}  // namespace

ParsingResult parse(const char* path) {
ParsingResult parse(const char* path, bool isConfigurable) {
    XmlErrorHandler errorHandler;
    auto doc = make_xmlUnique(xmlParseFile(path));
    if (doc == NULL) {
@@ -801,6 +810,7 @@ ParsingResult parse(const char* path) {
        ALOGE("%s: No version found", __func__);
        return {nullptr, 0};
    }
    gIsConfigurableEngine = isConfigurable;
    size_t nbSkippedElements = 0;
    auto config = std::make_unique<Config>();
    config->version = std::stof(version);
Loading