• 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 #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