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