1 /*
2 * Copyright (c) 2021-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 "AudioIOHandleMap"
17 #endif
18
19 #include "audio_iohandle_map.h"
20 #include "parameter.h"
21 #include "parameters.h"
22 #include "audio_policy_manager_factory.h"
23
24 #include "audio_server_proxy.h"
25 #include "audio_policy_async_action_handler.h"
26 #include "audio_pipe_manager.h"
27
28 namespace OHOS {
29 namespace AudioStandard {
30
31 class WaitActiveDeviceAction : public PolicyAsyncAction {
32 public:
WaitActiveDeviceAction(int32_t muteDuration,const std::string & portName)33 WaitActiveDeviceAction(int32_t muteDuration, const std::string &portName)
34 : muteDuration_(muteDuration), portName_(portName)
35 {}
36
Exec()37 void Exec() override
38 {
39 AudioIOHandleMap::GetInstance().UnmutePortAfterMuteDuration(muteDuration_, portName_);
40 }
41
42 private:
43 int32_t muteDuration_;
44 const std::string portName_;
45 };
46
47 class UnmutePortAction : public PolicyAsyncAction {
48 public:
UnmutePortAction(int32_t muteDuration,const std::string & portName)49 UnmutePortAction(int32_t muteDuration, const std::string &portName)
50 : muteDuration_(muteDuration), portName_(portName)
51 {}
52
Exec()53 void Exec() override
54 {
55 AudioIOHandleMap::GetInstance().DoUnmutePort(muteDuration_, portName_);
56 }
57
58 private:
59 int32_t muteDuration_;
60 const std::string portName_;
61 };
62
63 static const int64_t WAIT_SET_MUTE_LATENCY_TIME_US = 80000; // 80ms
64 static const int64_t OLD_DEVICE_UNAVALIABLE_MUTE_MS = 1000000; // 1s
65 static const int64_t WAIT_MOVE_DEVICE_MUTE_TIME_MAX_MS = 5000; // 5s
66 static const int64_t US_PER_MS = 1000;
67
68 std::map<std::string, std::string> AudioIOHandleMap::sinkPortStrToClassStrMap_ = {
69 {PRIMARY_SPEAKER, PRIMARY_CLASS},
70 {BLUETOOTH_SPEAKER, A2DP_CLASS},
71 {USB_SPEAKER, USB_CLASS},
72 {DP_SINK, DP_CLASS},
73 {OFFLOAD_PRIMARY_SPEAKER, OFFLOAD_CLASS},
74 {PRIMARY_DIRECT_VOIP, DIRECT_VOIP_CLASS},
75 {PRIMARY_MMAP_VOIP, MMAP_VOIP_CLASS},
76 };
77
DeInit()78 void AudioIOHandleMap::DeInit()
79 {
80 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
81 IOHandles_.clear();
82 }
83
GetCopy()84 std::unordered_map<std::string, AudioIOHandle> AudioIOHandleMap::GetCopy()
85 {
86 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
87 return IOHandles_;
88 }
89
GetModuleIdByKey(std::string moduleName,AudioIOHandle & moduleId)90 bool AudioIOHandleMap::GetModuleIdByKey(std::string moduleName, AudioIOHandle& moduleId)
91 {
92 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
93 if (IOHandles_.count(moduleName)) {
94 moduleId = IOHandles_[moduleName];
95 return true;
96 }
97 return false;
98 }
99
CheckIOHandleExist(std::string moduleName)100 bool AudioIOHandleMap::CheckIOHandleExist(std::string moduleName)
101 {
102 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
103 return (IOHandles_.find(moduleName) != IOHandles_.end());
104 }
105
DelIOHandleInfo(std::string moduleName)106 void AudioIOHandleMap::DelIOHandleInfo(std::string moduleName)
107 {
108 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
109 IOHandles_.erase(moduleName);
110 }
111
AddIOHandleInfo(std::string moduleName,const AudioIOHandle & moduleId)112 void AudioIOHandleMap::AddIOHandleInfo(std::string moduleName, const AudioIOHandle& moduleId)
113 {
114 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
115 IOHandles_[moduleName] = moduleId;
116 }
117
118 // private methods
GetSinkIOHandle(DeviceType deviceType)119 AudioIOHandle AudioIOHandleMap::GetSinkIOHandle(DeviceType deviceType)
120 {
121 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
122 AudioIOHandle ioHandle;
123 switch (deviceType) {
124 case DeviceType::DEVICE_TYPE_WIRED_HEADSET:
125 case DeviceType::DEVICE_TYPE_WIRED_HEADPHONES:
126 case DeviceType::DEVICE_TYPE_USB_HEADSET:
127 case DeviceType::DEVICE_TYPE_EARPIECE:
128 case DeviceType::DEVICE_TYPE_SPEAKER:
129 case DeviceType::DEVICE_TYPE_BLUETOOTH_SCO:
130 case DeviceType::DEVICE_TYPE_HDMI:
131 ioHandle = IOHandles_[PRIMARY_SPEAKER];
132 break;
133 case DeviceType::DEVICE_TYPE_USB_ARM_HEADSET:
134 ioHandle = IOHandles_[USB_SPEAKER];
135 break;
136 case DeviceType::DEVICE_TYPE_BLUETOOTH_A2DP:
137 ioHandle = IOHandles_[BLUETOOTH_SPEAKER];
138 break;
139 case DeviceType::DEVICE_TYPE_FILE_SINK:
140 ioHandle = IOHandles_[FILE_SINK];
141 break;
142 case DeviceType::DEVICE_TYPE_DP:
143 ioHandle = IOHandles_[DP_SINK];
144 break;
145 default:
146 ioHandle = IOHandles_[PRIMARY_SPEAKER];
147 break;
148 }
149 return ioHandle;
150 }
151
GetSourceIOHandle(DeviceType deviceType)152 AudioIOHandle AudioIOHandleMap::GetSourceIOHandle(DeviceType deviceType)
153 {
154 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
155 AudioIOHandle ioHandle;
156 switch (deviceType) {
157 case DeviceType::DEVICE_TYPE_USB_ARM_HEADSET:
158 ioHandle = IOHandles_[USB_MIC];
159 break;
160 case DeviceType::DEVICE_TYPE_MIC:
161 ioHandle = IOHandles_[PRIMARY_MIC];
162 break;
163 case DeviceType::DEVICE_TYPE_FILE_SOURCE:
164 ioHandle = IOHandles_[FILE_SOURCE];
165 break;
166 case DeviceType::DEVICE_TYPE_BLUETOOTH_A2DP_IN:
167 ioHandle = IOHandles_[BLUETOOTH_MIC];
168 break;
169 case DeviceType::DEVICE_TYPE_ACCESSORY:
170 ioHandle = IOHandles_[ACCESSORY_SOURCE];
171 break;
172 default:
173 ioHandle = IOHandles_[PRIMARY_MIC];
174 break;
175 }
176 return ioHandle;
177 }
178
OpenPortAndInsertIOHandle(const std::string & moduleName,const AudioModuleInfo & moduleInfo)179 int32_t AudioIOHandleMap::OpenPortAndInsertIOHandle(const std::string &moduleName,
180 const AudioModuleInfo &moduleInfo)
181 {
182 uint32_t paIndex = 0;
183 AudioIOHandle ioHandle = AudioPolicyManagerFactory::GetAudioPolicyManager().OpenAudioPort(moduleInfo, paIndex);
184 CHECK_AND_RETURN_RET_LOG(ioHandle != HDI_INVALID_ID, ERR_INVALID_HANDLE,
185 "OpenAudioPort failed ioHandle[%{public}u]", ioHandle);
186 CHECK_AND_RETURN_RET_LOG(paIndex != OPEN_PORT_FAILURE, ERR_OPERATION_FAILED,
187 "OpenAudioPort failed paId[%{public}u]", paIndex);
188
189 std::shared_ptr<AudioPipeInfo> pipeInfo = std::make_shared<AudioPipeInfo>();
190 pipeInfo->id_ = ioHandle;
191 pipeInfo->paIndex_ = paIndex;
192 pipeInfo->name_ = moduleName;
193 if (moduleInfo.role == "sink") {
194 pipeInfo->pipeRole_ = PIPE_ROLE_OUTPUT;
195 pipeInfo->routeFlag_ = AUDIO_OUTPUT_FLAG_NORMAL;
196 } else {
197 pipeInfo->pipeRole_ = PIPE_ROLE_INPUT;
198 pipeInfo->routeFlag_ = moduleInfo.sourceType == std::to_string(SourceType::SOURCE_TYPE_WAKEUP) ?
199 AUDIO_INPUT_FLAG_WAKEUP : AUDIO_INPUT_FLAG_NORMAL;
200 }
201 pipeInfo->adapterName_ = moduleInfo.adapterName;
202 pipeInfo->moduleInfo_ = moduleInfo;
203 pipeInfo->pipeAction_ = PIPE_ACTION_DEFAULT;
204 pipeInfo->InitAudioStreamInfo();
205 AudioPipeManager::GetPipeManager()->AddAudioPipeInfo(pipeInfo);
206
207 AddIOHandleInfo(moduleName, ioHandle);
208
209 return SUCCESS;
210 }
211
ClosePortAndEraseIOHandle(const std::string & moduleName)212 int32_t AudioIOHandleMap::ClosePortAndEraseIOHandle(const std::string &moduleName)
213 {
214 std::shared_ptr<AudioPipeManager> pipeManager = AudioPipeManager::GetPipeManager();
215 auto pipeInfoInput = pipeManager->GetPipeinfoByNameAndFlag("primary", AUDIO_INPUT_FLAG_NORMAL);
216 if (pipeInfoInput != nullptr && pipeInfoInput->softLinkFlag_) {
217 pipeInfoInput->streamDescMap_.clear();
218 pipeInfoInput->streamDescriptors_.clear();
219 pipeManager->UpdateAudioPipeInfo(pipeInfoInput);
220 return SUCCESS;
221 }
222 AudioIOHandle ioHandle;
223 CHECK_AND_RETURN_RET_LOG(GetModuleIdByKey(moduleName, ioHandle), ERROR,
224 "can not find %{public}s in io map", moduleName.c_str());
225 DelIOHandleInfo(moduleName);
226
227 uint32_t paIndex = pipeManager->GetPaIndexByIoHandle(ioHandle);
228 pipeManager->RemoveAudioPipeInfo(ioHandle);
229
230 int32_t result = AudioPolicyManagerFactory::GetAudioPolicyManager().CloseAudioPort(ioHandle, paIndex);
231 CHECK_AND_RETURN_RET_LOG(result == SUCCESS, result, "CloseAudioPort failed %{public}d", result);
232 return SUCCESS;
233 }
234
MuteSinkPort(const std::string & portName,int32_t duration,bool isSync,bool isSleepEnabled)235 void AudioIOHandleMap::MuteSinkPort(const std::string &portName, int32_t duration, bool isSync, bool isSleepEnabled)
236 {
237 if (sinkPortStrToClassStrMap_.count(portName) > 0) {
238 // Mute by render sink. (primary、a2dp、usb、dp、offload)
239 AudioServerProxy::GetInstance().SetSinkMuteForSwitchDeviceProxy(sinkPortStrToClassStrMap_.at(portName),
240 duration, true);
241 } else {
242 // Mute by pa.
243 AudioPolicyManagerFactory::GetAudioPolicyManager().SetSinkMute(portName, true, isSync);
244 }
245
246 std::shared_ptr<WaitActiveDeviceAction> action = std::make_shared<WaitActiveDeviceAction>(duration, portName);
247 CHECK_AND_RETURN_LOG(action != nullptr, "action is nullptr");
248 AsyncActionDesc desc;
249 desc.action = std::static_pointer_cast<PolicyAsyncAction>(action);
250 DelayedSingleton<AudioPolicyAsyncActionHandler>::GetInstance()->PostAsyncAction(desc);
251
252 if (isSleepEnabled) {
253 usleep(WAIT_SET_MUTE_LATENCY_TIME_US); // sleep fix data cache pop.
254 }
255 }
256
MuteDefaultSinkPort(std::string networkID,std::string sinkName)257 void AudioIOHandleMap::MuteDefaultSinkPort(std::string networkID, std::string sinkName)
258 {
259 if (networkID != LOCAL_NETWORK_ID || sinkName != PRIMARY_SPEAKER) {
260 // PA may move the sink to default when unloading module.
261 MuteSinkPort(PRIMARY_SPEAKER, OLD_DEVICE_UNAVALIABLE_MUTE_MS, true);
262 }
263 }
264
SetMoveFinish(bool flag)265 void AudioIOHandleMap::SetMoveFinish(bool flag)
266 {
267 moveDeviceFinished_ = flag;
268 }
269
NotifyUnmutePort()270 void AudioIOHandleMap::NotifyUnmutePort()
271 {
272 std::unique_lock<std::mutex> lock(moveDeviceMutex_);
273 moveDeviceFinished_ = true;
274 moveDeviceCV_.notify_all();
275 }
276
UnmutePortAfterMuteDuration(int32_t muteDuration,const std::string & portName)277 void AudioIOHandleMap::UnmutePortAfterMuteDuration(int32_t muteDuration, const std::string &portName)
278 {
279 Trace trace("UnmutePortAfterMuteDuration:" + portName + " for " + std::to_string(muteDuration) + "us");
280
281 if (!moveDeviceFinished_.load()) {
282 std::unique_lock<std::mutex> lock(moveDeviceMutex_);
283 bool loadWaiting = moveDeviceCV_.wait_for(lock,
284 std::chrono::milliseconds(WAIT_MOVE_DEVICE_MUTE_TIME_MAX_MS),
285 [this] { return moveDeviceFinished_.load(); }
286 );
287 if (!loadWaiting) {
288 AUDIO_ERR_LOG("move device time out");
289 }
290 }
291 AUDIO_INFO_LOG("%{public}d us for device type[%{public}s]", muteDuration, portName.c_str());
292
293 std::shared_ptr<UnmutePortAction> action = std::make_shared<UnmutePortAction>(muteDuration, portName);
294 CHECK_AND_RETURN_LOG(action != nullptr, "action is nullptr");
295 AsyncActionDesc desc;
296 desc.delayTimeMs = muteDuration / US_PER_MS;
297 desc.action = std::static_pointer_cast<PolicyAsyncAction>(action);
298 DelayedSingleton<AudioPolicyAsyncActionHandler>::GetInstance()->PostAsyncAction(desc);
299 }
300
DoUnmutePort(int32_t muteDuration,const std::string & portName)301 void AudioIOHandleMap::DoUnmutePort(int32_t muteDuration, const std::string &portName)
302 {
303 if (sinkPortStrToClassStrMap_.count(portName) > 0) {
304 AudioServerProxy::GetInstance().SetSinkMuteForSwitchDeviceProxy(sinkPortStrToClassStrMap_.at(portName),
305 muteDuration, false);
306 } else {
307 AudioPolicyManagerFactory::GetAudioPolicyManager().SetSinkMute(portName, false);
308 }
309 }
310
ReloadPortAndUpdateIOHandle(std::shared_ptr<AudioPipeInfo> & pipeInfo,const AudioModuleInfo & moduleInfo)311 int32_t AudioIOHandleMap::ReloadPortAndUpdateIOHandle(std::shared_ptr<AudioPipeInfo> &pipeInfo,
312 const AudioModuleInfo &moduleInfo)
313 {
314 std::string oldModuleName = pipeInfo->moduleInfo_.name;
315 AudioIOHandle ioHandle;
316 CHECK_AND_RETURN_RET_LOG(GetModuleIdByKey(oldModuleName, ioHandle), ERROR,
317 "can not find %{public}s in io map", oldModuleName.c_str());
318 DelIOHandleInfo(oldModuleName);
319
320 AUDIO_INFO_LOG("[close-module] %{public}s, id:%{public}d, paIndex: %{public}u",
321 oldModuleName.c_str(), ioHandle, pipeInfo->paIndex_);
322 int32_t result = AudioPolicyManagerFactory::GetAudioPolicyManager().CloseAudioPort(ioHandle,
323 pipeInfo->paIndex_);
324 CHECK_AND_RETURN_RET_LOG(result == SUCCESS, result, "CloseAudioPort failed %{public}d", result);
325
326 uint32_t paIndex = 0;
327 ioHandle = AudioPolicyManagerFactory::GetAudioPolicyManager().OpenAudioPort(moduleInfo, paIndex);
328 CHECK_AND_RETURN_RET_LOG(ioHandle != HDI_INVALID_ID, ERR_INVALID_HANDLE,
329 "OpenAudioPort failed ioHandle[%{public}u]", ioHandle);
330 CHECK_AND_RETURN_RET_LOG(paIndex != OPEN_PORT_FAILURE, ERR_OPERATION_FAILED,
331 "OpenAudioPort failed paId[%{public}u]", paIndex);
332 AUDIO_INFO_LOG("[open-module] %{public}s, id:%{public}d, paIndex: %{public}u",
333 moduleInfo.name.c_str(), ioHandle, paIndex);
334
335 pipeInfo->id_ = ioHandle;
336 pipeInfo->paIndex_ = paIndex;
337 pipeInfo->adapterName_ = moduleInfo.adapterName;
338 pipeInfo->moduleInfo_ = moduleInfo;
339 pipeInfo->pipeAction_ = PIPE_ACTION_DEFAULT;
340 pipeInfo->InitAudioStreamInfo();
341
342 AddIOHandleInfo(moduleInfo.name, ioHandle);
343 return SUCCESS;
344 }
345 }
346 }
347