1 /*
2 * Copyright (C) 2024-2024 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
16 #include "distributed_source_switch_controller.h"
17 #include "cJSON.h"
18 #ifdef ABILITY_BLUETOOTH_SUPPORT
19 #include "bluetooth_device.h"
20 #endif
21 #include "audio_proxy.h"
22 #include "telephony_errors.h"
23 #include "audio_device_manager.h"
24 #include "telephony_log_wrapper.h"
25 #include "distributed_communication_manager.h"
26
27 namespace OHOS {
28 namespace Telephony {
OnDeviceOnline(const std::string & devId,const std::string & devName,AudioDeviceType devType)29 void DistributedSourceSwitchController::OnDeviceOnline(const std::string &devId, const std::string &devName,
30 AudioDeviceType devType)
31 {
32 auto audioDeviceManager = DelayedSingleton<AudioDeviceManager>::GetInstance();
33 if (audioDeviceManager != nullptr) {
34 std::string address = GetDevAddress(devId, devName);
35 audioDeviceManager->AddAudioDeviceList(address, devType, devName);
36 }
37
38 #ifdef ABILITY_BLUETOOTH_SUPPORT
39 std::lock_guard<ffrt::mutex> lock(mutex_);
40 if (hfpListener_ == nullptr) {
41 hfpListener_ = std::make_shared<DcCallSourceHfpListener>();
42 Bluetooth::HandsFreeAudioGateway::GetProfile()->RegisterObserver(hfpListener_);
43 }
44 #endif
45 }
46
OnDeviceOffline(const std::string & devId,const std::string & devName,AudioDeviceType devType)47 void DistributedSourceSwitchController::OnDeviceOffline(const std::string &devId, const std::string &devName,
48 AudioDeviceType devType)
49 {
50 auto audioDeviceManager = DelayedSingleton<AudioDeviceManager>::GetInstance();
51 if (audioDeviceManager != nullptr) {
52 std::string address = GetDevAddress(devId, devName);
53 audioDeviceManager->RemoveAudioDeviceList(address, devType);
54 audioDeviceManager->InitAudioDevice();
55 }
56
57 #ifdef ABILITY_BLUETOOTH_SUPPORT
58 std::lock_guard<ffrt::mutex> lock(mutex_);
59 if (hfpListener_ != nullptr) {
60 Bluetooth::HandsFreeAudioGateway::GetProfile()->DeregisterObserver(hfpListener_);
61 hfpListener_ = nullptr;
62 }
63 #endif
64 }
65
OnDistributedAudioDeviceChange(const std::string & devId,const std::string & devName,AudioDeviceType devType,int32_t devRole)66 void DistributedSourceSwitchController::OnDistributedAudioDeviceChange(const std::string &devId,
67 const std::string &devName, AudioDeviceType devType, int32_t devRole)
68 {
69 {
70 std::lock_guard<ffrt::mutex> lock(mutex_);
71 isAudioOnSink_ = (devRole == static_cast<int32_t>(DistributedRole::SINK));
72 TELEPHONY_LOGI("OnDistributedAudioDeviceChange isAudioOnSink[%{public}d]", isAudioOnSink_);
73 }
74 auto audioDeviceManager = DelayedSingleton<AudioDeviceManager>::GetInstance();
75 if (audioDeviceManager != nullptr) {
76 if (devRole == static_cast<int32_t>(DistributedRole::SINK)) {
77 if (AudioStandard::AudioSystemManager::GetInstance()->IsDeviceActive(
78 AudioStandard::DeviceType::DEVICE_TYPE_BLUETOOTH_SCO)) { // deactive bt if switch from bt to sink
79 AudioStandard::AudioSystemManager::GetInstance()->SetDeviceActive(
80 AudioStandard::DeviceType::DEVICE_TYPE_BLUETOOTH_SCO, false);
81 }
82 std::string address = GetDevAddress(devId, devName);
83 AudioDevice targetDevice = {
84 .deviceType = devType,
85 };
86 if (memcpy_s(targetDevice.address, kMaxAddressLen, address.c_str(), address.length()) != EOK ||
87 memcpy_s(targetDevice.deviceName, kMaxDeviceNameLen, devName.c_str(), devName.length()) != EOK) {
88 TELEPHONY_LOGE("memcpy_s address or deviceName failed.");
89 return;
90 }
91 audioDeviceManager->SetCurrentAudioDevice(targetDevice);
92 } else {
93 AudioDevice audioDevice;
94 if (DelayedSingleton<AudioProxy>::GetInstance()->GetPreferredOutputAudioDevice(audioDevice) !=
95 TELEPHONY_SUCCESS) {
96 TELEPHONY_LOGE("get preferred output audio device fail");
97 return;
98 }
99 audioDeviceManager->SetCurrentAudioDevice(audioDevice.deviceType);
100 }
101 }
102 }
103
OnRemoveSystemAbility()104 void DistributedSourceSwitchController::OnRemoveSystemAbility()
105 {
106 auto audioDeviceManager = DelayedSingleton<AudioDeviceManager>::GetInstance();
107 if (audioDeviceManager != nullptr) {
108 audioDeviceManager->ResetDistributedCallDevicesList();
109 audioDeviceManager->InitAudioDevice();
110 }
111
112 std::lock_guard<ffrt::mutex> lock(mutex_);
113 isAudioOnSink_ = false;
114 #ifdef ABILITY_BLUETOOTH_SUPPORT
115 if (hfpListener_ != nullptr) {
116 Bluetooth::HandsFreeAudioGateway::GetProfile()->DeregisterObserver(hfpListener_);
117 hfpListener_ = nullptr;
118 }
119 #endif
120 }
121
SwitchDevice(const std::string & devId,int32_t direction)122 bool DistributedSourceSwitchController::SwitchDevice(const std::string &devId, int32_t direction)
123 {
124 auto distributedMgr = DelayedSingleton<DistributedCommunicationManager>::GetInstance();
125 if (distributedMgr == nullptr) {
126 return false;
127 }
128 auto ret = distributedMgr->SwitchDevWrapper(devId, direction);
129 TELEPHONY_LOGI("switch distributed device result[%{public}d]", ret);
130 return ret == TELEPHONY_SUCCESS;
131 }
132
GetDevAddress(const std::string & devId,const std::string & devName)133 std::string DistributedSourceSwitchController::GetDevAddress(const std::string &devId, const std::string &devName)
134 {
135 std::string address = "";
136 cJSON *root = cJSON_CreateObject();
137 if (root == nullptr) {
138 TELEPHONY_LOGE("create json msg fail");
139 return address;
140 }
141 do {
142 if (cJSON_AddStringToObject(root, "devId", devId.c_str()) == nullptr) {
143 TELEPHONY_LOGE("add dev id fail");
144 break;
145 }
146 if (cJSON_AddStringToObject(root, "devName", devName.c_str()) == nullptr) {
147 TELEPHONY_LOGE("add dev name fail");
148 break;
149 }
150 char *jsonData = cJSON_PrintUnformatted(root);
151 if (jsonData != nullptr) {
152 address = jsonData;
153 free(jsonData);
154 jsonData = nullptr;
155 }
156 } while (false);
157 cJSON_Delete(root);
158 return address;
159 }
160
161 #ifdef ABILITY_BLUETOOTH_SUPPORT
OnHfpStackChanged(const Bluetooth::BluetoothRemoteDevice & device,int32_t action)162 void DcCallSourceHfpListener::OnHfpStackChanged(const Bluetooth::BluetoothRemoteDevice &device, int32_t action)
163 {
164 TELEPHONY_LOGI("source hfp stack changed, action[%{public}d]", action);
165 if (IsNeedSwitchToSource(device, action)) {
166 (void)DelayedSingleton<DistributedCommunicationManager>::GetInstance()->SwitchToSourceDevice();
167 }
168 }
169
IsNeedSwitchToSource(const Bluetooth::BluetoothRemoteDevice & device,int32_t action)170 bool DcCallSourceHfpListener::IsNeedSwitchToSource(const Bluetooth::BluetoothRemoteDevice &device, int32_t action)
171 {
172 if (!DelayedSingleton<DistributedCommunicationManager>::GetInstance()->IsAudioOnSink()) {
173 return false;
174 }
175 int32_t cod = DEFAULT_HFP_FLAG_VALUE;
176 int32_t majorClass = DEFAULT_HFP_FLAG_VALUE;
177 int32_t majorMinorClass = DEFAULT_HFP_FLAG_VALUE;
178 device.GetDeviceProductType(cod, majorClass, majorMinorClass);
179 TELEPHONY_LOGI("device major %{public}d, minor %{public}d", majorClass, majorMinorClass);
180 if (action == WEAR_ACTION && majorClass == Bluetooth::BluetoothDevice::MAJOR_AUDIO_VIDEO &&
181 (majorMinorClass == Bluetooth::BluetoothDevice::AUDIO_VIDEO_HEADPHONES ||
182 majorMinorClass == Bluetooth::BluetoothDevice::AUDIO_VIDEO_WEARABLE_HEADSET)) {
183 return true;
184 }
185 if (action == USER_SELECTION_ACTION && majorClass == Bluetooth::BluetoothDevice::MAJOR_WEARABLE &&
186 majorMinorClass == Bluetooth::BluetoothDevice::WEARABLE_WRIST_WATCH) {
187 return true;
188 }
189 return false;
190 }
191 #endif
192
193 } // namespace Telephony
194 } // namespace OHOS
195