• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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