• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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