• 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 
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