1 /*
2 * Copyright (c) 2021-2022 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 #include "audio_focus_parser.h"
16
17 namespace OHOS {
18 namespace AudioStandard {
AudioFocusParser()19 AudioFocusParser::AudioFocusParser()
20 {
21 AUDIO_INFO_LOG("AudioFocusParser ctor");
22
23 // Initialize stream map with string vs AudioStreamType
24 streamMap = {
25 {"STREAM_RING", STREAM_RING},
26 {"STREAM_MUSIC", STREAM_MUSIC},
27 {"STREAM_VOICE_ASSISTANT", STREAM_VOICE_ASSISTANT},
28 {"STREAM_VOICE_CALL", STREAM_VOICE_CALL},
29 };
30
31 // Initialize action map with string vs InterruptActionType
32 actionMap = {
33 {"DUCK", INTERRUPT_HINT_DUCK},
34 {"PAUSE", INTERRUPT_HINT_PAUSE},
35 {"REJECT", INTERRUPT_HINT_NONE},
36 {"STOP", INTERRUPT_HINT_STOP}
37 };
38
39 // Initialize target map with string vs InterruptActionTarget
40 targetMap = {
41 {"new", INCOMING},
42 {"existing", CURRENT},
43 {"both", BOTH},
44 };
45
46 forceMap = {
47 {"true", INTERRUPT_FORCE},
48 {"false", INTERRUPT_SHARE},
49 };
50 }
51
~AudioFocusParser()52 AudioFocusParser::~AudioFocusParser()
53 {
54 streamMap.clear();
55 actionMap.clear();
56 targetMap.clear();
57 forceMap.clear();
58 }
59
LoadDefaultConfig(std::map<std::pair<AudioStreamType,AudioStreamType>,AudioFocusEntry> & focusMap)60 void AudioFocusParser::LoadDefaultConfig(std::map<std::pair<AudioStreamType, AudioStreamType>,
61 AudioFocusEntry> &focusMap)
62 {
63 }
64
LoadConfig(std::map<std::pair<AudioStreamType,AudioStreamType>,AudioFocusEntry> & focusMap)65 int32_t AudioFocusParser::LoadConfig(std::map<std::pair<AudioStreamType, AudioStreamType>,
66 AudioFocusEntry> &focusMap)
67 {
68 xmlDoc *doc = nullptr;
69 xmlNode *rootElement = nullptr;
70
71 if ((doc = xmlReadFile(AUDIO_FOCUS_CONFIG_FILE, nullptr, 0)) == nullptr) {
72 AUDIO_ERR_LOG("error: could not parse file %s", AUDIO_FOCUS_CONFIG_FILE);
73 LoadDefaultConfig(focusMap);
74 return ERROR;
75 }
76
77 rootElement = xmlDocGetRootElement(doc);
78 xmlNode *currNode = rootElement;
79 CHECK_AND_RETURN_RET_LOG(currNode != nullptr, ERROR, "root element is null");
80 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("audio_focus_policy"))) {
81 if ((currNode->children) && (currNode->children->next)) {
82 currNode = currNode->children->next;
83 ParseStreams(currNode, focusMap);
84 } else {
85 AUDIO_ERR_LOG("empty focus policy in : %s", AUDIO_FOCUS_CONFIG_FILE);
86 return SUCCESS;
87 }
88 } else {
89 AUDIO_ERR_LOG("Missing tag - focus_policy in : %s", AUDIO_FOCUS_CONFIG_FILE);
90 return ERROR;
91 }
92
93 xmlFreeDoc(doc);
94 xmlCleanupParser();
95 return SUCCESS;
96 }
97
ParseFocusMap(xmlNode * node,char * curStream,std::map<std::pair<AudioStreamType,AudioStreamType>,AudioFocusEntry> & focusMap)98 void AudioFocusParser::ParseFocusMap(xmlNode *node, char *curStream,
99 std::map<std::pair<AudioStreamType, AudioStreamType>, AudioFocusEntry> &focusMap)
100 {
101 xmlNode *currNode = node;
102 while (currNode != nullptr) {
103 if (currNode->type == XML_ELEMENT_NODE) {
104 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("focus_table"))) {
105 AUDIO_INFO_LOG("node type: Element, name: %s", currNode->name);
106 xmlNode *sNode = currNode->children;
107 while (sNode) {
108 if (sNode->type == XML_ELEMENT_NODE) {
109 if (!xmlStrcmp(sNode->name, reinterpret_cast<const xmlChar*>("deny"))) {
110 ParseRejectedStreams(sNode->children, curStream, focusMap);
111 } else {
112 ParseAllowedStreams(sNode->children, curStream, focusMap);
113 }
114 }
115 sNode = sNode->next;
116 }
117 }
118 }
119 currNode = currNode->next;
120 }
121 }
122
ParseStreams(xmlNode * node,std::map<std::pair<AudioStreamType,AudioStreamType>,AudioFocusEntry> & focusMap)123 void AudioFocusParser::ParseStreams(xmlNode *node,
124 std::map<std::pair<AudioStreamType, AudioStreamType>, AudioFocusEntry> &focusMap)
125 {
126 xmlNode *currNode = node;
127 while (currNode) {
128 if (currNode->type == XML_ELEMENT_NODE) {
129 char *sType = reinterpret_cast<char*>(xmlGetProp(currNode,
130 reinterpret_cast<xmlChar*>(const_cast<char*>("value"))));
131 std::map<std::string, AudioStreamType>::iterator it = streamMap.find(sType);
132 if (it != streamMap.end()) {
133 AUDIO_INFO_LOG("stream type: %{public}s", sType);
134 ParseFocusMap(currNode->children, sType, focusMap);
135 }
136 xmlFree(sType);
137 }
138 currNode = currNode->next;
139 }
140 }
141
ParseRejectedStreams(xmlNode * node,char * curStream,std::map<std::pair<AudioStreamType,AudioStreamType>,AudioFocusEntry> & focusMap)142 void AudioFocusParser::ParseRejectedStreams(xmlNode *node, char *curStream,
143 std::map<std::pair<AudioStreamType, AudioStreamType>, AudioFocusEntry> &focusMap)
144 {
145 xmlNode *currNode = node;
146
147 while (currNode) {
148 if (currNode->type == XML_ELEMENT_NODE) {
149 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("stream_type"))) {
150 char *newStream = reinterpret_cast<char*>(xmlGetProp(currNode,
151 reinterpret_cast<xmlChar*>(const_cast<char*>("value"))));
152
153 std::map<std::string, AudioStreamType>::iterator it1 = streamMap.find(newStream);
154 if (it1 != streamMap.end()) {
155 std::pair<AudioStreamType, AudioStreamType> rejectedStreamsPair =
156 std::make_pair(streamMap[curStream], streamMap[newStream]);
157 AudioFocusEntry rejectedFocusEntry;
158 rejectedFocusEntry.actionOn = INCOMING;
159 rejectedFocusEntry.hintType = INTERRUPT_HINT_NONE;
160 rejectedFocusEntry.forceType = INTERRUPT_FORCE;
161 rejectedFocusEntry.isReject = true;
162 focusMap.emplace(rejectedStreamsPair, rejectedFocusEntry);
163
164 AUDIO_INFO_LOG("current stream: %s, incoming stream: %s", curStream, newStream);
165 AUDIO_INFO_LOG("actionOn: %d, hintType: %d, forceType: %d isReject: %d",
166 rejectedFocusEntry.actionOn, rejectedFocusEntry.hintType,
167 rejectedFocusEntry.forceType, rejectedFocusEntry.isReject);
168 }
169 xmlFree(newStream);
170 }
171 }
172 currNode = currNode->next;
173 }
174 }
175
ParseAllowedStreams(xmlNode * node,char * curStream,std::map<std::pair<AudioStreamType,AudioStreamType>,AudioFocusEntry> & focusMap)176 void AudioFocusParser::ParseAllowedStreams(xmlNode *node, char *curStream,
177 std::map<std::pair<AudioStreamType, AudioStreamType>, AudioFocusEntry> &focusMap)
178 {
179 xmlNode *currNode = node;
180
181 while (currNode) {
182 if (currNode->type == XML_ELEMENT_NODE) {
183 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("stream_type"))) {
184 char *newStream = reinterpret_cast<char*>(xmlGetProp(currNode,
185 reinterpret_cast<xmlChar*>(const_cast<char*>("value"))));
186 char *aType = reinterpret_cast<char*>(xmlGetProp(currNode,
187 reinterpret_cast<xmlChar*>(const_cast<char*>("action_type"))));
188 char *aTarget = reinterpret_cast<char*>(xmlGetProp(currNode,
189 reinterpret_cast<xmlChar*>(const_cast<char*>("action_on"))));
190 char *isForced = reinterpret_cast<char*>(xmlGetProp(currNode,
191 reinterpret_cast<xmlChar*>(const_cast<char*>("is_forced"))));
192
193 std::map<std::string, AudioStreamType>::iterator it1 = streamMap.find(newStream);
194 std::map<std::string, ActionTarget>::iterator it2 = targetMap.find(aTarget);
195 std::map<std::string, InterruptHint>::iterator it3 = actionMap.find(aType);
196 std::map<std::string, InterruptForceType>::iterator it4 = forceMap.find(isForced);
197 if ((it1 != streamMap.end()) && (it2 != targetMap.end()) && (it3 != actionMap.end()) &&
198 (it4 != forceMap.end())) {
199 std::pair<AudioStreamType, AudioStreamType> allowedStreamsPair =
200 std::make_pair(streamMap[curStream], streamMap[newStream]);
201 AudioFocusEntry allowedFocusEntry;
202 allowedFocusEntry.actionOn = targetMap[aTarget];
203 allowedFocusEntry.hintType = actionMap[aType];
204 allowedFocusEntry.forceType = forceMap[isForced];
205 allowedFocusEntry.isReject = false;
206 focusMap.emplace(allowedStreamsPair, allowedFocusEntry);
207
208 AUDIO_INFO_LOG("current stream: %s, incoming stream: %s", curStream, newStream);
209 AUDIO_INFO_LOG("actionOn: %d, hintType: %d, forceType: %d isReject: %d",
210 allowedFocusEntry.actionOn, allowedFocusEntry.hintType,
211 allowedFocusEntry.forceType, allowedFocusEntry.isReject);
212 }
213 xmlFree(newStream);
214 xmlFree(aType);
215 xmlFree(aTarget);
216 xmlFree(isForced);
217 }
218 }
219 currNode = currNode->next;
220 }
221 }
222 } // namespace AudioStandard
223 } // namespace OHOS
224