1 /*
2 * Copyright (c) 2025 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 "AudioInterruptService"
17 #endif
18
19 #include "audio_interrupt_service.h"
20
21 #include "audio_focus_parser.h"
22 #include "standard_audio_policy_manager_listener_proxy.h"
23 #include "media_monitor_manager.h"
24
25 #include "dfx_utils.h"
26 #include "app_mgr_client.h"
27 #include "dfx_msg_manager.h"
28 #include "audio_server_proxy.h"
29
30 namespace OHOS {
31 namespace AudioStandard {
AudioInterruptZoneDump(std::string & dumpString)32 void AudioInterruptService::AudioInterruptZoneDump(std::string &dumpString)
33 {
34 std::unordered_map<int32_t, std::shared_ptr<AudioInterruptZone>> audioInterruptZonesMapDump;
35 AddDumpInfo(audioInterruptZonesMapDump);
36 dumpString += "\nAudioInterrupt Zone:\n";
37 AppendFormat(dumpString, "- %zu AudioInterruptZoneDump (s) available:\n",
38 zonesMap_.size());
39 for (const auto&[zoneID, audioInterruptZoneDump] : audioInterruptZonesMapDump) {
40 if (zoneID < 0) {
41 continue;
42 }
43 AppendFormat(dumpString, " - Zone ID: %d\n", zoneID);
44
45 AppendFormat(dumpString, " - Interrupt callback size: %zu\n",
46 audioInterruptZoneDump->interruptCbStreamIdsMap.size());
47 AppendFormat(dumpString, " - The streamIds as follow:\n");
48 for (auto streamId : audioInterruptZoneDump->interruptCbStreamIdsMap) {
49 AppendFormat(dumpString, " - StreamId: %u -- have interrupt callback.\n", streamId);
50 }
51
52 AppendFormat(dumpString, " - Audio policy client proxy callback size: %zu\n",
53 audioInterruptZoneDump->audioPolicyClientProxyCBClientPidMap.size());
54 AppendFormat(dumpString, " - The clientPids as follow:\n");
55 for (auto pid : audioInterruptZoneDump->audioPolicyClientProxyCBClientPidMap) {
56 AppendFormat(dumpString, " - ClientPid: %d -- have audiopolicy client proxy callback.\n", pid);
57 }
58
59 std::list<std::pair<AudioInterrupt, AudioFocuState>> audioFocusInfoList
60 = audioInterruptZoneDump->audioFocusInfoList;
61 AppendFormat(dumpString, " - %zu Audio Focus Info (s) available:\n", audioFocusInfoList.size());
62 uint32_t invalidStreamId = static_cast<uint32_t>(-1);
63 for (auto iter = audioFocusInfoList.begin(); iter != audioFocusInfoList.end(); ++iter) {
64 if ((iter->first).streamId == invalidStreamId) {
65 continue;
66 }
67 AppendFormat(dumpString, " - Pid: %d\n", (iter->first).pid);
68 AppendFormat(dumpString, " - StreamId: %u\n", (iter->first).streamId);
69 AppendFormat(dumpString, " - isAudioSessionInterrupt: %d\n", (iter->first).isAudioSessionInterrupt);
70 AppendFormat(dumpString, " - Audio Focus isPlay Id: %d\n", (iter->first).audioFocusType.isPlay);
71 AppendFormat(dumpString, " - Stream Name: %s\n",
72 AudioInfoDumpUtils::GetStreamName((iter->first).audioFocusType.streamType).c_str());
73 AppendFormat(dumpString, " - Source Name: %s\n",
74 AudioInfoDumpUtils::GetSourceName((iter->first).audioFocusType.sourceType).c_str());
75 AppendFormat(dumpString, " - Audio Focus State: %d\n", iter->second);
76 dumpString += "\n";
77 }
78 dumpString += "\n";
79 }
80 return;
81 }
82
AudioSessionInfoDump(std::string & dumpString)83 void AudioInterruptService::AudioSessionInfoDump(std::string &dumpString)
84 {
85 AppendFormat(dumpString, " - The AudioSession as follow:\n");
86 if (sessionService_ == nullptr) {
87 AppendFormat(dumpString, " - The AudioSessionService is null.\n");
88 return;
89 }
90 sessionService_->AudioSessionInfoDump(dumpString);
91 }
92
93 // AudioInterruptDeathRecipient impl begin
AudioInterruptDeathRecipient(const std::shared_ptr<AudioInterruptService> & service,uint32_t streamId)94 AudioInterruptService::AudioInterruptDeathRecipient::AudioInterruptDeathRecipient(
95 const std::shared_ptr<AudioInterruptService> &service,
96 uint32_t streamId)
97 : service_(service), streamId_(streamId)
98 {
99 }
100
OnRemoteDied(const wptr<IRemoteObject> & remote)101 void AudioInterruptService::AudioInterruptDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
102 {
103 std::shared_ptr<AudioInterruptService> service = service_.lock();
104 if (service != nullptr) {
105 service->RemoveClient(ZONEID_DEFAULT, streamId_);
106 }
107 }
108
109 // AudioInterruptClient impl begin
AudioInterruptClient(const std::shared_ptr<AudioInterruptCallback> & callback,const sptr<IRemoteObject> & object,const sptr<AudioInterruptDeathRecipient> & deathRecipient)110 AudioInterruptService::AudioInterruptClient::AudioInterruptClient(
111 const std::shared_ptr<AudioInterruptCallback> &callback,
112 const sptr<IRemoteObject> &object,
113 const sptr<AudioInterruptDeathRecipient> &deathRecipient)
114 : callback_(callback), object_(object), deathRecipient_(deathRecipient)
115 {
116 }
117
~AudioInterruptClient()118 AudioInterruptService::AudioInterruptClient::~AudioInterruptClient()
119 {
120 if (object_ != nullptr) {
121 object_->RemoveDeathRecipient(deathRecipient_);
122 }
123 }
124
OnInterrupt(const InterruptEventInternal & interruptEvent)125 void AudioInterruptService::AudioInterruptClient::OnInterrupt(const InterruptEventInternal &interruptEvent)
126 {
127 if (callback_ != nullptr) {
128 callback_->OnInterrupt(interruptEvent);
129 }
130 }
131
SetCallingUid(uint32_t uid)132 void AudioInterruptService::AudioInterruptClient::SetCallingUid(uint32_t uid)
133 {
134 AUDIO_INFO_LOG("uid: %{public}u", uid);
135 callingUid_ = uid;
136 }
137
GetCallingUid()138 uint32_t AudioInterruptService::AudioInterruptClient::GetCallingUid()
139 {
140 return callingUid_;
141 }
142
SetSessionMuteState(uint32_t sessionId,bool insert,bool muteFlag)143 void AudioInterruptService::SetSessionMuteState(uint32_t sessionId, bool insert, bool muteFlag)
144 {
145 AudioServerProxy::GetInstance().SetSessionMuteState(sessionId, insert, muteFlag);
146 }
147
SetLatestMuteState(const InterruptEventInternal & interruptEvent,const uint32_t & streamId)148 void AudioInterruptService::SetLatestMuteState(const InterruptEventInternal &interruptEvent,
149 const uint32_t &streamId)
150 {
151 CHECK_AND_RETURN_LOG(interruptEvent.hintType == INTERRUPT_HINT_MUTE ||
152 interruptEvent.hintType == INTERRUPT_HINT_UNMUTE, "unsupported hintType: %{public}d",
153 interruptEvent.hintType);
154 bool muteFlag = interruptEvent.hintType == INTERRUPT_HINT_MUTE;
155 AudioServerProxy::GetInstance().SetLatestMuteState(streamId, muteFlag);
156 }
157
UpdateMuteAudioFocusStrategy(const AudioInterrupt & currentInterrupt,const AudioInterrupt & incomingInterrupt,AudioFocusEntry & focusEntry)158 void AudioInterruptService::UpdateMuteAudioFocusStrategy(const AudioInterrupt ¤tInterrupt,
159 const AudioInterrupt &incomingInterrupt, AudioFocusEntry &focusEntry)
160 {
161 if (currentInterrupt.strategy == InterruptStrategy::DEFAULT &&
162 incomingInterrupt.strategy == InterruptStrategy::DEFAULT) {
163 return;
164 }
165
166 if ((focusEntry.hintType != INTERRUPT_HINT_STOP &&
167 focusEntry.hintType != INTERRUPT_HINT_PAUSE) ||
168 incomingInterrupt.audioFocusType.streamType == STREAM_INTERNAL_FORCE_STOP) {
169 AUDIO_INFO_LOG("streamId: %{public}u, keep current hintType=%{public}d",
170 currentInterrupt.streamId, focusEntry.hintType);
171 return;
172 }
173
174 if (currentInterrupt.strategy == InterruptStrategy::MUTE) {
175 focusEntry.actionOn = CURRENT;
176 }
177 if (incomingInterrupt.strategy == InterruptStrategy::MUTE) {
178 focusEntry.actionOn = INCOMING;
179 }
180
181 AUDIO_INFO_LOG("currentStreamId:%{public}u, incomingStreamId:%{public}u, action:%{public}u",
182 currentInterrupt.streamId, incomingInterrupt.streamId, focusEntry.actionOn);
183 focusEntry.isReject = false;
184 focusEntry.hintType = INTERRUPT_HINT_MUTE;
185 }
186
ProcessActiveStreamFocus(std::list<std::pair<AudioInterrupt,AudioFocuState>> & audioFocusInfoList,const AudioInterrupt & incomingInterrupt,AudioFocuState & incomingState,std::list<std::pair<AudioInterrupt,AudioFocuState>>::iterator & activeInterrupt)187 int32_t AudioInterruptService::ProcessActiveStreamFocus(
188 std::list<std::pair<AudioInterrupt, AudioFocuState>> &audioFocusInfoList,
189 const AudioInterrupt &incomingInterrupt, AudioFocuState &incomingState,
190 std::list<std::pair<AudioInterrupt, AudioFocuState>>::iterator &activeInterrupt)
191 {
192 incomingState = ACTIVE;
193 activeInterrupt = audioFocusInfoList.end();
194
195 for (auto iterActive = audioFocusInfoList.begin(); iterActive != audioFocusInfoList.end(); ++iterActive) {
196 activeInterrupt = iterActive;
197 if (IsSameAppInShareMode(incomingInterrupt, iterActive->first)) { continue; }
198 // if peeling is the incomming interrupt while at the momount there are already some existing recordings
199 // peeling should be rejected
200 if (IsLowestPriorityRecording(incomingInterrupt) && IsRecordingInterruption(iterActive->first)) {
201 incomingState = STOP;
202 AUDIO_INFO_LOG("PEELING AUDIO fail, there's a device recording");
203 break;
204 }
205
206 std::pair<AudioFocusType, AudioFocusType> focusPair =
207 std::make_pair((iterActive->first).audioFocusType, incomingInterrupt.audioFocusType);
208 CHECK_AND_RETURN_RET_LOG(focusCfgMap_.find(focusPair) != focusCfgMap_.end(),
209 ERR_INVALID_PARAM,
210 "no focus cfg, active stream type = %{public}d, incoming stream type = %{public}d",
211 static_cast<int32_t>(focusPair.first.streamType),
212 static_cast<int32_t>(focusPair.second.streamType));
213 AudioFocusEntry focusEntry = focusCfgMap_[focusPair];
214 UpdateAudioFocusStrategy(iterActive->first, incomingInterrupt, focusEntry);
215 CheckIncommingFoucsValidity(focusEntry, incomingInterrupt, incomingInterrupt.currencySources.sourcesTypes);
216 if (FocusEntryContinue(iterActive, focusEntry, incomingInterrupt)) { continue; }
217 if (focusEntry.isReject) {
218 if (IsGameAvoidCallbackCase(incomingInterrupt)) {
219 incomingState = PAUSE;
220 AUDIO_INFO_LOG("incomingState: %{public}d", incomingState);
221 continue;
222 }
223
224 AUDIO_INFO_LOG("the incoming stream is rejected by streamId:%{public}d, pid:%{public}d",
225 (iterActive->first).streamId, (iterActive->first).pid);
226 incomingState = STOP;
227 break;
228 }
229 incomingState = GetNewIncomingState(focusEntry.hintType, incomingState);
230 }
231 if (incomingState == STOP && !incomingInterrupt.deviceTag.empty()) {
232 incomingState = ACTIVE;
233 }
234 return SUCCESS;
235 }
236
ReportRecordGetFocusFail(const AudioInterrupt & incomingInterrupt,const AudioInterrupt & activeInterrupt,int32_t reason)237 void AudioInterruptService::ReportRecordGetFocusFail(const AudioInterrupt &incomingInterrupt,
238 const AudioInterrupt &activeInterrupt, int32_t reason)
239 {
240 CHECK_AND_RETURN_LOG(incomingInterrupt.audioFocusType.sourceType != SOURCE_TYPE_INVALID &&
241 incomingInterrupt.audioFocusType.sourceType != SOURCE_TYPE_INVALID, "not recording");
242 AUDIO_INFO_LOG("recording failed to start, incoming: sourceType %{public}d pid %{public}d uid %{public}d"\
243 "active: sourceType %{public}d pid %{public}d uid %{public}d",
244 incomingInterrupt.audioFocusType.sourceType, incomingInterrupt.pid, incomingInterrupt.uid,
245 activeInterrupt.audioFocusType.sourceType, activeInterrupt.pid, activeInterrupt.uid);
246
247 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
248 Media::MediaMonitor::ModuleId::AUDIO, Media::MediaMonitor::EventId::RECORD_ERROR,
249 Media::MediaMonitor::EventType::FAULT_EVENT);
250 CHECK_AND_RETURN_LOG(bean != nullptr, "bean is nullptr");
251
252 bean->Add("INCOMING_SOURCE", incomingInterrupt.audioFocusType.sourceType);
253 bean->Add("INCOMING_PID", incomingInterrupt.pid);
254 bean->Add("INCOMING_UID", incomingInterrupt.uid);
255 bean->Add("ACTIVE_SOURCE", activeInterrupt.audioFocusType.sourceType);
256 bean->Add("ACTIVE_PID", activeInterrupt.pid);
257 bean->Add("ACTIVE_UID", activeInterrupt.uid);
258 bean->Add("REASON", reason);
259 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
260 }
261
IsCapturerFocusAvailable(const int32_t zoneId,const AudioCapturerInfo & capturerInfo)262 bool AudioInterruptService::IsCapturerFocusAvailable(const int32_t zoneId, const AudioCapturerInfo &capturerInfo)
263 {
264 if (isPreemptMode_) {
265 AUDIO_INFO_LOG("Preempt mode, recording is not allowed");
266 return false;
267 }
268
269 AudioInterrupt incomingInterrupt;
270 incomingInterrupt.audioFocusType.sourceType = capturerInfo.sourceType;
271 incomingInterrupt.audioFocusType.isPlay = false;
272 AudioFocuState incomingState = ACTIVE;
273 auto itZone = zonesMap_.find(zoneId);
274 CHECK_AND_RETURN_RET_LOG(itZone != zonesMap_.end(), false, "can not find zoneid");
275 std::list<std::pair<AudioInterrupt, AudioFocuState>> audioFocusInfoList;
276 if (itZone->second != nullptr) {
277 audioFocusInfoList = itZone->second->audioFocusInfoList;
278 }
279 std::list<std::pair<AudioInterrupt, AudioFocuState>>::iterator activeInterrupt = audioFocusInfoList.end();
280 int32_t res = ProcessActiveStreamFocus(audioFocusInfoList, incomingInterrupt, incomingState, activeInterrupt);
281 return res == SUCCESS && incomingState < PAUSE;
282 }
283
ClearAudioFocusBySessionID(const int32_t & sessionID)284 int32_t AudioInterruptService::ClearAudioFocusBySessionID(const int32_t &sessionID)
285 {
286 AUDIO_INFO_LOG("start clear audio focus, target sessionID:%{public}d", sessionID);
287
288 int32_t targetZoneId = -1;
289 AudioInterrupt targetInterrupt;
290 const uint32_t targetSessionID = static_cast<uint32_t>(sessionID);
291 bool clearFlag = false;
292 InterruptEventInternal interruptEvent {INTERRUPT_TYPE_BEGIN, INTERRUPT_FORCE, INTERRUPT_HINT_STOP, 1.0f};
293
294 {
295 std::unique_lock<std::mutex> lock(mutex_);
296 for (const auto&[zoneId, audioInterruptZone] : zonesMap_) {
297 CHECK_AND_CONTINUE_LOG(audioInterruptZone != nullptr, "audioInterruptZone is nullptr");
298
299 auto match = [&](const auto& item) {
300 return sessionID >= 0 && item.first.streamId == targetSessionID;
301 };
302
303 auto it = std::find_if(audioInterruptZone->audioFocusInfoList.begin(),
304 audioInterruptZone->audioFocusInfoList.end(), match);
305 if (it != audioInterruptZone->audioFocusInfoList.end()) {
306 targetZoneId = zoneId;
307 targetInterrupt = it->first;
308 clearFlag = true;
309 break;
310 }
311 }
312 }
313
314 if (clearFlag) {
315 (void)DeactivateAudioInterrupt(targetZoneId, targetInterrupt);
316 {
317 std::unique_lock<std::mutex> lock(mutex_);
318 CHECK_AND_RETURN_RET_LOG(handler_ != nullptr, ERROR, "handler is nullptr");
319 SendInterruptEventCallback(interruptEvent, targetInterrupt.streamId, targetInterrupt);
320 }
321 }
322
323 return SUCCESS;
324 }
325 }
326 } // namespace OHOS
327