blob: a33fb775f5428cab3ca1836ffdfe49569f36f8c5 [file] [log] [blame]
/*
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. 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"
#include <errno.h>
#include <string>
#include <map>
#include "PalCommon.h"
#include "PalDefs.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)
{
}
uint32_t ACDContextInfo::GetContextId() {
return context_id_;
}
uint32_t ACDContextInfo::GetContextType() {
return context_type_;
}
ACDSoundModelInfo::ACDSoundModelInfo(StreamConfig *sm_cfg) :
model_bin_name_(""),
is_parsing_contexts(false),
sm_cfg_(sm_cfg)
{
}
void ACDSoundModelInfo::HandleStartTag(const char* tag, const char** attribs __unused) {
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")) {
std::string type(data->data_buf);
model_type_ = type;
auto valItr = acdContextTypeMap.find(data->data_buf);
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;
}
std::string ACDSoundModelInfo::GetModelType() {
return model_type_;
}
std::string ACDSoundModelInfo::GetModelBinName() {
return model_bin_name_;
}
uint32_t ACDSoundModelInfo::GetModelUUID() {
return model_uuid_;
}
uint32_t ACDSoundModelInfo::GetModelId() {
return model_id_;
}
std::vector<std::shared_ptr<ACDContextInfo>> ACDSoundModelInfo::GetSupportedContextList() {
return acd_context_info_list_;
}
size_t ACDSoundModelInfo::GetNumContexts() {
return acd_context_info_list_.size();
}
StreamConfig::StreamConfig(const acd_cap_profile_map_t& cap_prof_map) :
sample_rate_(16000),
bit_width_(16),
out_channels_(1),
cap_profile_map_(cap_prof_map),
curr_child_(nullptr)
{
}
std::pair<uint32_t, uint32_t> StreamConfig::GetStreamMetadata() {
return stream_metadata_;
}
ACDUUID StreamConfig::GetUUID() {
return vendor_uuid_;
}
uint32_t StreamConfig::GetSampleRate() {
return sample_rate_;
}
uint32_t StreamConfig::GetBitWidth() {
return bit_width_;
}
uint32_t StreamConfig::GetOutChannels() {
return out_channels_;
}
std::string StreamConfig::GetStreamConfigName() {
return name_;
}
std::shared_ptr<CaptureProfile> StreamConfig::GetCaptureProfile(
std::pair<StOperatingModes, StInputModes> mode_pair) {
return op_modes_.at(mode_pair);
}
std::vector<std::shared_ptr<ACDSoundModelInfo>> StreamConfig::GetSoundModelList() {
return acd_soundmodel_info_list_;
}
void StreamConfig::ReadCapProfileNames(StOperatingModes mode,
const char** attribs) {
uint32_t i = 0;
while (attribs[i]) {
if (!strcmp(attribs[i], "capture_profile_handset")) {
op_modes_[std::make_pair(mode, ST_INPUT_MODE_HANDSET)] =
cap_profile_map_.at(std::string(attribs[++i]));
} else if(!strcmp(attribs[i], "capture_profile_headset")) {
op_modes_[std::make_pair(mode, ST_INPUT_MODE_HEADSET)] =
cap_profile_map_.at(std::string(attribs[++i]));
} else {
PAL_ERR(LOG_TAG, "Error:%d got unexpected attribute: %s", -EINVAL, attribs[i]);
}
++i; /* move to next attribute */
}
}
void StreamConfig::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> StreamConfig::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> StreamConfig::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 StreamConfig::HandleStartTag(const char* tag, const char** attribs) {
PAL_DBG(LOG_TAG, "Got tag %s", tag);
/* Delegate to child element if currently active */
if (curr_child_) {
curr_child_->HandleStartTag(tag, attribs);
return;
}
if (!strcmp(tag, "model")) {
curr_child_ = std::static_pointer_cast<SoundTriggerXml>(
std::make_shared<ACDSoundModelInfo>(this));
return;
}
if (!strcmp(tag, "param")) {
uint32_t i = 0;
while (attribs[i]) {
if (!strcmp(attribs[i], "vendor_uuid")) {
SoundTriggerUUID::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")) {
out_channels_ = std::stoi(attribs[++i]);
} else {
PAL_INFO(LOG_TAG, "Invalid attribute %s", attribs[i++]);
}
++i; /* move to next attribute */
}
} else if (!strcmp(tag, "kvpair")) {
uint32_t i = 0;
uint32_t key = 0, value = 0;
while (attribs[i]) {
if (!strcmp(attribs[i], "key")) {
std::string tagkey(attribs[++i]);
key = ResourceManager::convertCharToHex(tagkey);
} else if(!strcmp(attribs[i], "value")) {
std::string tagvalue(attribs[++i]);
value = ResourceManager::convertCharToHex(tagvalue);
stream_metadata_ = std::make_pair(key, value);
PAL_DBG(LOG_TAG, "stream_metadata_, key = %x, value = %x",
stream_metadata_.first, stream_metadata_.second);
}
++i; /* move to next attribute */
}
} else if (!strcmp(tag, "low_power")) {
ReadCapProfileNames(ST_OPERATING_MODE_LOW_POWER, attribs);
} else if (!strcmp(tag, "low_power_ns")) {
ReadCapProfileNames(ST_OPERATING_MODE_LOW_POWER_NS, attribs);
} else if (!strcmp(tag, "high_performance")) {
ReadCapProfileNames(ST_OPERATING_MODE_HIGH_PERF, attribs);
} else if (!strcmp(tag, "high_performance_ns")) {
ReadCapProfileNames(ST_OPERATING_MODE_HIGH_PERF_NS, attribs);
} else if (!strcmp(tag, "high_performance_and_charging")) {
ReadCapProfileNames(ST_OPERATING_MODE_HIGH_PERF_AND_CHARGING, attribs);
} else {
PAL_INFO(LOG_TAG, "Invalid tag %s", (char *)tag);
}
}
void StreamConfig::HandleEndTag(struct xml_userdata *data, const char* tag) {
PAL_DBG(LOG_TAG, "Got end tag %s", tag);
if (!strcmp(tag, "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),
support_device_switch_(false),
support_nlpi_switch_(true),
dedicated_sva_path_(true),
dedicated_headset_path_(false),
lpi_enable_(false),
enable_debug_dumps_(false),
concurrent_capture_(false),
concurrent_voice_call_(false),
concurrent_voip_call_(false),
low_latency_bargein_enable_(false),
curr_child_(nullptr)
{
}
bool ACDPlatformInfo::GetSupportDevSwitch() const {
return support_device_switch_;
}
bool ACDPlatformInfo::GetSupportNLPISwitch() const {
return support_nlpi_switch_;
}
bool ACDPlatformInfo::GetDedicatedSvaPath() const {
return dedicated_sva_path_;
}
bool ACDPlatformInfo::GetDedicatedHeadsetPath() const {
return dedicated_headset_path_;
}
bool ACDPlatformInfo::GetLpiEnable() const {
return lpi_enable_;
}
bool ACDPlatformInfo::GetEnableDebugDumps() const {
return enable_debug_dumps_;
}
bool ACDPlatformInfo::GetConcurrentCaptureEnable() const {
return concurrent_capture_;
}
bool ACDPlatformInfo::GetConcurrentVoiceCallEnable() const {
return concurrent_voice_call_;
}
bool ACDPlatformInfo::GetConcurrentVoipCallEnable() const {
return concurrent_voip_call_;
}
bool ACDPlatformInfo::GetLowLatencyBargeinEnable() const {
return low_latency_bargein_enable_;
}
bool ACDPlatformInfo::IsACDEnabled() const {
return acd_enable_;
}
std::shared_ptr<StreamConfig> ACDPlatformInfo::GetStreamConfig(
const ACDUUID& uuid) const {
auto streamCfg = acd_cfg_list_.find(uuid);
if (streamCfg != acd_cfg_list_.end())
return streamCfg->second;
else
return nullptr;
}
std::shared_ptr<CaptureProfile> ACDPlatformInfo::GetCapProfile(
const std::string& name) const {
auto capProfile = capture_profile_map_.find(name);
if (capProfile != capture_profile_map_.end())
return capProfile->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<StreamConfig>(capture_profile_map_));
return;
}
if (!strcmp(tag, "capture_profile")) {
if (attribs[0] && !strcmp(attribs[0], "name")) {
curr_child_ = std::static_pointer_cast<SoundTriggerXml>(
std::make_shared<CaptureProfile>(attribs[1]));
return;
} else {
PAL_ERR(LOG_TAG, "Error:%d missing name attrib for tag %s", -EINVAL, tag);
return;
}
}
if (!strcmp(tag, "common_config") || !strcmp(tag, "capture_profile_list")) {
PAL_INFO(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 if (!strcmp(attribs[i], "support_device_switch")) {
support_device_switch_ =
!strncasecmp(attribs[++i], "true", 4) ? true : false;
} else if (!strcmp(attribs[i], "support_nlpi_switch")) {
support_nlpi_switch_ =
!strncasecmp(attribs[++i], "true", 4) ? true : false;
} else if (!strcmp(attribs[i], "lpi_enable")) {
lpi_enable_ =
!strncasecmp(attribs[++i], "true", 4) ? true : false;
} else if (!strcmp(attribs[i], "enable_debug_dumps")) {
enable_debug_dumps_ =
!strncasecmp(attribs[++i], "true", 4) ? true : false;
} else if (!strcmp(attribs[i], "concurrent_capture")) {
concurrent_capture_ =
!strncasecmp(attribs[++i], "true", 4) ? true : false;
} else if (!strcmp(attribs[i], "concurrent_voice_call") &&
concurrent_capture_) {
concurrent_voice_call_ =
!strncasecmp(attribs[++i], "true", 4) ? true : false;
} else if (!strcmp(attribs[i], "concurrent_voip_call") &&
concurrent_capture_) {
concurrent_voip_call_ =
!strncasecmp(attribs[++i], "true", 4) ? true : false;
} else if (!strcmp(attribs[i], "low_latency_bargein_enable") &&
concurrent_capture_) {
low_latency_bargein_enable_ =
!strncasecmp(attribs[++i], "true", 4) ? true : false;
} else {
PAL_INFO(LOG_TAG, "Invalid attribute %s", attribs[i++]);
}
++i; /* move to next attribute */
}
} else {
PAL_INFO(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<StreamConfig> acd_cfg(
std::static_pointer_cast<StreamConfig>(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;
} else if (!strcmp(tag, "capture_profile")) {
std::shared_ptr<CaptureProfile> cap_prof(
std::static_pointer_cast<CaptureProfile>(curr_child_));
const auto res = capture_profile_map_.insert(
std::make_pair(cap_prof->GetName(), cap_prof));
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;
}