1 /*
2 * Copyright (c) 2021-2022 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 "audio_bluetooth_manager.h"
17
18 #include "audio_info.h"
19 #include "audio_errors.h"
20 #include "audio_log.h"
21 #include "bluetooth_def.h"
22 #include "hdf_remote_service.h"
23 #include "servmgr_hdi.h"
24
25 namespace OHOS {
26 namespace Bluetooth {
27 using namespace AudioStandard;
28
29 IDeviceStatusObserver *g_deviceObserver = nullptr;
30 A2dpSource *AudioA2dpManager::a2dpInstance_ = nullptr;
31 AudioA2dpListener AudioA2dpManager::a2dpListener_;
32 HandsFreeAudioGateway *AudioHfpManager::hfpInstance_ = nullptr;
33 AudioHfpListener AudioHfpManager::hfpListener_;
34 int AudioA2dpManager::connectionState_ = static_cast<int>(BTConnectState::DISCONNECTED);
35 bool AudioA2dpManager::bluetoothSinkLoaded_ = false;
36 BluetoothRemoteDevice AudioA2dpManager::bluetoothRemoteDevice_;
37 HdfRemoteService *g_hdiService = nullptr;
38 HdfRemoteService *g_audioSessionService = nullptr;
39 constexpr const char *AUDIO_BLUETOOTH_SERVICE_NAME = "audio_bluetooth_hdi_service";
40
41 std::mutex g_deviceLock;
42 std::mutex g_a2dpInstanceLock;
43
GetAudioStreamInfo(A2dpCodecInfo codecInfo,AudioStreamInfo & audioStreamInfo)44 static bool GetAudioStreamInfo(A2dpCodecInfo codecInfo, AudioStreamInfo &audioStreamInfo)
45 {
46 switch (codecInfo.sampleRate) {
47 case A2DP_SBC_SAMPLE_RATE_48000_USER:
48 audioStreamInfo.samplingRate = SAMPLE_RATE_48000;
49 break;
50 case A2DP_SBC_SAMPLE_RATE_44100_USER:
51 audioStreamInfo.samplingRate = SAMPLE_RATE_44100;
52 break;
53 case A2DP_SBC_SAMPLE_RATE_32000_USER:
54 audioStreamInfo.samplingRate = SAMPLE_RATE_32000;
55 break;
56 case A2DP_SBC_SAMPLE_RATE_16000_USER:
57 audioStreamInfo.samplingRate = SAMPLE_RATE_16000;
58 break;
59 default:
60 return false;
61 }
62
63 switch (codecInfo.bitsPerSample) {
64 case A2DP_SAMPLE_BITS_16_USER:
65 audioStreamInfo.format = SAMPLE_S16LE;
66 break;
67 case A2DP_SAMPLE_BITS_24_USER:
68 audioStreamInfo.format = SAMPLE_S24LE;
69 break;
70 case A2DP_SAMPLE_BITS_32_USER:
71 audioStreamInfo.format = SAMPLE_S32LE;
72 break;
73 default:
74 return false;
75 }
76
77 switch (codecInfo.channelMode) {
78 case A2DP_SBC_CHANNEL_MODE_STEREO_USER:
79 audioStreamInfo.channels = STEREO;
80 break;
81 case A2DP_SBC_CHANNEL_MODE_MONO_USER:
82 audioStreamInfo.channels = MONO;
83 break;
84 default:
85 return false;
86 }
87
88 audioStreamInfo.encoding = ENCODING_PCM;
89
90 return true;
91 }
92
RegisterDeviceObserver(IDeviceStatusObserver & observer)93 int32_t RegisterDeviceObserver(IDeviceStatusObserver &observer)
94 {
95 std::lock_guard<std::mutex> deviceLock(g_deviceLock);
96 g_deviceObserver = &observer;
97 return SUCCESS;
98 }
99
UnregisterDeviceObserver()100 void UnregisterDeviceObserver()
101 {
102 std::lock_guard<std::mutex> deviceLock(g_deviceLock);
103 g_deviceObserver = nullptr;
104 }
105
RegisterBluetoothA2dpListener()106 void AudioA2dpManager::RegisterBluetoothA2dpListener()
107 {
108 AUDIO_INFO_LOG("Entered %{public}s", __func__);
109
110 std::lock_guard<std::mutex> a2dpLock(g_a2dpInstanceLock);
111
112 a2dpInstance_ = A2dpSource::GetProfile();
113 CHECK_AND_RETURN_LOG(a2dpInstance_ != nullptr, "Failed to obtain A2DP profile instance");
114
115 a2dpInstance_->RegisterObserver(&a2dpListener_);
116 }
117
UnregisterBluetoothA2dpListener()118 void AudioA2dpManager::UnregisterBluetoothA2dpListener()
119 {
120 AUDIO_INFO_LOG("Entered %{public}s", __func__);
121
122 std::lock_guard<std::mutex> a2dpLock(g_a2dpInstanceLock);
123
124 CHECK_AND_RETURN_LOG(a2dpInstance_ != nullptr, "A2DP profile instance unavailable");
125
126 a2dpInstance_->DeregisterObserver(&a2dpListener_);
127 a2dpInstance_ = nullptr;
128 }
129
ConnectBluetoothA2dpSink()130 void AudioA2dpManager::ConnectBluetoothA2dpSink()
131 {
132 // Update device when hdi service is available
133 if (connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
134 AUDIO_ERR_LOG("bluetooth state is not on");
135 return;
136 }
137
138 std::lock_guard<std::mutex> deviceLock(g_deviceLock);
139
140 if (g_deviceObserver == nullptr) {
141 AUDIO_INFO_LOG("device observer is null");
142 return;
143 }
144
145 AudioStreamInfo streamInfo = {};
146 A2dpCodecStatus codecStatus = A2dpSource::GetProfile()->GetCodecStatus(bluetoothRemoteDevice_);
147 if (!GetAudioStreamInfo(codecStatus.codecInfo, streamInfo)) {
148 AUDIO_ERR_LOG("OnConnectionStateChanged: Unsupported a2dp codec info");
149 return;
150 }
151
152 g_deviceObserver->OnDeviceStatusUpdated(DEVICE_TYPE_BLUETOOTH_A2DP, true,
153 bluetoothRemoteDevice_.GetDeviceAddr(), bluetoothRemoteDevice_.GetDeviceName(), streamInfo);
154 bluetoothSinkLoaded_ = true;
155 }
156
DisconnectBluetoothA2dpSink()157 void AudioA2dpManager::DisconnectBluetoothA2dpSink()
158 {
159 if (!bluetoothSinkLoaded_) {
160 AUDIO_INFO_LOG("DisconnectBluetoothA2dpSink: bluetooth is disconnected");
161 return;
162 }
163
164 int connectionState = static_cast<int>(BTConnectState::DISCONNECTED);
165 a2dpListener_.OnConnectionStateChanged(bluetoothRemoteDevice_, connectionState);
166 }
167
OnConnectionStateChanged(const BluetoothRemoteDevice & device,int state)168 void AudioA2dpListener::OnConnectionStateChanged(const BluetoothRemoteDevice &device, int state)
169 {
170 AUDIO_INFO_LOG("OnConnectionStateChanged: state: %{public}d", state);
171
172 // Record connection state and device for hdi start time to check
173 AudioA2dpManager::SetConnectionState(state);
174 if (state == static_cast<int>(BTConnectState::CONNECTED)) {
175 AudioA2dpManager::SetBluetoothRemoteDevice(device);
176
177 struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();
178 if (serviceMgr == nullptr) {
179 AUDIO_ERR_LOG("HDIServiceManagerGet failed!");
180 return;
181 }
182 g_hdiService = serviceMgr->GetService(serviceMgr, AUDIO_BLUETOOTH_SERVICE_NAME);
183 HDIServiceManagerRelease(serviceMgr);
184
185 if (g_hdiService != nullptr) {
186 AUDIO_INFO_LOG("Remote GetService [g_hdiService] SUCCESS!");
187 AudioA2dpManager::ConnectBluetoothA2dpSink();
188 }
189 }
190
191 // Currently disconnect need to be done in OnConnectionStateChanged instead of hdi service stopped
192 if (state == static_cast<int>(BTConnectState::DISCONNECTED)) {
193 std::lock_guard<std::mutex> deviceLock(g_deviceLock);
194
195 if (g_deviceObserver == nullptr) {
196 AUDIO_INFO_LOG("device observer is null");
197 return;
198 }
199
200 AudioStreamInfo streamInfo = {};
201 g_deviceObserver->OnDeviceStatusUpdated(DEVICE_TYPE_BLUETOOTH_A2DP, false,
202 device.GetDeviceAddr(), device.GetDeviceName(), streamInfo);
203 AudioA2dpManager::SetBluetoothSinkLoaded(false);
204 }
205 }
206
OnConfigurationChanged(const BluetoothRemoteDevice & device,const A2dpCodecInfo & codecInfo,int error)207 void AudioA2dpListener::OnConfigurationChanged(const BluetoothRemoteDevice &device, const A2dpCodecInfo &codecInfo,
208 int error)
209 {
210 AUDIO_INFO_LOG("OnConfigurationChanged: sampleRate: %{public}d, channels: %{public}d, format: %{public}d",
211 codecInfo.sampleRate, codecInfo.channelMode, codecInfo.bitsPerSample);
212
213 std::lock_guard<std::mutex> deviceLock(g_deviceLock);
214
215 if (g_deviceObserver == nullptr) {
216 AUDIO_INFO_LOG("device observer is null");
217 return;
218 }
219
220 AudioStreamInfo streamInfo = {};
221 if (!GetAudioStreamInfo(codecInfo, streamInfo)) {
222 AUDIO_ERR_LOG("OnConfigurationChanged: Unsupported a2dp codec info");
223 return;
224 }
225
226 g_deviceObserver->OnDeviceConfigurationChanged(DEVICE_TYPE_BLUETOOTH_A2DP, device.GetDeviceAddr(),
227 device.GetDeviceName(), streamInfo);
228 }
229
OnPlayingStatusChanged(const BluetoothRemoteDevice & device,int playingState,int error)230 void AudioA2dpListener::OnPlayingStatusChanged(const BluetoothRemoteDevice &device, int playingState, int error)
231 {
232 AUDIO_INFO_LOG("OnPlayingStatusChanged, state: %{public}d, error: %{public}d", playingState, error);
233 }
234
RegisterBluetoothScoListener()235 void AudioHfpManager::RegisterBluetoothScoListener()
236 {
237 AUDIO_INFO_LOG("Entered %{public}s", __func__);
238 hfpInstance_ = HandsFreeAudioGateway::GetProfile();
239 CHECK_AND_RETURN_LOG(hfpInstance_ != nullptr, "Failed to obtain HFP AG profile instance");
240
241 hfpInstance_->RegisterObserver(&hfpListener_);
242 }
243
UnregisterBluetoothScoListener()244 void AudioHfpManager::UnregisterBluetoothScoListener()
245 {
246 AUDIO_INFO_LOG("Entered %{public}s", __func__);
247 CHECK_AND_RETURN_LOG(hfpInstance_ != nullptr, "HFP AG profile instance unavailable");
248
249 hfpInstance_->DeregisterObserver(&hfpListener_);
250 hfpInstance_ = nullptr;
251 }
252
OnScoStateChanged(const BluetoothRemoteDevice & device,int state)253 void AudioHfpListener::OnScoStateChanged(const BluetoothRemoteDevice &device, int state)
254 {
255 AUDIO_INFO_LOG("Entered %{public}s [%{public}d]", __func__, state);
256
257 std::lock_guard<std::mutex> deviceLock(g_deviceLock);
258
259 if (g_deviceObserver == nullptr) {
260 AUDIO_INFO_LOG("device observer is null");
261 return;
262 }
263
264 HfpScoConnectState scoState = static_cast<HfpScoConnectState>(state);
265 if (scoState == HfpScoConnectState::SCO_CONNECTED || scoState == HfpScoConnectState::SCO_DISCONNECTED) {
266 AudioStreamInfo streamInfo = {};
267 bool isConnected = (scoState == HfpScoConnectState::SCO_CONNECTED) ? true : false;
268 g_deviceObserver->OnDeviceStatusUpdated(DEVICE_TYPE_BLUETOOTH_SCO, isConnected, device.GetDeviceAddr(),
269 device.GetDeviceName(), streamInfo);
270 }
271 }
272
273 } // namespace Bluetooth
274 } // namespace OHOS
275