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