1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef LOG_TAG
16 #define LOG_TAG "AudioDeviceParser"
17 #endif
18 
19 #include "audio_device_parser.h"
20 #include "media_monitor_manager.h"
21 
22 namespace OHOS {
23 namespace AudioStandard {
LoadConfiguration()24 bool AudioDeviceParser::LoadConfiguration()
25 {
26     mDoc_ = xmlReadFile(DEVICE_CONFIG_FILE, nullptr, 0);
27     if (mDoc_ == nullptr) {
28         std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
29             Media::MediaMonitor::AUDIO, Media::MediaMonitor::LOAD_CONFIG_ERROR,
30             Media::MediaMonitor::FAULT_EVENT);
31         bean->Add("CATEGORY", Media::MediaMonitor::AUDIO_DEVICE_PRIVACY);
32         Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
33     }
34     CHECK_AND_RETURN_RET_LOG(mDoc_ != nullptr, false,
35         "xmlReadFile Failed");
36 
37     return true;
38 }
39 
Parse()40 bool AudioDeviceParser::Parse()
41 {
42     xmlNode *root = xmlDocGetRootElement(mDoc_);
43     CHECK_AND_RETURN_RET_LOG(root != nullptr, false,
44         "xmlDocGetRootElement Failed");
45 
46     if (!ParseInternal(root)) {
47         return false;
48     }
49     audioDeviceManager_->OnXmlParsingCompleted(devicePrivacyMaps_);
50     return true;
51 }
52 
Destroy()53 void AudioDeviceParser::Destroy()
54 {
55     if (mDoc_ != nullptr) {
56         xmlFreeDoc(mDoc_);
57     }
58 }
59 
ParseInternal(xmlNode * node)60 bool AudioDeviceParser::ParseInternal(xmlNode *node)
61 {
62     xmlNode *currNode = node;
63     for (; currNode; currNode = currNode->next) {
64         if (XML_ELEMENT_NODE == currNode->type) {
65             switch (GetDeviceNodeNameAsInt(currNode)) {
66                 case ADAPTER:
67                     ParseAudioDevicePrivacyType(currNode, devicePrivacyType_);
68                     break;
69                 default:
70                     ParseInternal((currNode->xmlChildrenNode));
71                     break;
72             }
73         }
74     }
75     return true;
76 }
77 
ParseDevicePrivacyInfo(xmlNode * node,std::list<DevicePrivacyInfo> & deviceLists)78 void AudioDeviceParser::ParseDevicePrivacyInfo(xmlNode *node, std::list<DevicePrivacyInfo> &deviceLists)
79 {
80     xmlNode *deviceNode = node;
81 
82     while (deviceNode != nullptr) {
83         if (deviceNode->type == XML_ELEMENT_NODE) {
84             DevicePrivacyInfo deviceInfo = {};
85             char *pValue = reinterpret_cast<char*>(xmlGetProp(deviceNode,
86                 reinterpret_cast<xmlChar*>(const_cast<char*>("name"))));
87             deviceInfo.deviceName = pValue;
88             xmlFree(pValue);
89 
90             pValue = reinterpret_cast<char*>(xmlGetProp(deviceNode,
91                 reinterpret_cast<xmlChar*>(const_cast<char*>("type"))));
92             deviceInfo.deviceType = deviceTypeMap_[pValue];
93             xmlFree(pValue);
94 
95             pValue = reinterpret_cast<char*>(xmlGetProp(deviceNode,
96                 reinterpret_cast<xmlChar*>(const_cast<char*>("role"))));
97             uint32_t intValue = 0;
98             ParseDeviceRole(pValue, intValue);
99             deviceInfo.deviceRole = static_cast<DeviceRole>(intValue);
100             xmlFree(pValue);
101 
102             pValue = reinterpret_cast<char*>(xmlGetProp(deviceNode,
103                 reinterpret_cast<xmlChar*>(const_cast<char*>("Category"))));
104             intValue = 0;
105             ParseDeviceCategory(pValue, intValue);
106             deviceInfo.deviceCategory = static_cast<DeviceCategory>(intValue);
107             xmlFree(pValue);
108 
109             pValue = reinterpret_cast<char*>(xmlGetProp(deviceNode,
110                 reinterpret_cast<xmlChar*>(const_cast<char*>("usage"))));
111             intValue = 0;
112             ParseDeviceUsage(pValue, intValue);
113             deviceInfo.deviceUsage = static_cast<DeviceUsage>(intValue);
114             xmlFree(pValue);
115             deviceLists.push_back(deviceInfo);
116             AUDIO_DEBUG_LOG("AudioDeviceParser: name:%{public}s, type:%{public}d, role:%{public}d, Category:%{public}d,"
117                 "Usage:%{public}d", deviceInfo.deviceName.c_str(), deviceInfo.deviceType, deviceInfo.deviceRole,
118                 deviceInfo.deviceCategory, deviceInfo.deviceUsage);
119         }
120         deviceNode = deviceNode->next;
121     }
122 }
123 
ParserDevicePrivacyInfoList(xmlNode * node,std::list<DevicePrivacyInfo> & deviceLists)124 void AudioDeviceParser::ParserDevicePrivacyInfoList(xmlNode *node, std::list<DevicePrivacyInfo> &deviceLists)
125 {
126     xmlNode *currentNode = node;
127     while (currentNode != nullptr) {
128         if (currentNode->type == XML_ELEMENT_NODE
129             && (!xmlStrcmp(currentNode->name, reinterpret_cast<const xmlChar*>("devices")))) {
130             ParseDevicePrivacyInfo(currentNode->xmlChildrenNode, deviceLists);
131         }
132         currentNode = currentNode->next;
133     }
134 }
135 
ParseAudioDevicePrivacyType(xmlNode * node,AudioDevicePrivacyType & deviceType)136 void AudioDeviceParser::ParseAudioDevicePrivacyType(xmlNode *node, AudioDevicePrivacyType &deviceType)
137 {
138     xmlNode *currNode = node;
139     while (currNode != nullptr) {
140         //read deviceType
141         if (currNode->type == XML_ELEMENT_NODE &&
142             (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("adapter")))) {
143             std::string adapterName = ExtractPropertyValue("name", currNode);
144             if (adapterName.empty()) {
145                 AUDIO_ERR_LOG("AudioDeviceParser: No name provided for the adapter %{public}s", node->name);
146                 return;
147             } else {
148                 AUDIO_DEBUG_LOG("AudioDeviceParser: adapter name: %{public}s", adapterName.c_str());
149                 devicePrivacyType_ = GetDevicePrivacyType(adapterName);
150                 std::list<DevicePrivacyInfo> deviceLists = {};
151                 ParserDevicePrivacyInfoList(currNode->xmlChildrenNode, deviceLists);
152                 devicePrivacyMaps_[devicePrivacyType_] = deviceLists;
153             }
154         } else {
155             return;
156         }
157         currNode = currNode->next;
158     }
159 }
160 
GetDevicePrivacyType(const std::string & devicePrivacyType)161 AudioDevicePrivacyType AudioDeviceParser::GetDevicePrivacyType(const std::string &devicePrivacyType)
162 {
163     if (devicePrivacyType == PRIVACY_TYPE) {
164         return AudioDevicePrivacyType::TYPE_PRIVACY;
165     } else if (devicePrivacyType == PUBLIC_TYPE) {
166         return AudioDevicePrivacyType::TYPE_PUBLIC;
167     } else {
168         return AudioDevicePrivacyType::TYPE_NEGATIVE;
169     }
170 }
171 
ExtractPropertyValue(const std::string & propName,xmlNode * node)172 std::string AudioDeviceParser::ExtractPropertyValue(const std::string &propName, xmlNode *node)
173 {
174     std::string propValue = "";
175     xmlChar *tempValue = nullptr;
176 
177     if (xmlHasProp(node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
178         tempValue = xmlGetProp(node, reinterpret_cast<const xmlChar*>(propName.c_str()));
179     }
180 
181     if (tempValue != nullptr) {
182         propValue = reinterpret_cast<const char*>(tempValue);
183         xmlFree(tempValue);
184     }
185 
186     return propValue;
187 }
188 
GetDeviceNodeNameAsInt(xmlNode * node)189 DeviceNodeName AudioDeviceParser::GetDeviceNodeNameAsInt(xmlNode *node)
190 {
191     if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("adapter"))) {
192         return DeviceNodeName::ADAPTER;
193     } else {
194         return DeviceNodeName::UNKNOWN_NODE;
195     }
196 }
197 
split(const std::string & line,const std::string & sep)198 std::vector<std::string> split(const std::string &line, const std::string &sep)
199 {
200     std::vector<std::string> buf;
201     size_t temp = 0;
202     std::string::size_type pos = 0;
203     while (true) {
204         pos = line.find(sep, temp);
205         if (pos == std::string::npos) {
206             break;
207         }
208         buf.push_back(line.substr(temp, pos-temp));
209         temp = pos + sep.length();
210     }
211     buf.push_back(line.substr(temp, line.length()));
212     return buf;
213 }
214 
ParseDeviceRole(const std::string & deviceRole,uint32_t & deviceRoleFlag)215 void AudioDeviceParser::ParseDeviceRole(const std::string &deviceRole, uint32_t &deviceRoleFlag)
216 {
217     std::vector<std::string> buf = split(deviceRole, ",");
218     for (const auto &role : buf) {
219         if (role == "output") {
220             deviceRoleFlag |= DeviceRole::OUTPUT_DEVICE;
221         } else if (role == "input") {
222             deviceRoleFlag |= DeviceRole::INPUT_DEVICE;
223         }
224     }
225 }
226 
ParseDeviceCategory(const std::string & deviceCategory,uint32_t & deviceCategoryFlag)227 void AudioDeviceParser::ParseDeviceCategory(const std::string &deviceCategory, uint32_t &deviceCategoryFlag)
228 {
229     std::vector<std::string> buf = split(deviceCategory, ",");
230     for (const auto &category : buf) {
231         if (category == "HEADPHONE") {
232             deviceCategoryFlag |= DeviceCategory::BT_HEADPHONE;
233         } else if (category == "GLASSES") {
234             deviceCategoryFlag |= DeviceCategory::BT_GLASSES;
235         } else if (category == "SOUNDBOX") {
236             deviceCategoryFlag |= DeviceCategory::BT_SOUNDBOX;
237         } else if (category == "CAR") {
238             deviceCategoryFlag |= DeviceCategory::BT_CAR;
239         } else if (category == "HEADPHONE_UNWEAR") {
240             deviceCategoryFlag |= DeviceCategory::BT_UNWEAR_HEADPHONE;
241         } else if (category == "WATCH") {
242             deviceCategoryFlag |= DeviceCategory::BT_WATCH;
243         }
244     }
245 }
246 
ParseDeviceUsage(const std::string & deviceUsage,uint32_t & deviceUsageFlag)247 void AudioDeviceParser::ParseDeviceUsage(const std::string &deviceUsage, uint32_t &deviceUsageFlag)
248 {
249     std::vector<std::string> buf = split(deviceUsage, ",");
250     for (const auto &usage : buf) {
251         if (usage == "media") {
252             deviceUsageFlag |= DeviceUsage::MEDIA;
253         } else if (usage == "voice") {
254             deviceUsageFlag |= DeviceUsage::VOICE;
255         } else if (usage == "recongnition") {
256             deviceUsageFlag |= DeviceUsage::RECOGNITION;
257         }
258     }
259 }
260 } // namespace AudioStandard
261 } // namespace OHOS