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