blob: ced616472d388477663646844f1dbe47996ba347 [file] [log] [blame]
/*
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ACDPlatformInfo.h"
#define LOG_TAG "PAL: ACDPlatformInfo"
static const std::map<std::string, int32_t> acdContextTypeMap {
{std::string{"ACD_SOUND_MODEL_ID_ENV"}, ACD_SOUND_MODEL_ID_ENV},
{std::string{"ACD_SOUND_MODEL_ID_EVENT"}, ACD_SOUND_MODEL_ID_EVENT},
{std::string{"ACD_SOUND_MODEL_ID_SPEECH"}, ACD_SOUND_MODEL_ID_SPEECH},
{std::string{"ACD_SOUND_MODEL_ID_MUSIC"}, ACD_SOUND_MODEL_ID_MUSIC},
{std::string{"ACD_SOUND_MODEL_AMBIENCE_NOISE_SILENCE"}, ACD_SOUND_MODEL_AMBIENCE_NOISE_SILENCE},
};
ACDContextInfo::ACDContextInfo(uint32_t context_id, uint32_t type) :
context_id_(context_id),
context_type_(type)
{
}
ACDSoundModelInfo::ACDSoundModelInfo(ACDStreamConfig *sm_cfg) :
model_bin_name_(""),
is_parsing_contexts(false),
sm_cfg_(sm_cfg)
{
}
void ACDSoundModelInfo::HandleStartTag(const char* tag, const char** attribs __unused)
{
PAL_DBG(LOG_TAG, "Got start tag %s", tag);
if (is_parsing_contexts) {
if (!strcmp(tag, "context")) {
uint32_t i = 0;
uint32_t id;
while (attribs[i]) {
if (!strcmp(attribs[i], "id")) {
std::string tagid(attribs[++i]);
id = ResourceManager::convertCharToHex(tagid);
std::shared_ptr<ACDContextInfo> context_info =
std::make_shared<ACDContextInfo>(id, model_id_);
acd_context_info_list_.push_back(context_info);
sm_cfg_->UpdateContextModelMap(id);
}
++i; /* move to next attribute */
}
}
}
if (!strcmp(tag, "contexts"))
is_parsing_contexts = true;
}
void ACDSoundModelInfo::HandleEndTag(struct xml_userdata *data, const char* tag_name)
{
PAL_DBG(LOG_TAG, "Got end tag %s", tag_name);
if (!strcmp(tag_name, "contexts"))
is_parsing_contexts = false;
if (data->offs <= 0)
return;
data->data_buf[data->offs] = '\0';
if (!strcmp(tag_name, "name")) {
auto valItr = acdContextTypeMap.find(data->data_buf);
std::string type(data->data_buf);
model_type_ = type;
if (valItr == acdContextTypeMap.end()) {
PAL_ERR(LOG_TAG, "Error:%d could not find value %s in lookup table",
-EINVAL, data->data_buf);
} else {
model_id_ = valItr->second;
}
} else if (!strcmp(tag_name, "bin")) {
std::string bin_name(data->data_buf);
model_bin_name_ = bin_name;
} else if (!strcmp(tag_name, "uuid")) {
std::string uuid(data->data_buf);
model_uuid_ = ResourceManager::convertCharToHex(uuid);
}
return;
}
ACDStreamConfig::ACDStreamConfig() : curr_child_(nullptr)
{
}
void ACDStreamConfig::UpdateContextModelMap(uint32_t context_id)
{
std::shared_ptr<ACDSoundModelInfo> sm_info(
std::static_pointer_cast<ACDSoundModelInfo>(curr_child_));
context_model_map_.insert(std::make_pair(context_id, sm_info));
}
std::shared_ptr<ACDSoundModelInfo> ACDStreamConfig::GetSoundModelInfoByContextId(uint32_t context_id)
{
auto contextModel = context_model_map_.find(context_id);
if (contextModel != context_model_map_.end())
return contextModel->second;
else
return nullptr;
}
std::shared_ptr<ACDSoundModelInfo> ACDStreamConfig::GetSoundModelInfoByModelId(uint32_t model_id)
{
auto modelInfo = acd_modelinfo_map_.find(model_id);
if (modelInfo != acd_modelinfo_map_.end())
return modelInfo->second;
else
return nullptr;
}
void ACDStreamConfig::HandleStartTag(const char* tag, const char** attribs)
{
PAL_DBG(LOG_TAG, "Got start tag %s", tag);
/* Delegate to child element if currently active */
if (curr_child_) {
curr_child_->HandleStartTag(tag, attribs);
return;
}
if (!strcmp(tag, "sound_model")) {
curr_child_ = std::static_pointer_cast<SoundTriggerXml>(
std::make_shared<ACDSoundModelInfo>(this));
return;
}
if (!strcmp(tag, "operating_modes") || !strcmp(tag, "sound_model_info")
|| !strcmp(tag, "name")) {
PAL_DBG(LOG_TAG, "tag:%s appeared, nothing to do", tag);
return;
}
std::shared_ptr<SoundTriggerPlatformInfo> st_info = SoundTriggerPlatformInfo::GetInstance();
if (!strcmp(tag, "param")) {
uint32_t i = 0;
while (attribs[i]) {
if (!strcmp(attribs[i], "vendor_uuid")) {
UUID::StringToUUID(attribs[++i], vendor_uuid_);
} else if (!strcmp(attribs[i], "sample_rate")) {
sample_rate_ = std::stoi(attribs[++i]);
} else if (!strcmp(attribs[i], "bit_width")) {
bit_width_ = std::stoi(attribs[++i]);
} else if (!strcmp(attribs[i], "out_channels")) {
if (std::stoi(attribs[++i]) <= MAX_MODULE_CHANNELS)
out_channels_ = std::stoi(attribs[i]);
} else {
PAL_ERR(LOG_TAG, "Invalid attribute %s", attribs[i++]);
}
++i; /* move to next attribute */
}
} else if (!strcmp(tag, "low_power")) {
st_info->ReadCapProfileNames(ST_OPERATING_MODE_LOW_POWER, attribs, acd_op_modes_);
} else if (!strcmp(tag, "low_power_ns")) {
st_info->ReadCapProfileNames(ST_OPERATING_MODE_LOW_POWER_NS, attribs, acd_op_modes_);
} else if (!strcmp(tag, "high_performance")) {
st_info->ReadCapProfileNames(ST_OPERATING_MODE_HIGH_PERF, attribs, acd_op_modes_);
} else if (!strcmp(tag, "high_performance_ns")) {
st_info->ReadCapProfileNames(ST_OPERATING_MODE_HIGH_PERF_NS, attribs, acd_op_modes_);
} else {
PAL_ERR(LOG_TAG, "Invalid tag %s", (char *)tag);
}
}
void ACDStreamConfig::HandleEndTag(struct xml_userdata *data, const char* tag)
{
PAL_DBG(LOG_TAG, "Got end tag %s", tag);
if (!strcmp(tag, "sound_model")) {
std::shared_ptr<ACDSoundModelInfo> acd_sm_info(
std::static_pointer_cast<ACDSoundModelInfo>(curr_child_));
acd_soundmodel_info_list_.push_back(acd_sm_info);
acd_modelinfo_map_.insert(std::make_pair(acd_sm_info->GetModelId(), acd_sm_info));
curr_child_ = nullptr;
}
if (curr_child_) {
curr_child_->HandleEndTag(data, tag);
return;
}
if (!strcmp(tag, "name")) {
if (data->offs <= 0)
return;
data->data_buf[data->offs] = '\0';
std::string name(data->data_buf);
name_ = name;
}
return;
}
std::shared_ptr<ACDPlatformInfo> ACDPlatformInfo::me_ = nullptr;
ACDPlatformInfo::ACDPlatformInfo() :
acd_enable_(true),
curr_child_(nullptr)
{
}
std::shared_ptr<ACDStreamConfig> ACDPlatformInfo::GetStreamConfig(const UUID& uuid) const
{
auto streamCfg = acd_cfg_list_.find(uuid);
if (streamCfg != acd_cfg_list_.end())
return streamCfg->second;
else
return nullptr;
}
std::shared_ptr<ACDPlatformInfo> ACDPlatformInfo::GetInstance()
{
if (!me_)
me_ = std::shared_ptr<ACDPlatformInfo> (new ACDPlatformInfo);
return me_;
}
void ACDPlatformInfo::HandleStartTag(const char* tag, const char** attribs)
{
/* Delegate to child element if currently active */
if (curr_child_) {
curr_child_->HandleStartTag(tag, attribs);
return;
}
PAL_DBG(LOG_TAG, "Got start tag %s", tag);
if (!strcmp(tag, "stream_config")) {
curr_child_ = std::static_pointer_cast<SoundTriggerXml>(
std::make_shared<ACDStreamConfig>());
return;
}
if (!strcmp(tag, "config")) {
PAL_DBG(LOG_TAG, "tag:%s appeared, nothing to do", tag);
return;
}
if (!strcmp(tag, "param")) {
uint32_t i = 0;
while (attribs[i]) {
if (!attribs[i]) {
PAL_ERR(LOG_TAG, "Error:%d missing attrib value for tag %s", -EINVAL, tag);
} else if (!strcmp(attribs[i], "acd_enable")) {
acd_enable_ = !strncasecmp(attribs[++i], "true", 4) ? true : false;
} else {
PAL_ERR(LOG_TAG, "Invalid attribute %s", attribs[i++]);
}
++i; /* move to next attribute */
}
} else {
PAL_ERR(LOG_TAG, "Invalid tag %s", tag);
}
}
void ACDPlatformInfo::HandleEndTag(struct xml_userdata *data, const char* tag)
{
PAL_DBG(LOG_TAG, "Got end tag %s", tag);
if (!strcmp(tag, "stream_config")) {
std::shared_ptr<ACDStreamConfig> acd_cfg(
std::static_pointer_cast<ACDStreamConfig>(curr_child_));
const auto res = acd_cfg_list_.insert(
std::make_pair(acd_cfg->GetUUID(), acd_cfg));
if (!res.second)
PAL_ERR(LOG_TAG, "Error:%d Failed to insert to map", -EINVAL);
curr_child_ = nullptr;
}
if (curr_child_)
curr_child_->HandleEndTag(data, tag);
return;
}