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
27 namespace OHOS {
28 namespace AudioStandard {
29
30 class WaitActiveDeviceAction : public PolicyAsyncAction {
31 public:
WaitActiveDeviceAction(int32_t muteDuration,const std::string & portName)32 WaitActiveDeviceAction(int32_t muteDuration, const std::string &portName)
33 : muteDuration_(muteDuration), portName_(portName)
34 {}
35
Exec()36 void Exec() override
37 {
38 AudioIOHandleMap::GetInstance().UnmutePortAfterMuteDuration(muteDuration_, portName_);
39 }
40
41 private:
42 int32_t muteDuration_;
43 const std::string portName_;
44 };
45
46 class UnmutePortAction : public PolicyAsyncAction {
47 public:
UnmutePortAction(int32_t muteDuration,const std::string & portName)48 UnmutePortAction(int32_t muteDuration, const std::string &portName)
49 : muteDuration_(muteDuration), portName_(portName)
50 {}
51
Exec()52 void Exec() override
53 {
54 AudioIOHandleMap::GetInstance().DoUnmutePort(muteDuration_, portName_);
55 }
56
57 private:
58 int32_t muteDuration_;
59 const std::string portName_;
60 };
61
62 static const int64_t WAIT_SET_MUTE_LATENCY_TIME_US = 80000; // 80ms
63 static const int64_t OLD_DEVICE_UNAVALIABLE_MUTE_MS = 1000000; // 1s
64 static const int64_t WAIT_MOVE_DEVICE_MUTE_TIME_MAX_MS = 5000; // 5s
65 static const int64_t US_PER_MS = 1000;
66
67 std::map<std::string, std::string> AudioIOHandleMap::sinkPortStrToClassStrMap_ = {
68 {PRIMARY_SPEAKER, PRIMARY_CLASS},
69 {BLUETOOTH_SPEAKER, A2DP_CLASS},
70 {USB_SPEAKER, USB_CLASS},
71 {DP_SINK, DP_CLASS},
72 {OFFLOAD_PRIMARY_SPEAKER, OFFLOAD_CLASS},
73 {PRIMARY_DIRECT_VOIP, DIRECT_VOIP_CLASS},
74 {PRIMARY_MMAP_VOIP, MMAP_VOIP_CLASS},
75 };
76
DeInit()77 void AudioIOHandleMap::DeInit()
78 {
79 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
80 IOHandles_.clear();
81 }
82
GetCopy()83 std::unordered_map<std::string, AudioIOHandle> AudioIOHandleMap::GetCopy()
84 {
85 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
86 return IOHandles_;
87 }
88
GetModuleIdByKey(std::string moduleName,AudioIOHandle & moduleId)89 bool AudioIOHandleMap::GetModuleIdByKey(std::string moduleName, AudioIOHandle& moduleId)
90 {
91 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
92 if (IOHandles_.count(moduleName)) {
93 moduleId = IOHandles_[moduleName];
94 return true;
95 }
96 return false;
97 }
98
CheckIOHandleExist(std::string moduleName)99 bool AudioIOHandleMap::CheckIOHandleExist(std::string moduleName)
100 {
101 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
102 return (IOHandles_.find(moduleName) != IOHandles_.end());
103 }
104
DelIOHandleInfo(std::string moduleName)105 void AudioIOHandleMap::DelIOHandleInfo(std::string moduleName)
106 {
107 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
108 IOHandles_.erase(moduleName);
109 }
110
AddIOHandleInfo(std::string moduleName,const AudioIOHandle & moduleId)111 void AudioIOHandleMap::AddIOHandleInfo(std::string moduleName, const AudioIOHandle& moduleId)
112 {
113 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
114 IOHandles_[moduleName] = moduleId;
115 }
116
117 // private methods
GetSinkIOHandle(DeviceType deviceType)118 AudioIOHandle AudioIOHandleMap::GetSinkIOHandle(DeviceType deviceType)
119 {
120 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
121 AudioIOHandle ioHandle;
122 switch (deviceType) {
123 case DeviceType::DEVICE_TYPE_WIRED_HEADSET:
124 case DeviceType::DEVICE_TYPE_WIRED_HEADPHONES:
125 case DeviceType::DEVICE_TYPE_USB_HEADSET:
126 case DeviceType::DEVICE_TYPE_EARPIECE:
127 case DeviceType::DEVICE_TYPE_SPEAKER:
128 case DeviceType::DEVICE_TYPE_BLUETOOTH_SCO:
129 case DeviceType::DEVICE_TYPE_HDMI:
130 ioHandle = IOHandles_[PRIMARY_SPEAKER];
131 break;
132 case DeviceType::DEVICE_TYPE_USB_ARM_HEADSET:
133 ioHandle = IOHandles_[USB_SPEAKER];
134 break;
135 case DeviceType::DEVICE_TYPE_BLUETOOTH_A2DP:
136 ioHandle = IOHandles_[BLUETOOTH_SPEAKER];
137 break;
138 case DeviceType::DEVICE_TYPE_FILE_SINK:
139 ioHandle = IOHandles_[FILE_SINK];
140 break;
141 case DeviceType::DEVICE_TYPE_DP:
142 ioHandle = IOHandles_[DP_SINK];
143 break;
144 default:
145 ioHandle = IOHandles_[PRIMARY_SPEAKER];
146 break;
147 }
148 return ioHandle;
149 }
150
GetSourceIOHandle(DeviceType deviceType)151 AudioIOHandle AudioIOHandleMap::GetSourceIOHandle(DeviceType deviceType)
152 {
153 std::lock_guard<std::mutex> ioHandleLock(ioHandlesMutex_);
154 AudioIOHandle ioHandle;
155 switch (deviceType) {
156 case DeviceType::DEVICE_TYPE_USB_ARM_HEADSET:
157 ioHandle = IOHandles_[USB_MIC];
158 break;
159 case DeviceType::DEVICE_TYPE_MIC:
160 ioHandle = IOHandles_[PRIMARY_MIC];
161 break;
162 case DeviceType::DEVICE_TYPE_FILE_SOURCE:
163 ioHandle = IOHandles_[FILE_SOURCE];
164 break;
165 case DeviceType::DEVICE_TYPE_BLUETOOTH_A2DP_IN:
166 ioHandle = IOHandles_[BLUETOOTH_MIC];
167 break;
168 default:
169 ioHandle = IOHandles_[PRIMARY_MIC];
170 break;
171 }
172 return ioHandle;
173 }
174
OpenPortAndInsertIOHandle(const std::string & moduleName,const AudioModuleInfo & moduleInfo)175 int32_t AudioIOHandleMap::OpenPortAndInsertIOHandle(const std::string &moduleName,
176 const AudioModuleInfo &moduleInfo)
177 {
178 AudioIOHandle ioHandle = AudioPolicyManagerFactory::GetAudioPolicyManager().OpenAudioPort(moduleInfo);
179 CHECK_AND_RETURN_RET_LOG(ioHandle != OPEN_PORT_FAILURE, ERR_INVALID_HANDLE,
180 "OpenAudioPort failed %{public}d", ioHandle);
181
182 AddIOHandleInfo(moduleName, ioHandle);
183 return SUCCESS;
184 }
185
ClosePortAndEraseIOHandle(const std::string & moduleName,bool isSync)186 int32_t AudioIOHandleMap::ClosePortAndEraseIOHandle(const std::string &moduleName, bool isSync)
187 {
188 AudioIOHandle ioHandle;
189 CHECK_AND_RETURN_RET_LOG(GetModuleIdByKey(moduleName, ioHandle), ERROR,
190 "can not find %{public}s in io map", moduleName.c_str());
191 DelIOHandleInfo(moduleName);
192
193 AUDIO_INFO_LOG("[close-module] %{public}s,id:%{public}d", moduleName.c_str(), ioHandle);
194 int32_t result = AudioPolicyManagerFactory::GetAudioPolicyManager().CloseAudioPort(ioHandle, isSync);
195 CHECK_AND_RETURN_RET_LOG(result == SUCCESS, result, "CloseAudioPort failed %{public}d", result);
196 return SUCCESS;
197 }
198
MuteSinkPort(const std::string & portName,int32_t duration,bool isSync)199 void AudioIOHandleMap::MuteSinkPort(const std::string &portName, int32_t duration, bool isSync)
200 {
201 if (sinkPortStrToClassStrMap_.count(portName) > 0) {
202 // Mute by render sink. (primary、a2dp、usb、dp、offload)
203 AudioServerProxy::GetInstance().SetSinkMuteForSwitchDeviceProxy(sinkPortStrToClassStrMap_.at(portName),
204 duration, true);
205 } else {
206 // Mute by pa.
207 AudioPolicyManagerFactory::GetAudioPolicyManager().SetSinkMute(portName, true, isSync);
208 }
209
210 std::shared_ptr<WaitActiveDeviceAction> action = std::make_shared<WaitActiveDeviceAction>(duration, portName);
211 CHECK_AND_RETURN_LOG(action != nullptr, "action is nullptr");
212 AsyncActionDesc desc;
213 desc.action = std::static_pointer_cast<PolicyAsyncAction>(action);
214 DelayedSingleton<AudioPolicyAsyncActionHandler>::GetInstance()->PostAsyncAction(desc);
215
216 usleep(WAIT_SET_MUTE_LATENCY_TIME_US); // sleep fix data cache pop.
217 }
218
MuteDefaultSinkPort(std::string networkID,std::string sinkName)219 void AudioIOHandleMap::MuteDefaultSinkPort(std::string networkID, std::string sinkName)
220 {
221 if (networkID != LOCAL_NETWORK_ID || sinkName != PRIMARY_SPEAKER) {
222 // PA may move the sink to default when unloading module.
223 MuteSinkPort(PRIMARY_SPEAKER, OLD_DEVICE_UNAVALIABLE_MUTE_MS, true);
224 }
225 }
226
SetMoveFinish(bool flag)227 void AudioIOHandleMap::SetMoveFinish(bool flag)
228 {
229 moveDeviceFinished_ = flag;
230 }
231
NotifyUnmutePort()232 void AudioIOHandleMap::NotifyUnmutePort()
233 {
234 std::unique_lock<std::mutex> lock(moveDeviceMutex_);
235 moveDeviceFinished_ = true;
236 moveDeviceCV_.notify_all();
237 }
238
UnmutePortAfterMuteDuration(int32_t muteDuration,const std::string & portName)239 void AudioIOHandleMap::UnmutePortAfterMuteDuration(int32_t muteDuration, const std::string &portName)
240 {
241 Trace trace("UnmutePortAfterMuteDuration:" + portName + " for " + std::to_string(muteDuration) + "us");
242
243 if (!moveDeviceFinished_.load()) {
244 std::unique_lock<std::mutex> lock(moveDeviceMutex_);
245 bool loadWaiting = moveDeviceCV_.wait_for(lock,
246 std::chrono::milliseconds(WAIT_MOVE_DEVICE_MUTE_TIME_MAX_MS),
247 [this] { return moveDeviceFinished_.load(); }
248 );
249 if (!loadWaiting) {
250 AUDIO_ERR_LOG("move device time out");
251 }
252 }
253 AUDIO_INFO_LOG("%{public}d us for device type[%{public}s]", muteDuration, portName.c_str());
254
255 std::shared_ptr<UnmutePortAction> action = std::make_shared<UnmutePortAction>(muteDuration, portName);
256 CHECK_AND_RETURN_LOG(action != nullptr, "action is nullptr");
257 AsyncActionDesc desc;
258 desc.delayTimeMs = muteDuration / US_PER_MS;
259 desc.action = std::static_pointer_cast<PolicyAsyncAction>(action);
260 DelayedSingleton<AudioPolicyAsyncActionHandler>::GetInstance()->PostAsyncAction(desc);
261 }
262
DoUnmutePort(int32_t muteDuration,const std::string & portName)263 void AudioIOHandleMap::DoUnmutePort(int32_t muteDuration, const std::string &portName)
264 {
265 if (sinkPortStrToClassStrMap_.count(portName) > 0) {
266 AudioServerProxy::GetInstance().SetSinkMuteForSwitchDeviceProxy(sinkPortStrToClassStrMap_.at(portName),
267 muteDuration, false);
268 } else {
269 AudioPolicyManagerFactory::GetAudioPolicyManager().SetSinkMute(portName, false);
270 }
271 }
272 }
273 }
274