xref: /aosp_15_r20/hardware/interfaces/audio/aidl/default/bluetooth/StreamBluetooth.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <algorithm>
18 
19 #define LOG_TAG "AHAL_StreamBluetooth"
20 #include <Utils.h>
21 #include <android-base/logging.h>
22 #include <audio_utils/clock.h>
23 
24 #include "core-impl/StreamBluetooth.h"
25 
26 using aidl::android::hardware::audio::common::SinkMetadata;
27 using aidl::android::hardware::audio::common::SourceMetadata;
28 using aidl::android::hardware::audio::core::VendorParameter;
29 using aidl::android::hardware::bluetooth::audio::ChannelMode;
30 using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
31 using aidl::android::hardware::bluetooth::audio::PresentationPosition;
32 using aidl::android::media::audio::common::AudioChannelLayout;
33 using aidl::android::media::audio::common::AudioConfigBase;
34 using aidl::android::media::audio::common::AudioDevice;
35 using aidl::android::media::audio::common::AudioDeviceAddress;
36 using aidl::android::media::audio::common::AudioFormatDescription;
37 using aidl::android::media::audio::common::AudioFormatType;
38 using aidl::android::media::audio::common::AudioOffloadInfo;
39 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
40 using aidl::android::media::audio::common::MicrophoneInfo;
41 using android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
42 using android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn;
43 using android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
44 using android::bluetooth::audio::aidl::BluetoothStreamState;
45 
46 namespace aidl::android::hardware::audio::core {
47 
48 constexpr int kBluetoothDefaultInputBufferMs = 20;
49 constexpr int kBluetoothDefaultOutputBufferMs = 10;
50 // constexpr int kBluetoothSpatializerOutputBufferMs = 10;
51 constexpr int kBluetoothDefaultRemoteDelayMs = 200;
52 
StreamBluetooth(StreamContext * context,const Metadata & metadata,ModuleBluetooth::BtProfileHandles && btHandles,const std::shared_ptr<BluetoothAudioPortAidl> & btDeviceProxy,const PcmConfiguration & pcmConfig)53 StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata,
54                                  ModuleBluetooth::BtProfileHandles&& btHandles,
55                                  const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
56                                  const PcmConfiguration& pcmConfig)
57     : StreamCommonImpl(context, metadata),
58       mFrameSizeBytes(getContext().getFrameSize()),
59       mIsInput(isInput(metadata)),
60       mBluetoothA2dp(std::move(std::get<ModuleBluetooth::BtInterface::BTA2DP>(btHandles))),
61       mBluetoothLe(std::move(std::get<ModuleBluetooth::BtInterface::BTLE>(btHandles))),
62       mPreferredDataIntervalUs(pcmConfig.dataIntervalUs != 0
63                                        ? pcmConfig.dataIntervalUs
64                                        : (mIsInput ? kBluetoothDefaultInputBufferMs
65                                                    : kBluetoothDefaultOutputBufferMs) *
66                                                  1000),
67       mBtDeviceProxy(btDeviceProxy) {}
68 
~StreamBluetooth()69 StreamBluetooth::~StreamBluetooth() {
70     cleanupWorker();
71 }
72 
init()73 ::android::status_t StreamBluetooth::init() {
74     std::lock_guard guard(mLock);
75     if (mBtDeviceProxy == nullptr) {
76         // This is a normal situation in VTS tests.
77         LOG(INFO) << __func__ << ": no BT HAL proxy, stream is non-functional";
78     }
79     LOG(INFO) << __func__ << ": preferred data interval (us): " << mPreferredDataIntervalUs;
80     return ::android::OK;
81 }
82 
drain(StreamDescriptor::DrainMode)83 ::android::status_t StreamBluetooth::drain(StreamDescriptor::DrainMode) {
84     usleep(1000);
85     return ::android::OK;
86 }
87 
flush()88 ::android::status_t StreamBluetooth::flush() {
89     usleep(1000);
90     return ::android::OK;
91 }
92 
pause()93 ::android::status_t StreamBluetooth::pause() {
94     return standby();
95 }
96 
transfer(void * buffer,size_t frameCount,size_t * actualFrameCount,int32_t * latencyMs)97 ::android::status_t StreamBluetooth::transfer(void* buffer, size_t frameCount,
98                                               size_t* actualFrameCount, int32_t* latencyMs) {
99     std::lock_guard guard(mLock);
100     *actualFrameCount = 0;
101     *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
102     if (mBtDeviceProxy == nullptr || mBtDeviceProxy->getState() == BluetoothStreamState::DISABLED) {
103         // The BT session is turned down, silently ignore write.
104         return ::android::OK;
105     }
106     if (!mBtDeviceProxy->start()) {
107         LOG(WARNING) << __func__ << ": state= " << mBtDeviceProxy->getState()
108                      << " failed to start, will retry";
109         return ::android::OK;
110     }
111     *latencyMs = 0;
112     const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
113     const size_t bytesTransferred = mIsInput ? mBtDeviceProxy->readData(buffer, bytesToTransfer)
114                                              : mBtDeviceProxy->writeData(buffer, bytesToTransfer);
115     *actualFrameCount = bytesTransferred / mFrameSizeBytes;
116     PresentationPosition presentation_position;
117     if (!mBtDeviceProxy->getPresentationPosition(presentation_position)) {
118         presentation_position.remoteDeviceAudioDelayNanos =
119                 kBluetoothDefaultRemoteDelayMs * NANOS_PER_MILLISECOND;
120         LOG(WARNING) << __func__ << ": getPresentationPosition failed, latency info is unavailable";
121     }
122     // TODO(b/317117580): incorporate logic from
123     //                    packages/modules/Bluetooth/system/audio_bluetooth_hw/stream_apis.cc
124     //                    out_calculate_feeding_delay_ms / in_calculate_starving_delay_ms
125     *latencyMs = std::max(*latencyMs, (int32_t)(presentation_position.remoteDeviceAudioDelayNanos /
126                                                 NANOS_PER_MILLISECOND));
127     return ::android::OK;
128 }
129 
130 // static
checkConfigParams(const PcmConfiguration & pcmConfig,const AudioConfigBase & config)131 bool StreamBluetooth::checkConfigParams(const PcmConfiguration& pcmConfig,
132                                         const AudioConfigBase& config) {
133     if ((int)config.sampleRate != pcmConfig.sampleRateHz) {
134         LOG(ERROR) << __func__ << ": sample rate mismatch, stream value=" << config.sampleRate
135                    << ", BT HAL value=" << pcmConfig.sampleRateHz;
136         return false;
137     }
138     const auto channelCount =
139             aidl::android::hardware::audio::common::getChannelCount(config.channelMask);
140     if ((pcmConfig.channelMode == ChannelMode::MONO && channelCount != 1) ||
141         (pcmConfig.channelMode == ChannelMode::STEREO && channelCount != 2)) {
142         LOG(ERROR) << __func__ << ": Channel count mismatch, stream value=" << channelCount
143                    << ", BT HAL value=" << toString(pcmConfig.channelMode);
144         return false;
145     }
146     if (config.format.type != AudioFormatType::PCM) {
147         LOG(ERROR) << __func__
148                    << ": unexpected stream format type: " << toString(config.format.type);
149         return false;
150     }
151     const int8_t bitsPerSample =
152             aidl::android::hardware::audio::common::getPcmSampleSizeInBytes(config.format.pcm) * 8;
153     if (bitsPerSample != pcmConfig.bitsPerSample) {
154         LOG(ERROR) << __func__ << ": bits per sample mismatch, stream value=" << bitsPerSample
155                    << ", BT HAL value=" << pcmConfig.bitsPerSample;
156         return false;
157     }
158     return true;
159 }
160 
prepareToClose()161 ndk::ScopedAStatus StreamBluetooth::prepareToClose() {
162     std::lock_guard guard(mLock);
163     if (mBtDeviceProxy != nullptr) {
164         if (mBtDeviceProxy->getState() != BluetoothStreamState::DISABLED) {
165             mBtDeviceProxy->stop();
166         }
167     }
168     return ndk::ScopedAStatus::ok();
169 }
170 
standby()171 ::android::status_t StreamBluetooth::standby() {
172     std::lock_guard guard(mLock);
173     if (mBtDeviceProxy != nullptr) mBtDeviceProxy->suspend();
174     return ::android::OK;
175 }
176 
start()177 ::android::status_t StreamBluetooth::start() {
178     std::lock_guard guard(mLock);
179     if (mBtDeviceProxy != nullptr) mBtDeviceProxy->start();
180     return ::android::OK;
181 }
182 
shutdown()183 void StreamBluetooth::shutdown() {
184     std::lock_guard guard(mLock);
185     if (mBtDeviceProxy != nullptr) {
186         mBtDeviceProxy->stop();
187         mBtDeviceProxy = nullptr;
188     }
189 }
190 
updateMetadataCommon(const Metadata & metadata)191 ndk::ScopedAStatus StreamBluetooth::updateMetadataCommon(const Metadata& metadata) {
192     std::lock_guard guard(mLock);
193     if (mBtDeviceProxy == nullptr) {
194         return ndk::ScopedAStatus::ok();
195     }
196     bool isOk = true;
197     if (isInput(metadata)) {
198         isOk = mBtDeviceProxy->updateSinkMetadata(std::get<SinkMetadata>(metadata));
199     } else {
200         isOk = mBtDeviceProxy->updateSourceMetadata(std::get<SourceMetadata>(metadata));
201     }
202     return isOk ? ndk::ScopedAStatus::ok()
203                 : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
204 }
205 
bluetoothParametersUpdated()206 ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {
207     if (mIsInput) {
208         return ndk::ScopedAStatus::ok();
209     }
210     auto applyParam = [](const std::shared_ptr<BluetoothAudioPortAidl>& proxy,
211                          bool isEnabled) -> bool {
212         if (!isEnabled) {
213             if (proxy->suspend()) return proxy->setState(BluetoothStreamState::DISABLED);
214             return false;
215         }
216         return proxy->standby();
217     };
218     bool hasA2dpParam, enableA2dp;
219     auto btA2dp = mBluetoothA2dp.lock();
220     hasA2dpParam = btA2dp != nullptr && btA2dp->isEnabled(&enableA2dp).isOk();
221     bool hasLeParam, enableLe;
222     auto btLe = mBluetoothLe.lock();
223     hasLeParam = btLe != nullptr && btLe->isEnabled(&enableLe).isOk();
224     std::lock_guard guard(mLock);
225     if (mBtDeviceProxy != nullptr) {
226         if ((hasA2dpParam && mBtDeviceProxy->isA2dp() && !applyParam(mBtDeviceProxy, enableA2dp)) ||
227             (hasLeParam && mBtDeviceProxy->isLeAudio() && !applyParam(mBtDeviceProxy, enableLe))) {
228             LOG(DEBUG) << __func__ << ": applyParam failed";
229             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
230         }
231     }
232     return ndk::ScopedAStatus::ok();
233 }
234 
235 // static
getNominalLatencyMs(size_t dataIntervalUs)236 int32_t StreamInBluetooth::getNominalLatencyMs(size_t dataIntervalUs) {
237     if (dataIntervalUs == 0) dataIntervalUs = kBluetoothDefaultInputBufferMs * 1000LL;
238     return dataIntervalUs / 1000LL;
239 }
240 
StreamInBluetooth(StreamContext && context,const SinkMetadata & sinkMetadata,const std::vector<MicrophoneInfo> & microphones,ModuleBluetooth::BtProfileHandles && btProfileHandles,const std::shared_ptr<BluetoothAudioPortAidl> & btDeviceProxy,const PcmConfiguration & pcmConfig)241 StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
242                                      const std::vector<MicrophoneInfo>& microphones,
243                                      ModuleBluetooth::BtProfileHandles&& btProfileHandles,
244                                      const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
245                                      const PcmConfiguration& pcmConfig)
246     : StreamIn(std::move(context), microphones),
247       StreamBluetooth(&mContextInstance, sinkMetadata, std::move(btProfileHandles), btDeviceProxy,
248                       pcmConfig) {}
249 
getActiveMicrophones(std::vector<MicrophoneDynamicInfo> * _aidl_return __unused)250 ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
251         std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
252     LOG(DEBUG) << __func__ << ": not supported";
253     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
254 }
255 
256 // static
getNominalLatencyMs(size_t dataIntervalUs)257 int32_t StreamOutBluetooth::getNominalLatencyMs(size_t dataIntervalUs) {
258     if (dataIntervalUs == 0) dataIntervalUs = kBluetoothDefaultOutputBufferMs * 1000LL;
259     return dataIntervalUs / 1000LL;
260 }
261 
StreamOutBluetooth(StreamContext && context,const SourceMetadata & sourceMetadata,const std::optional<AudioOffloadInfo> & offloadInfo,ModuleBluetooth::BtProfileHandles && btProfileHandles,const std::shared_ptr<BluetoothAudioPortAidl> & btDeviceProxy,const PcmConfiguration & pcmConfig)262 StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
263                                        const SourceMetadata& sourceMetadata,
264                                        const std::optional<AudioOffloadInfo>& offloadInfo,
265                                        ModuleBluetooth::BtProfileHandles&& btProfileHandles,
266                                        const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
267                                        const PcmConfiguration& pcmConfig)
268     : StreamOut(std::move(context), offloadInfo),
269       StreamBluetooth(&mContextInstance, sourceMetadata, std::move(btProfileHandles), btDeviceProxy,
270                       pcmConfig) {}
271 
272 }  // namespace aidl::android::hardware::audio::core
273