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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioFocusParser"
17 #endif
18
19 #include "audio_focus_parser.h"
20 #ifdef USE_CONFIG_POLICY
21 #include "config_policy_utils.h"
22 #endif
23
24 #include "media_monitor_manager.h"
25
26 namespace OHOS {
27 namespace AudioStandard {
28
29 // Initialize stream map with string vs AudioStreamType
30 std::map<std::string, AudioFocusType> AudioFocusParser::audioFocusMap = {
31 // stream type for audio interrupt
32 {"STREAM_VOICE_CALL",
33 {AudioStreamType::STREAM_VOICE_CALL, SourceType::SOURCE_TYPE_INVALID, true}},
34 {"STREAM_VOICE_CALL_ASSISTANT",
35 {AudioStreamType::STREAM_VOICE_CALL_ASSISTANT, SourceType::SOURCE_TYPE_INVALID, true}},
36 {"STREAM_VOICE_MESSAGE",
37 {AudioStreamType::STREAM_VOICE_MESSAGE, SourceType::SOURCE_TYPE_INVALID, true}},
38 {"STREAM_SYSTEM",
39 {AudioStreamType::STREAM_SYSTEM, SourceType::SOURCE_TYPE_INVALID, true}},
40 {"STREAM_RING",
41 {AudioStreamType::STREAM_RING, SourceType::SOURCE_TYPE_INVALID, true}},
42 {"STREAM_MUSIC",
43 {AudioStreamType::STREAM_MUSIC, SourceType::SOURCE_TYPE_INVALID, true}},
44 {"STREAM_MOVIE",
45 {AudioStreamType::STREAM_MOVIE, SourceType::SOURCE_TYPE_INVALID, true}},
46 {"STREAM_GAME",
47 {AudioStreamType::STREAM_GAME, SourceType::SOURCE_TYPE_INVALID, true}},
48 {"STREAM_SPEECH",
49 {AudioStreamType::STREAM_SPEECH, SourceType::SOURCE_TYPE_INVALID, true}},
50 {"STREAM_NAVIGATION",
51 {AudioStreamType::STREAM_NAVIGATION, SourceType::SOURCE_TYPE_INVALID, true}},
52 {"STREAM_ALARM",
53 {AudioStreamType::STREAM_ALARM, SourceType::SOURCE_TYPE_INVALID, true}},
54 {"STREAM_NOTIFICATION",
55 {AudioStreamType::STREAM_NOTIFICATION, SourceType::SOURCE_TYPE_INVALID, true}},
56 {"STREAM_SYSTEM_ENFORCED",
57 {AudioStreamType::STREAM_SYSTEM_ENFORCED, SourceType::SOURCE_TYPE_INVALID, true}},
58 {"STREAM_DTMF",
59 {AudioStreamType::STREAM_DTMF, SourceType::SOURCE_TYPE_INVALID, true}},
60 {"STREAM_VOICE_ASSISTANT",
61 {AudioStreamType::STREAM_VOICE_ASSISTANT, SourceType::SOURCE_TYPE_INVALID, true}},
62 {"STREAM_ACCESSIBILITY",
63 {AudioStreamType::STREAM_ACCESSIBILITY, SourceType::SOURCE_TYPE_INVALID, true}},
64 {"STREAM_ULTRASONIC",
65 {AudioStreamType::STREAM_ULTRASONIC, SourceType::SOURCE_TYPE_INVALID, true}},
66 {"STREAM_INTERNAL_FORCE_STOP",
67 {AudioStreamType::STREAM_INTERNAL_FORCE_STOP, SourceType::SOURCE_TYPE_INVALID, true}},
68 {"STREAM_VOICE_COMMUNICATION",
69 {AudioStreamType::STREAM_VOICE_COMMUNICATION, SourceType::SOURCE_TYPE_INVALID, true}},
70 {"STREAM_VOICE_RING",
71 {AudioStreamType::STREAM_VOICE_RING, SourceType::SOURCE_TYPE_INVALID, true}},
72 {"STREAM_CAMCORDER",
73 {AudioStreamType::STREAM_CAMCORDER, SourceType::SOURCE_TYPE_INVALID, true}},
74 // source type for audio interrupt
75 {"SOURCE_TYPE_MIC",
76 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_MIC, false}},
77 {"SOURCE_TYPE_CAMCORDER",
78 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_CAMCORDER, false}},
79 {"SOURCE_TYPE_VOICE_RECOGNITION",
80 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_VOICE_RECOGNITION, false}},
81 {"SOURCE_TYPE_WAKEUP",
82 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_WAKEUP, false}},
83 {"SOURCE_TYPE_VOICE_COMMUNICATION",
84 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_VOICE_COMMUNICATION, false}},
85 {"SOURCE_TYPE_ULTRASONIC",
86 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_ULTRASONIC, false}},
87 {"SOURCE_TYPE_PLAYBACK_CAPTURE",
88 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_PLAYBACK_CAPTURE, false}},
89 {"SOURCE_TYPE_VOICE_CALL",
90 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_VOICE_CALL, false}},
91 {"SOURCE_TYPE_VOICE_MESSAGE",
92 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_VOICE_MESSAGE, false}},
93 {"SOURCE_TYPE_REMOTE_CAST",
94 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_REMOTE_CAST, false}},
95 {"SOURCE_TYPE_VOICE_TRANSCRIPTION",
96 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_VOICE_TRANSCRIPTION, false}},
97 {"SOURCE_TYPE_UNPROCESSED",
98 {AudioStreamType::STREAM_DEFAULT, SourceType::SOURCE_TYPE_UNPROCESSED, false}},
99 };
100
101 // Initialize action map with string vs InterruptActionType
102 std::map<std::string, InterruptHint> AudioFocusParser::actionMap = {
103 {"DUCK", INTERRUPT_HINT_DUCK},
104 {"PAUSE", INTERRUPT_HINT_PAUSE},
105 {"REJECT", INTERRUPT_HINT_STOP},
106 {"STOP", INTERRUPT_HINT_STOP},
107 {"PLAY", INTERRUPT_HINT_NONE}
108 };
109
110 // Initialize target map with string vs InterruptActionTarget
111 std::map<std::string, ActionTarget> AudioFocusParser::targetMap = {
112 {"incoming", INCOMING},
113 {"existing", CURRENT},
114 {"both", BOTH},
115 };
116
117 std::map<std::string, InterruptForceType> AudioFocusParser::forceMap = {
118 {"true", INTERRUPT_FORCE},
119 {"false", INTERRUPT_SHARE},
120 };
121
AudioFocusParser()122 AudioFocusParser::AudioFocusParser()
123 {
124 curNode_ = AudioXmlNode::Create();
125 AUDIO_DEBUG_LOG("AudioFocusParser ctor");
126 }
127
~AudioFocusParser()128 AudioFocusParser::~AudioFocusParser()
129 {
130 curNode_ = nullptr;
131 AUDIO_DEBUG_LOG("AudioFocusParser dtor");
132 }
133
LoadDefaultConfig(std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)134 void AudioFocusParser::LoadDefaultConfig(std::map<std::pair<AudioFocusType, AudioFocusType>,
135 AudioFocusEntry> &focusMap)
136 {
137 }
138
LoadConfig(std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)139 int32_t AudioFocusParser::LoadConfig(std::map<std::pair<AudioFocusType, AudioFocusType>,
140 AudioFocusEntry> &focusMap)
141 {
142 #ifdef USE_CONFIG_POLICY
143 char buf[MAX_PATH_LEN];
144 char *path = GetOneCfgFile(AUDIO_FOCUS_CONFIG_FILE, buf, MAX_PATH_LEN);
145 #else
146 const char *path = AUDIO_FOCUS_CONFIG_FILE;
147 #endif
148 CHECK_AND_RETURN_RET_LOG(path != nullptr && *path != '\0', ERROR, "invalid path!");
149 if (curNode_->Config(path, nullptr, 0) != SUCCESS) {
150 AUDIO_ERR_LOG("load path: %{public}s fail!", path);
151 LoadDefaultConfig(focusMap);
152 WriteConfigErrorEvent();
153 return ERROR;
154 }
155 CHECK_AND_RETURN_RET_LOG(curNode_->IsNodeValid(), ERROR, "root element is null");
156
157 if (!curNode_->CompareName("audio_focus_policy")) {
158 AUDIO_ERR_LOG("Missing tag - focus_policy in : %s", AUDIO_FOCUS_CONFIG_FILE);
159 WriteConfigErrorEvent();
160 curNode_ = nullptr;
161 return ERROR;
162 }
163
164 curNode_->MoveToChildren();
165 CHECK_AND_RETURN_RET_LOG(curNode_->IsNodeValid(), ERROR, "Missing child: %s", AUDIO_FOCUS_CONFIG_FILE);
166
167 while (curNode_->IsNodeValid()) {
168 if (curNode_->CompareName("focus_type")) {
169 ParseStreams(curNode_->GetCopyNode(), focusMap);
170 break;
171 } else {
172 curNode_->MoveToNext();
173 }
174 }
175 curNode_ = nullptr;
176 return SUCCESS;
177 }
178
WriteConfigErrorEvent()179 void AudioFocusParser::WriteConfigErrorEvent()
180 {
181 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
182 Media::MediaMonitor::AUDIO, Media::MediaMonitor::LOAD_CONFIG_ERROR, Media::MediaMonitor::FAULT_EVENT);
183 bean->Add("CATEGORY", Media::MediaMonitor::AUDIO_INTERRUPT_POLICY_CONFIG);
184 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
185 }
186
ParseFocusChildrenMap(std::shared_ptr<AudioXmlNode> curNode,const std::string & curStream,std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)187 void AudioFocusParser::ParseFocusChildrenMap(std::shared_ptr<AudioXmlNode> curNode, const std::string &curStream,
188 std::map<std::pair<AudioFocusType, AudioFocusType>, AudioFocusEntry> &focusMap)
189 {
190 while (curNode->IsNodeValid()) {
191 if (curNode->IsElementNode()) {
192 if (curNode->CompareName("deny")) {
193 ParseRejectedStreams(curNode->GetChildrenNode(), curStream, focusMap);
194 } else {
195 ParseAllowedStreams(curNode->GetChildrenNode(), curStream, focusMap);
196 }
197 }
198 curNode->MoveToNext();
199 }
200 }
201
ParseFocusMap(std::shared_ptr<AudioXmlNode> curNode,const std::string & curStream,std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)202 void AudioFocusParser::ParseFocusMap(std::shared_ptr<AudioXmlNode> curNode, const std::string &curStream,
203 std::map<std::pair<AudioFocusType, AudioFocusType>, AudioFocusEntry> &focusMap)
204 {
205 while (curNode->IsNodeValid()) {
206 if (curNode->CompareName("focus_table")) {
207 AUDIO_DEBUG_LOG("node type: Element, name: %s", curNode->GetName().c_str());
208 ParseFocusChildrenMap(curNode->GetChildrenNode(), curStream, focusMap);
209 }
210 curNode->MoveToNext();
211 }
212 }
213
ParseStreams(std::shared_ptr<AudioXmlNode> curNode,std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)214 void AudioFocusParser::ParseStreams(std::shared_ptr<AudioXmlNode> curNode,
215 std::map<std::pair<AudioFocusType, AudioFocusType>, AudioFocusEntry> &focusMap)
216 {
217 while (curNode->IsNodeValid()) {
218 if (curNode->IsElementNode()) {
219 std::string typeStr;
220 curNode->GetProp("value", typeStr);
221 std::map<std::string, AudioFocusType>::iterator it = audioFocusMap.find(typeStr);
222 if (it != audioFocusMap.end()) {
223 AUDIO_DEBUG_LOG("stream type: %{public}s", typeStr.c_str());
224 ParseFocusMap(curNode->GetChildrenNode(), typeStr, focusMap);
225 }
226 }
227 curNode->MoveToNext();
228 }
229 }
230
AddRejectedFocusEntry(std::shared_ptr<AudioXmlNode> curNode,const std::string & curStream,std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)231 void AudioFocusParser::AddRejectedFocusEntry(std::shared_ptr<AudioXmlNode> curNode, const std::string &curStream,
232 std::map<std::pair<AudioFocusType, AudioFocusType>, AudioFocusEntry> &focusMap)
233 {
234 std::string newStreamStr;
235 curNode->GetProp("value", newStreamStr);
236 std::map<std::string, AudioFocusType>::iterator it1 = audioFocusMap.find(newStreamStr);
237 if (it1 != audioFocusMap.end()) {
238 std::pair<AudioFocusType, AudioFocusType> rejectedStreamsPair =
239 std::make_pair(audioFocusMap[curStream], audioFocusMap[newStreamStr]);
240 AudioFocusEntry rejectedFocusEntry;
241 rejectedFocusEntry.actionOn = INCOMING;
242 rejectedFocusEntry.hintType = INTERRUPT_HINT_STOP;
243 rejectedFocusEntry.forceType = INTERRUPT_FORCE;
244 rejectedFocusEntry.isReject = true;
245 focusMap.emplace(rejectedStreamsPair, rejectedFocusEntry);
246
247 AUDIO_DEBUG_LOG("current stream: %s, incoming stream: %s", curStream.c_str(), newStreamStr.c_str());
248 AUDIO_DEBUG_LOG("actionOn: %d, hintType: %d, forceType: %d isReject: %d",
249 rejectedFocusEntry.actionOn, rejectedFocusEntry.hintType,
250 rejectedFocusEntry.forceType, rejectedFocusEntry.isReject);
251 }
252 }
253
ParseRejectedStreams(std::shared_ptr<AudioXmlNode> curNode,const std::string & curStream,std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)254 void AudioFocusParser::ParseRejectedStreams(std::shared_ptr<AudioXmlNode> curNode, const std::string &curStream,
255 std::map<std::pair<AudioFocusType, AudioFocusType>, AudioFocusEntry> &focusMap)
256 {
257 while (curNode->IsNodeValid()) {
258 if (curNode->CompareName("focus_type")) {
259 AddRejectedFocusEntry(curNode->GetCopyNode(), curStream, focusMap);
260 }
261 curNode->MoveToNext();
262 }
263 }
264
AddAllowedFocusEntry(std::shared_ptr<AudioXmlNode> curNode,const std::string & curStream,std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)265 void AudioFocusParser::AddAllowedFocusEntry(std::shared_ptr<AudioXmlNode> curNode, const std::string &curStream,
266 std::map<std::pair<AudioFocusType, AudioFocusType>, AudioFocusEntry> &focusMap)
267 {
268 std::string newStreamStr;
269 std::string aTargetStr;
270 std::string aTypeStr;
271 std::string isForcedStr;
272 curNode->GetProp("value", newStreamStr);
273 curNode->GetProp("action_on", aTargetStr);
274 curNode->GetProp("action_type", aTypeStr);
275 curNode->GetProp("is_forced", isForcedStr);
276
277 std::map<std::string, AudioFocusType>::iterator it1 = audioFocusMap.find(newStreamStr);
278 std::map<std::string, ActionTarget>::iterator it2 = targetMap.find(aTargetStr);
279 std::map<std::string, InterruptHint>::iterator it3 = actionMap.find(aTypeStr);
280 std::map<std::string, InterruptForceType>::iterator it4 = forceMap.find(isForcedStr);
281 if ((it1 != audioFocusMap.end()) && (it2 != targetMap.end()) && (it3 != actionMap.end()) &&
282 (it4 != forceMap.end())) {
283 std::pair<AudioFocusType, AudioFocusType> allowedStreamsPair =
284 std::make_pair(audioFocusMap[curStream], audioFocusMap[newStreamStr]);
285 AudioFocusEntry allowedFocusEntry;
286 allowedFocusEntry.actionOn = targetMap[aTargetStr];
287 allowedFocusEntry.hintType = actionMap[aTypeStr];
288 allowedFocusEntry.forceType = forceMap[isForcedStr];
289 allowedFocusEntry.isReject = false;
290 focusMap.emplace(allowedStreamsPair, allowedFocusEntry);
291
292 AUDIO_DEBUG_LOG("current stream: %s, incoming stream: %s", curStream.c_str(), newStreamStr.c_str());
293 AUDIO_DEBUG_LOG("actionOn: %d, hintType: %d, forceType: %d isReject: %d",
294 allowedFocusEntry.actionOn, allowedFocusEntry.hintType,
295 allowedFocusEntry.forceType, allowedFocusEntry.isReject);
296 }
297 }
298
ParseAllowedStreams(std::shared_ptr<AudioXmlNode> curNode,const std::string & curStream,std::map<std::pair<AudioFocusType,AudioFocusType>,AudioFocusEntry> & focusMap)299 void AudioFocusParser::ParseAllowedStreams(std::shared_ptr<AudioXmlNode> curNode, const std::string &curStream,
300 std::map<std::pair<AudioFocusType, AudioFocusType>, AudioFocusEntry> &focusMap)
301 {
302 while (curNode->IsNodeValid()) {
303 if (curNode->CompareName("focus_type")) {
304 AddAllowedFocusEntry(curNode->GetCopyNode(), curStream, focusMap);
305 }
306 curNode->MoveToNext();
307 }
308 }
309 } // namespace AudioStandard
310 } // namespace OHOS
311