1 /*
2 * Copyright (C) 2021 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 "bluetooth_connection.h"
17
18 #include "audio_control_manager.h"
19 #include "bluetooth_call_manager.h"
20 #include "telephony_log_wrapper.h"
21 #ifdef ABILITY_BLUETOOTH_SUPPORT
22 #include "bluetooth_host.h"
23
24 constexpr int32_t PHONE_NUMBER_TYPE = 0x81;
25 #endif
26
27 namespace OHOS {
28 namespace Telephony {
BluetoothConnection()29 BluetoothConnection::BluetoothConnection() : connectedScoAddr_("") {}
30
~BluetoothConnection()31 BluetoothConnection::~BluetoothConnection()
32 {
33 #ifdef ABILITY_BLUETOOTH_SUPPORT
34 mapConnectedBtDevices_.clear();
35 Bluetooth::HandsFreeAudioGateway *profile = Bluetooth::HandsFreeAudioGateway::GetProfile();
36 if (profile == nullptr) {
37 TELEPHONY_LOGE("profile is nullptr");
38 } else {
39 profile->DeregisterObserver(this);
40 }
41 #endif
42 }
43
Init()44 void BluetoothConnection::Init()
45 {
46 #ifdef ABILITY_BLUETOOTH_SUPPORT
47 Bluetooth::HandsFreeAudioGateway *profile = Bluetooth::HandsFreeAudioGateway::GetProfile();
48 if (profile == nullptr) {
49 TELEPHONY_LOGE("BluetoothConnection init fail!");
50 return;
51 }
52
53 profile->RegisterObserver(this);
54 TELEPHONY_LOGI("BluetoothConnection init success!");
55 #endif
56 }
57
ConnectBtSco()58 bool BluetoothConnection::ConnectBtSco()
59 {
60 if (btScoState_ == BtScoState::SCO_STATE_CONNECTED) {
61 TELEPHONY_LOGI("BluetoothConnection::ConnectBtSco bluetooth sco is already connected");
62 return true;
63 }
64 #ifdef ABILITY_BLUETOOTH_SUPPORT
65 Bluetooth::HandsFreeAudioGateway *profile = Bluetooth::HandsFreeAudioGateway::GetProfile();
66 if (profile == nullptr) {
67 TELEPHONY_LOGE("profile is nullptr");
68 return false;
69 }
70
71 Bluetooth::BluetoothRemoteDevice *device = nullptr;
72 if (!connectedScoAddr_.empty()) {
73 TELEPHONY_LOGI("connectedScoAddr_ is not empty");
74 device = GetBtDevice(connectedScoAddr_);
75 } else if (!mapConnectedBtDevices_.empty()) {
76 TELEPHONY_LOGI("mapConnectedBtDevices_ is not empty");
77 device = &mapConnectedBtDevices_.begin()->second;
78 } else {
79 TELEPHONY_LOGE("device is invalid");
80 }
81
82 if (device == nullptr) {
83 TELEPHONY_LOGE("device is nullptr");
84 return false;
85 }
86 if (profile->SetActiveDevice(*device) && profile->ConnectSco()) {
87 btScoState_ = BtScoState::SCO_STATE_CONNECTED;
88 connectedScoAddr_ = device->GetDeviceAddr();
89 DelayedSingleton<AudioDeviceManager>::GetInstance()->ProcessEvent(AudioEvent::BLUETOOTH_SCO_CONNECTED);
90 TELEPHONY_LOGI("bluetooth sco connected successfully.");
91 return true;
92 }
93 #endif
94 TELEPHONY_LOGE("Connect Bluetooth Sco Fail !");
95 return false;
96 }
97
DisconnectBtSco()98 bool BluetoothConnection::DisconnectBtSco()
99 {
100 if (btScoState_ == BtScoState::SCO_STATE_DISCONNECTED) {
101 TELEPHONY_LOGI("bluetooth sco is already disconnected");
102 return true;
103 }
104 #ifdef ABILITY_BLUETOOTH_SUPPORT
105 Bluetooth::HandsFreeAudioGateway *profile = Bluetooth::HandsFreeAudioGateway::GetProfile();
106 if (profile == nullptr) {
107 TELEPHONY_LOGE("profile is nullptr");
108 return false;
109 }
110 return profile->DisconnectSco();
111 #endif
112 TELEPHONY_LOGE("Disconnect Bluetooth Sco Fail !");
113 return false;
114 }
115
116 #ifdef ABILITY_BLUETOOTH_SUPPORT
ConnectBtSco(const std::string & bluetoothAddress)117 bool BluetoothConnection::ConnectBtSco(const std::string &bluetoothAddress)
118 {
119 if (bluetoothAddress == connectedScoAddr_ && btScoState_ == BtScoState::SCO_STATE_CONNECTED) {
120 TELEPHONY_LOGI("bluetooth sco is already connected");
121 return true;
122 }
123
124 Bluetooth::BluetoothRemoteDevice device =
125 Bluetooth::BluetoothHost::GetDefaultHost().GetRemoteDevice(bluetoothAddress, Bluetooth::BT_TRANSPORT_BREDR);
126 AddBtDevice(bluetoothAddress, device);
127
128 return ConnectBtSco(device);
129 }
130
ConnectBtSco(const Bluetooth::BluetoothRemoteDevice & device)131 bool BluetoothConnection::ConnectBtSco(const Bluetooth::BluetoothRemoteDevice &device)
132 {
133 Bluetooth::HandsFreeAudioGateway *profile = Bluetooth::HandsFreeAudioGateway::GetProfile();
134 if (profile == nullptr) {
135 TELEPHONY_LOGE("profile is nullptr");
136 return false;
137 }
138
139 if (profile->SetActiveDevice(device) && profile->ConnectSco()) {
140 connectedScoAddr_ = device.GetDeviceAddr();
141 btScoState_ = BtScoState::SCO_STATE_CONNECTED;
142 TELEPHONY_LOGI("connect bluetooth sco success");
143 return true;
144 }
145 TELEPHONY_LOGE("connect bluetooth sco fail");
146 return false;
147 }
148
DisconnectBtSco(const Bluetooth::BluetoothRemoteDevice & device)149 bool BluetoothConnection::DisconnectBtSco(const Bluetooth::BluetoothRemoteDevice &device)
150 {
151 Bluetooth::HandsFreeAudioGateway *profile = Bluetooth::HandsFreeAudioGateway::GetProfile();
152 if (profile == nullptr) {
153 TELEPHONY_LOGE("profile is nullptr");
154 return false;
155 }
156
157 if (profile->Disconnect(device)) {
158 connectedScoAddr_ = "";
159 btScoState_ = BtScoState::SCO_STATE_DISCONNECTED;
160 TELEPHONY_LOGI("disconnect bluetooth sco success");
161 return true;
162 }
163
164 TELEPHONY_LOGE("Disconnect Bluetooth Sco Fail !");
165 return false;
166 }
167
IsBtAvailble()168 bool BluetoothConnection::IsBtAvailble()
169 {
170 if (mapConnectedBtDevices_.empty()) {
171 TELEPHONY_LOGE("mapConnectedBtDevices_ is empty");
172 return false;
173 }
174
175 return true;
176 }
177 #endif
178
IsBtScoConnected()179 bool BluetoothConnection::IsBtScoConnected()
180 {
181 return btScoState_ == BtScoState::SCO_STATE_CONNECTED;
182 }
183
SetBtScoState(BtScoState state)184 void BluetoothConnection::SetBtScoState(BtScoState state)
185 {
186 btScoState_ = state;
187 }
188
SendBtCallState(int32_t numActive,int32_t numHeld,int32_t callState,const std::string & number)189 int32_t BluetoothConnection::SendBtCallState(
190 int32_t numActive, int32_t numHeld, int32_t callState, const std::string &number)
191 {
192 #ifdef ABILITY_BLUETOOTH_SUPPORT
193 Bluetooth::HandsFreeAudioGateway *profile = Bluetooth::HandsFreeAudioGateway::GetProfile();
194 if (profile == nullptr) {
195 TELEPHONY_LOGE("profile is nullptr");
196 return TELEPHONY_ERROR;
197 }
198
199 std::string nickName = "";
200 profile->PhoneStateChanged(numActive, numHeld, callState, number, PHONE_NUMBER_TYPE, nickName);
201 #endif
202 TELEPHONY_LOGI("PhoneStateChanged,numActive:%{public}d,numHeld:%{public}d,callState:%{public}d", numActive, numHeld,
203 callState);
204 return TELEPHONY_SUCCESS;
205 }
206
GetBtScoState()207 BtScoState BluetoothConnection::GetBtScoState()
208 {
209 TELEPHONY_LOGI("current bluetooth sco state : %{public}d", btScoState_);
210 return btScoState_;
211 }
212
IsAudioActivated()213 bool BluetoothConnection::IsAudioActivated()
214 {
215 return DelayedSingleton<AudioControlManager>::GetInstance()->IsAudioActivated();
216 }
217
218 #ifdef ABILITY_BLUETOOTH_SUPPORT
OnScoStateChanged(const Bluetooth::BluetoothRemoteDevice & device,int32_t state)219 void BluetoothConnection::OnScoStateChanged(const Bluetooth::BluetoothRemoteDevice &device, int32_t state)
220 {
221 TELEPHONY_LOGI("BluetoothConnection::OnScoStateChanged state : %{public}d", state);
222 switch (state) {
223 case (int32_t)Bluetooth::HfpScoConnectState::SCO_CONNECTED:
224 connectedScoAddr_ = device.GetDeviceAddr();
225 btScoState_ = BtScoState::SCO_STATE_CONNECTED;
226 DelayedSingleton<AudioDeviceManager>::GetInstance()->ProcessEvent(AudioEvent::BLUETOOTH_SCO_CONNECTED);
227 break;
228 case (int32_t)Bluetooth::HfpScoConnectState::SCO_DISCONNECTED:
229 if (device.GetDeviceAddr() == connectedScoAddr_) {
230 connectedScoAddr_ = "";
231 btScoState_ = BtScoState::SCO_STATE_DISCONNECTED;
232 DelayedSingleton<AudioDeviceManager>::GetInstance()->ProcessEvent(
233 AudioEvent::BLUETOOTH_SCO_DISCONNECTED);
234 }
235 break;
236 default:
237 break;
238 }
239 }
240
AddBtDevice(const std::string & address,Bluetooth::BluetoothRemoteDevice device)241 void BluetoothConnection::AddBtDevice(const std::string &address, Bluetooth::BluetoothRemoteDevice device)
242 {
243 auto iter = mapConnectedBtDevices_.find(address);
244 if (iter != mapConnectedBtDevices_.end()) {
245 TELEPHONY_LOGI("device is existenced");
246 } else {
247 mapConnectedBtDevices_.insert(std::pair<std::string, const Bluetooth::BluetoothRemoteDevice>(address, device));
248 TELEPHONY_LOGI("AddBtDevice success");
249 }
250 }
251
RemoveBtDevice(const std::string & address)252 void BluetoothConnection::RemoveBtDevice(const std::string &address)
253 {
254 if (mapConnectedBtDevices_.count(address) > 0) {
255 mapConnectedBtDevices_.erase(address);
256 TELEPHONY_LOGI("RemoveBtDevice success");
257 } else {
258 TELEPHONY_LOGE("device is not existenced");
259 }
260 }
261
GetBtDevice(const std::string & address)262 Bluetooth::BluetoothRemoteDevice *BluetoothConnection::GetBtDevice(const std::string &address)
263 {
264 if (mapConnectedBtDevices_.count(address) > 0) {
265 auto iter = mapConnectedBtDevices_.find(address);
266 if (iter != mapConnectedBtDevices_.end()) {
267 return &iter->second;
268 }
269 }
270 TELEPHONY_LOGE("device is not existenced");
271 return nullptr;
272 }
273
OnConnectionStateChanged(const Bluetooth::BluetoothRemoteDevice & device,int32_t state)274 void BluetoothConnection::OnConnectionStateChanged(const Bluetooth::BluetoothRemoteDevice &device, int32_t state)
275 {
276 TELEPHONY_LOGI("BluetoothConnection::OnConnectionStateChanged state : %{public}d", state);
277 std::string macAddress = device.GetDeviceAddr();
278 switch (state) {
279 case (int32_t)Bluetooth::BTConnectState::CONNECTED:
280 AddBtDevice(macAddress, device);
281 /** try to connect sco while new bluetooth device connected
282 * if connect sco successfully , should switch current audio device to bluetooth sco
283 */
284 if (BluetoothConnection::GetBtScoState() == BtScoState::SCO_STATE_DISCONNECTED && IsAudioActivated()) {
285 ConnectBtSco(device);
286 }
287 break;
288 case (int32_t)Bluetooth::BTConnectState::DISCONNECTED:
289 RemoveBtDevice(macAddress);
290 break;
291 default:
292 break;
293 }
294 }
295 #endif
296 } // namespace Telephony
297 } // namespace OHOS
298