1
2 /*
3 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef LOG_TAG
17 #define LOG_TAG "AudioActiveDevice"
18 #endif
19
20 #include "audio_active_device.h"
21 #include <ability_manager_client.h>
22 #include "iservice_registry.h"
23 #include "parameter.h"
24 #include "parameters.h"
25 #include "audio_policy_log.h"
26 #include "audio_manager_listener_stub.h"
27 #include "audio_inner_call.h"
28 #include "media_monitor_manager.h"
29
30 #ifdef BLUETOOTH_ENABLE
31 #include "audio_server_death_recipient.h"
32 #include "audio_bluetooth_manager.h"
33 #include "bluetooth_device_manager.h"
34 #endif
35
36 #include "audio_policy_utils.h"
37 #include "audio_server_proxy.h"
38
39 namespace OHOS {
40 namespace AudioStandard {
41
42 #ifdef BLUETOOTH_ENABLE
43 const uint32_t USER_NOT_SELECT_BT = 1;
44 const uint32_t USER_SELECT_BT = 2;
45 #endif
46
GetActiveA2dpDeviceStreamInfo(DeviceType deviceType,AudioStreamInfo & streamInfo)47 bool AudioActiveDevice::GetActiveA2dpDeviceStreamInfo(DeviceType deviceType, AudioStreamInfo &streamInfo)
48 {
49 if (deviceType == DEVICE_TYPE_BLUETOOTH_A2DP) {
50 A2dpDeviceConfigInfo info;
51 if (audioA2dpDevice_.GetA2dpDeviceInfo(activeBTDevice_, info)) {
52 streamInfo.samplingRate = *info.streamInfo.samplingRate.rbegin();
53 streamInfo.format = info.streamInfo.format;
54 streamInfo.channels = *info.streamInfo.channels.rbegin();
55 return true;
56 }
57 } else if (deviceType == DEVICE_TYPE_BLUETOOTH_A2DP_IN) {
58 A2dpDeviceConfigInfo info;
59 if (audioA2dpDevice_.GetA2dpInDeviceInfo(activeBTInDevice_, info)) {
60 streamInfo.samplingRate = *info.streamInfo.samplingRate.rbegin();
61 streamInfo.format = info.streamInfo.format;
62 streamInfo.channels = *info.streamInfo.channels.rbegin();
63 return true;
64 }
65 }
66 return false;
67 }
68
GetActiveBtDeviceMac()69 std::string AudioActiveDevice::GetActiveBtDeviceMac()
70 {
71 return activeBTDevice_;
72 }
73
SetActiveBtDeviceMac(const std::string macAddress)74 void AudioActiveDevice::SetActiveBtDeviceMac(const std::string macAddress)
75 {
76 activeBTDevice_ = macAddress;
77 }
78
SetActiveBtInDeviceMac(const std::string macAddress)79 void AudioActiveDevice::SetActiveBtInDeviceMac(const std::string macAddress)
80 {
81 activeBTInDevice_ = macAddress;
82 }
83
IsDirectSupportedDevice()84 bool AudioActiveDevice::IsDirectSupportedDevice()
85 {
86 DeviceType dev = GetCurrentOutputDeviceType();
87 return dev == DEVICE_TYPE_WIRED_HEADSET || dev == DEVICE_TYPE_USB_HEADSET;
88 }
89
CheckActiveOutputDeviceSupportOffload()90 bool AudioActiveDevice::CheckActiveOutputDeviceSupportOffload()
91 {
92 DeviceType dev = GetCurrentOutputDeviceType();
93 if (GetCurrentOutputDeviceNetworkId() != LOCAL_NETWORK_ID || dev == DEVICE_TYPE_REMOTE_CAST) {
94 return false;
95 }
96
97 return dev == DEVICE_TYPE_SPEAKER ||
98 (dev == DEVICE_TYPE_BLUETOOTH_A2DP && audioA2dpOffloadFlag_.GetA2dpOffloadFlag() == A2DP_OFFLOAD) ||
99 dev == DEVICE_TYPE_USB_HEADSET;
100 }
101
SetCurrentInputDevice(const AudioDeviceDescriptor & desc)102 void AudioActiveDevice::SetCurrentInputDevice(const AudioDeviceDescriptor &desc)
103 {
104 std::lock_guard<std::mutex> lock(curInputDevice_);
105 currentActiveInputDevice_ = AudioDeviceDescriptor(desc);
106 }
107
GetCurrentInputDevice()108 const AudioDeviceDescriptor& AudioActiveDevice::GetCurrentInputDevice()
109 {
110 std::lock_guard<std::mutex> lock(curInputDevice_);
111 return currentActiveInputDevice_;
112 }
113
114
GetCurrentInputDeviceType()115 DeviceType AudioActiveDevice::GetCurrentInputDeviceType()
116 {
117 std::lock_guard<std::mutex> lock(curInputDevice_);
118 return currentActiveInputDevice_.deviceType_;
119 }
120
SetCurrentInputDeviceType(DeviceType deviceType)121 void AudioActiveDevice::SetCurrentInputDeviceType(DeviceType deviceType)
122 {
123 std::lock_guard<std::mutex> lock(curInputDevice_);
124 currentActiveInputDevice_.deviceType_ = deviceType;
125 }
126
GetCurrentInputDeviceMacAddr()127 std::string AudioActiveDevice::GetCurrentInputDeviceMacAddr()
128 {
129 std::lock_guard<std::mutex> lock(curInputDevice_);
130 return currentActiveDevice_.macAddress_;
131 }
132
SetCurrentOutputDevice(const AudioDeviceDescriptor & desc)133 void AudioActiveDevice::SetCurrentOutputDevice(const AudioDeviceDescriptor &desc)
134 {
135 std::lock_guard<std::mutex> lock(curOutputDevice_);
136 currentActiveDevice_ = AudioDeviceDescriptor(desc);
137 }
138
SetCurrentOutputDeviceType(DeviceType deviceType)139 void AudioActiveDevice::SetCurrentOutputDeviceType(DeviceType deviceType)
140 {
141 std::lock_guard<std::mutex> lock(curOutputDevice_);
142 currentActiveDevice_.deviceType_ = deviceType;
143 }
144
GetCurrentOutputDevice()145 const AudioDeviceDescriptor& AudioActiveDevice::GetCurrentOutputDevice()
146 {
147 std::lock_guard<std::mutex> lock(curOutputDevice_);
148 return currentActiveDevice_;
149 }
150
GetCurrentOutputDeviceType()151 DeviceType AudioActiveDevice::GetCurrentOutputDeviceType()
152 {
153 std::lock_guard<std::mutex> lock(curOutputDevice_);
154 return currentActiveDevice_.deviceType_;
155 }
156
GetCurrentOutputDeviceCategory()157 DeviceCategory AudioActiveDevice::GetCurrentOutputDeviceCategory()
158 {
159 std::lock_guard<std::mutex> lock(curOutputDevice_);
160 return currentActiveDevice_.deviceCategory_;
161 }
162
GetCurrentOutputDeviceNetworkId()163 std::string AudioActiveDevice::GetCurrentOutputDeviceNetworkId()
164 {
165 std::lock_guard<std::mutex> lock(curOutputDevice_);
166 return currentActiveDevice_.networkId_;
167 }
168
GetCurrentOutputDeviceMacAddr()169 std::string AudioActiveDevice::GetCurrentOutputDeviceMacAddr()
170 {
171 std::lock_guard<std::mutex> lock(curOutputDevice_);
172 return currentActiveDevice_.macAddress_;
173 }
174
GetMaxAmplitude(const int32_t deviceId,AudioInterrupt audioInterrupt)175 float AudioActiveDevice::GetMaxAmplitude(const int32_t deviceId, AudioInterrupt audioInterrupt)
176 {
177 AudioDeviceDescriptor descriptor = GetCurrentOutputDevice();
178 if (deviceId == descriptor.deviceId_) {
179 uint32_t sessionId = audioInterrupt.streamId;
180 std::string sinkName = AudioPolicyUtils::GetInstance().GetSinkName(descriptor, static_cast<int32_t>(sessionId));
181 std::string deviceClass = AudioPolicyUtils::GetInstance().GetOutputDeviceClassBySinkPortName(sinkName);
182 return AudioServerProxy::GetInstance().GetMaxAmplitudeProxy(true, deviceClass);
183 }
184
185 descriptor = GetCurrentInputDevice();
186 if (deviceId == descriptor.deviceId_) {
187 std::string sourceName = AudioPolicyUtils::GetInstance().GetSourcePortName(GetCurrentInputDeviceType());
188 std::string deviceClass = AudioPolicyUtils::GetInstance().GetInputDeviceClassBySourcePortName(sourceName);
189 return AudioServerProxy::GetInstance().GetMaxAmplitudeProxy(false, deviceClass,
190 audioInterrupt.audioFocusType.sourceType);
191 }
192
193 return 0;
194 }
195
NotifyUserSelectionEventToBt(std::shared_ptr<AudioDeviceDescriptor> audioDeviceDescriptor)196 void AudioActiveDevice::NotifyUserSelectionEventToBt(std::shared_ptr<AudioDeviceDescriptor> audioDeviceDescriptor)
197 {
198 Trace trace("AudioActiveDevice::NotifyUserSelectionEventToBt");
199 if (audioDeviceDescriptor == nullptr) {
200 return;
201 }
202 #ifdef BLUETOOTH_ENABLE
203 DeviceType curOutputDeviceType = GetCurrentOutputDeviceType();
204 if (curOutputDeviceType == DEVICE_TYPE_BLUETOOTH_SCO ||
205 curOutputDeviceType == DEVICE_TYPE_BLUETOOTH_A2DP) {
206 Bluetooth::SendUserSelectionEvent(curOutputDeviceType,
207 GetCurrentOutputDeviceMacAddr(), USER_NOT_SELECT_BT);
208 if (curOutputDeviceType == DEVICE_TYPE_BLUETOOTH_SCO) {
209 Bluetooth::AudioHfpManager::DisconnectSco();
210 }
211 }
212 if (audioDeviceDescriptor->deviceType_ == DEVICE_TYPE_BLUETOOTH_SCO ||
213 audioDeviceDescriptor->deviceType_ == DEVICE_TYPE_BLUETOOTH_A2DP) {
214 Bluetooth::SendUserSelectionEvent(audioDeviceDescriptor->deviceType_,
215 audioDeviceDescriptor->macAddress_, USER_SELECT_BT);
216 }
217 #endif
218 }
219
DisconnectScoWhenUserSelectInput(std::shared_ptr<AudioDeviceDescriptor> audioDeviceDescriptor)220 void AudioActiveDevice::DisconnectScoWhenUserSelectInput(std::shared_ptr<AudioDeviceDescriptor> audioDeviceDescriptor)
221 {
222 if (audioDeviceDescriptor == nullptr) {
223 AUDIO_ERR_LOG("nullptr audioDeviceDescriptor");
224 return;
225 }
226 #ifdef BLUETOOTH_ENABLE
227 DeviceType curInputDeviceType = GetCurrentInputDeviceType();
228 if (curInputDeviceType == DEVICE_TYPE_BLUETOOTH_SCO) {
229 AUDIO_INFO_LOG("user select ready to disconnect");
230 Bluetooth::AudioHfpManager::DisconnectSco();
231 }
232 #endif
233 }
234
WriteOutputRouteChangeEvent(std::shared_ptr<AudioDeviceDescriptor> & desc,const AudioStreamDeviceChangeReason reason)235 void AudioActiveDevice::WriteOutputRouteChangeEvent(std::shared_ptr<AudioDeviceDescriptor> &desc,
236 const AudioStreamDeviceChangeReason reason)
237 {
238 int64_t timeStamp = AudioPolicyUtils::GetInstance().GetCurrentTimeMS();
239 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
240 Media::MediaMonitor::AUDIO, Media::MediaMonitor::AUDIO_ROUTE_CHANGE,
241 Media::MediaMonitor::BEHAVIOR_EVENT);
242 DeviceType curOutputDeviceType = GetCurrentOutputDeviceType();
243 bean->Add("REASON", static_cast<int32_t>(reason));
244 bean->Add("TIMESTAMP", static_cast<uint64_t>(timeStamp));
245 bean->Add("DEVICE_TYPE_BEFORE_CHANGE", curOutputDeviceType);
246 bean->Add("DEVICE_TYPE_AFTER_CHANGE", desc->deviceType_);
247 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
248 }
249
UpdateDevice(std::shared_ptr<AudioDeviceDescriptor> & desc,const AudioStreamDeviceChangeReasonExt reason,const std::shared_ptr<AudioRendererChangeInfo> & rendererChangeInfo)250 bool AudioActiveDevice::UpdateDevice(std::shared_ptr<AudioDeviceDescriptor> &desc,
251 const AudioStreamDeviceChangeReasonExt reason, const std::shared_ptr<AudioRendererChangeInfo> &rendererChangeInfo)
252 {
253 std::shared_ptr<AudioDeviceDescriptor> preferredDesc =
254 audioAffinityManager_.GetRendererDevice(rendererChangeInfo->clientUID);
255 AudioDeviceDescriptor tmpOutputDeviceDesc = GetCurrentOutputDevice();
256 if (((preferredDesc->deviceType_ != DEVICE_TYPE_NONE) && !desc->IsSameDeviceInfo(tmpOutputDeviceDesc)
257 && desc->deviceType_ != preferredDesc->deviceType_)
258 || ((preferredDesc->deviceType_ == DEVICE_TYPE_NONE) && !desc->IsSameDeviceInfo(tmpOutputDeviceDesc))) {
259 WriteOutputRouteChangeEvent(desc, reason);
260 SetCurrentOutputDevice(*desc);
261 AUDIO_DEBUG_LOG("currentActiveDevice update %{public}d", GetCurrentOutputDeviceType());
262 return true;
263 }
264 return false;
265 }
266
HandleActiveBt(DeviceType deviceType,std::string macAddress)267 void AudioActiveDevice::HandleActiveBt(DeviceType deviceType, std::string macAddress)
268 {
269 if (GetCurrentOutputDeviceType() == DEVICE_TYPE_BLUETOOTH_SCO &&
270 deviceType != DEVICE_TYPE_BLUETOOTH_SCO) {
271 Bluetooth::SendUserSelectionEvent(DEVICE_TYPE_BLUETOOTH_SCO,
272 GetCurrentOutputDeviceMacAddr(), USER_NOT_SELECT_BT);
273 Bluetooth::AudioHfpManager::DisconnectSco();
274 }
275 if (GetCurrentOutputDeviceType() != DEVICE_TYPE_BLUETOOTH_SCO &&
276 deviceType == DEVICE_TYPE_BLUETOOTH_SCO) {
277 Bluetooth::SendUserSelectionEvent(DEVICE_TYPE_BLUETOOTH_SCO,
278 macAddress, USER_SELECT_BT);
279 }
280 }
281
HandleNegtiveBt(DeviceType deviceType)282 void AudioActiveDevice::HandleNegtiveBt(DeviceType deviceType)
283 {
284 if (GetCurrentOutputDeviceType() == DEVICE_TYPE_BLUETOOTH_SCO &&
285 deviceType == DEVICE_TYPE_BLUETOOTH_SCO) {
286 Bluetooth::SendUserSelectionEvent(DEVICE_TYPE_BLUETOOTH_SCO,
287 GetCurrentOutputDeviceMacAddr(), USER_NOT_SELECT_BT);
288 Bluetooth::AudioHfpManager::DisconnectSco();
289 }
290 }
291
IsDeviceActive(DeviceType deviceType)292 bool AudioActiveDevice::IsDeviceActive(DeviceType deviceType)
293 {
294 AUDIO_DEBUG_LOG("type [%{public}d]", deviceType);
295 CHECK_AND_RETURN_RET(GetCurrentOutputDeviceNetworkId() == LOCAL_NETWORK_ID, false);
296 return GetCurrentOutputDeviceType() == deviceType;
297 }
298
UpdateInputDeviceInfo(DeviceType deviceType)299 void AudioActiveDevice::UpdateInputDeviceInfo(DeviceType deviceType)
300 {
301 DeviceType curType = GetCurrentInputDeviceType();
302 switch (deviceType) {
303 case DEVICE_TYPE_EARPIECE:
304 case DEVICE_TYPE_SPEAKER:
305 case DEVICE_TYPE_BLUETOOTH_A2DP:
306 curType = DEVICE_TYPE_MIC;
307 break;
308 case DEVICE_TYPE_FILE_SINK:
309 curType = DEVICE_TYPE_FILE_SOURCE;
310 break;
311 case DEVICE_TYPE_USB_ARM_HEADSET:
312 curType = DEVICE_TYPE_USB_HEADSET;
313 break;
314 case DEVICE_TYPE_WIRED_HEADSET:
315 case DEVICE_TYPE_USB_HEADSET:
316 case DEVICE_TYPE_BLUETOOTH_SCO:
317 curType = deviceType;
318 break;
319 default:
320 break;
321 }
322
323 SetCurrentInputDeviceType(curType);
324
325 AUDIO_INFO_LOG("Input device updated to %{public}d", curType);
326 }
327
SetDeviceActive(DeviceType deviceType,bool active,const int32_t uid)328 int32_t AudioActiveDevice::SetDeviceActive(DeviceType deviceType, bool active, const int32_t uid)
329 {
330 CHECK_AND_RETURN_RET_LOG(deviceType != DEVICE_TYPE_NONE, ERR_DEVICE_NOT_SUPPORTED, "Invalid device");
331
332 // Activate new device if its already connected
333 auto isPresent = [&deviceType] (const std::shared_ptr<AudioDeviceDescriptor> &desc) {
334 CHECK_AND_RETURN_RET_LOG(desc != nullptr, false, "SetDeviceActive::Invalid device descriptor");
335 return ((deviceType == desc->deviceType_) || (deviceType == DEVICE_TYPE_FILE_SINK));
336 };
337
338 std::vector<std::shared_ptr<AudioDeviceDescriptor>> callDevices
339 = AudioPolicyUtils::GetInstance().GetAvailableDevicesInner(CALL_OUTPUT_DEVICES);
340 std::vector<std::shared_ptr<AudioDeviceDescriptor>> deviceList = {};
341 for (const auto &desc : callDevices) {
342 std::shared_ptr<AudioDeviceDescriptor> devDesc = std::make_shared<AudioDeviceDescriptor>(*desc);
343 deviceList.push_back(devDesc);
344 }
345
346 auto itr = std::find_if(deviceList.begin(), deviceList.end(), isPresent);
347 CHECK_AND_RETURN_RET_LOG(itr != deviceList.end(), ERR_OPERATION_FAILED,
348 "Requested device not available %{public}d ", deviceType);
349 if (!active) {
350 AudioPolicyUtils::GetInstance().SetPreferredDevice(AUDIO_CALL_RENDER,
351 std::make_shared<AudioDeviceDescriptor>(), uid, "SetDeviceActive");
352 #ifdef BLUETOOTH_ENABLE
353 HandleNegtiveBt(deviceType);
354 #endif
355 } else {
356 AudioPolicyUtils::GetInstance().SetPreferredDevice(AUDIO_CALL_RENDER, *itr, uid, "SetDeviceActive");
357 #ifdef BLUETOOTH_ENABLE
358 HandleActiveBt(deviceType, (*itr)->macAddress_);
359 #endif
360 }
361 return SUCCESS;
362 }
363
SetCallDeviceActive(DeviceType deviceType,bool active,std::string address,const int32_t uid)364 int32_t AudioActiveDevice::SetCallDeviceActive(DeviceType deviceType, bool active, std::string address,
365 const int32_t uid)
366 {
367 // Activate new device if its already connected
368 auto isPresent = [&deviceType, &address] (const std::shared_ptr<AudioDeviceDescriptor> &desc) {
369 CHECK_AND_RETURN_RET_LOG(desc != nullptr, false, "Invalid device descriptor");
370 return ((deviceType == desc->deviceType_) && (address == desc->macAddress_));
371 };
372 std::vector<std::shared_ptr<AudioDeviceDescriptor>> callDevices
373 = AudioPolicyUtils::GetInstance().GetAvailableDevicesInner(CALL_OUTPUT_DEVICES);
374
375 auto itr = std::find_if(callDevices.begin(), callDevices.end(), isPresent);
376 CHECK_AND_RETURN_RET_LOG(itr != callDevices.end(), ERR_OPERATION_FAILED,
377 "Requested device not available %{public}d ", deviceType);
378 if (active) {
379 if (deviceType == DEVICE_TYPE_BLUETOOTH_SCO) {
380 (*itr)->isEnable_ = true;
381 audioDeviceManager_.UpdateDevicesListInfo(std::make_shared<AudioDeviceDescriptor>(**itr), ENABLE_UPDATE);
382 AudioPolicyUtils::GetInstance().ClearScoDeviceSuspendState(address);
383 }
384 AudioPolicyUtils::GetInstance().SetPreferredDevice(AUDIO_CALL_RENDER,
385 std::make_shared<AudioDeviceDescriptor>(**itr), uid, "SetCallDeviceActive");
386 #ifdef BLUETOOTH_ENABLE
387 HandleActiveBt(deviceType, (*itr)->macAddress_);
388 #endif
389 } else {
390 AudioPolicyUtils::GetInstance().SetPreferredDevice(AUDIO_CALL_RENDER,
391 std::make_shared<AudioDeviceDescriptor>(), uid, "SetCallDeviceActive");
392 #ifdef BLUETOOTH_ENABLE
393 HandleNegtiveBt(deviceType);
394 #endif
395 }
396 return SUCCESS;
397 }
398
UpdateActiveDeviceRoute(DeviceType deviceType,DeviceFlag deviceFlag,const std::string & deviceName)399 void AudioActiveDevice::UpdateActiveDeviceRoute(DeviceType deviceType, DeviceFlag deviceFlag,
400 const std::string &deviceName)
401 {
402 Trace trace("AudioActiveDevice::UpdateActiveDeviceRoute DeviceType:" + std::to_string(deviceType));
403 AUDIO_INFO_LOG("Active route with type[%{public}d] name[%{public}s]", deviceType, deviceName.c_str());
404 std::vector<std::pair<DeviceType, DeviceFlag>> activeDevices;
405 activeDevices.push_back(make_pair(deviceType, deviceFlag));
406 UpdateActiveDevicesRoute(activeDevices, deviceName);
407 }
408
UpdateActiveDevicesRoute(std::vector<std::pair<DeviceType,DeviceFlag>> & activeDevices,const std::string & deviceName)409 void AudioActiveDevice::UpdateActiveDevicesRoute(std::vector<std::pair<DeviceType, DeviceFlag>>
410 &activeDevices, const std::string &deviceName)
411 {
412 CHECK_AND_RETURN_LOG(!activeDevices.empty(), "activeDevices is empty.");
413 auto ret = SUCCESS;
414 std::string deviceTypesInfo = "";
415 for (size_t i = 0; i < activeDevices.size(); i++) {
416 deviceTypesInfo = deviceTypesInfo + " " + std::to_string(activeDevices[i].first);
417 AUDIO_INFO_LOG("update active devices, device type info:[%{public}s]",
418 std::to_string(activeDevices[i].first).c_str());
419 }
420
421 Trace trace("AudioActiveDevice::UpdateActiveDevicesRoute DeviceTypes:" + deviceTypesInfo);
422 ret = AudioServerProxy::GetInstance().UpdateActiveDevicesRouteProxy(activeDevices,
423 audioA2dpOffloadFlag_.GetA2dpOffloadFlag(), deviceName);
424 CHECK_AND_RETURN_LOG(ret == SUCCESS, "Failed to update the route for %{public}s", deviceTypesInfo.c_str());
425 }
426
427 }
428 }
429