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
init()69 ::android::status_t StreamBluetooth::init() {
70 std::lock_guard guard(mLock);
71 if (mBtDeviceProxy == nullptr) {
72 // This is a normal situation in VTS tests.
73 LOG(INFO) << __func__ << ": no BT HAL proxy, stream is non-functional";
74 }
75 LOG(INFO) << __func__ << ": preferred data interval (us): " << mPreferredDataIntervalUs;
76 return ::android::OK;
77 }
78
drain(StreamDescriptor::DrainMode)79 ::android::status_t StreamBluetooth::drain(StreamDescriptor::DrainMode) {
80 usleep(1000);
81 return ::android::OK;
82 }
83
flush()84 ::android::status_t StreamBluetooth::flush() {
85 usleep(1000);
86 return ::android::OK;
87 }
88
pause()89 ::android::status_t StreamBluetooth::pause() {
90 return standby();
91 }
92
transfer(void * buffer,size_t frameCount,size_t * actualFrameCount,int32_t * latencyMs)93 ::android::status_t StreamBluetooth::transfer(void* buffer, size_t frameCount,
94 size_t* actualFrameCount, int32_t* latencyMs) {
95 std::lock_guard guard(mLock);
96 *actualFrameCount = 0;
97 *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
98 if (mBtDeviceProxy == nullptr || mBtDeviceProxy->getState() == BluetoothStreamState::DISABLED) {
99 // The BT session is turned down, silently ignore write.
100 return ::android::OK;
101 }
102 if (!mBtDeviceProxy->start()) {
103 LOG(WARNING) << __func__ << ": state= " << mBtDeviceProxy->getState()
104 << " failed to start, will retry";
105 return ::android::OK;
106 }
107 *latencyMs = 0;
108 const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
109 const size_t bytesTransferred = mIsInput ? mBtDeviceProxy->readData(buffer, bytesToTransfer)
110 : mBtDeviceProxy->writeData(buffer, bytesToTransfer);
111 *actualFrameCount = bytesTransferred / mFrameSizeBytes;
112 PresentationPosition presentation_position;
113 if (!mBtDeviceProxy->getPresentationPosition(presentation_position)) {
114 presentation_position.remoteDeviceAudioDelayNanos =
115 kBluetoothDefaultRemoteDelayMs * NANOS_PER_MILLISECOND;
116 LOG(WARNING) << __func__ << ": getPresentationPosition failed, latency info is unavailable";
117 }
118 // TODO(b/317117580): incorporate logic from
119 // packages/modules/Bluetooth/system/audio_bluetooth_hw/stream_apis.cc
120 // out_calculate_feeding_delay_ms / in_calculate_starving_delay_ms
121 *latencyMs = std::max(*latencyMs, (int32_t)(presentation_position.remoteDeviceAudioDelayNanos /
122 NANOS_PER_MILLISECOND));
123 return ::android::OK;
124 }
125
126 // static
checkConfigParams(const PcmConfiguration & pcmConfig,const AudioConfigBase & config)127 bool StreamBluetooth::checkConfigParams(const PcmConfiguration& pcmConfig,
128 const AudioConfigBase& config) {
129 if ((int)config.sampleRate != pcmConfig.sampleRateHz) {
130 LOG(ERROR) << __func__ << ": sample rate mismatch, stream value=" << config.sampleRate
131 << ", BT HAL value=" << pcmConfig.sampleRateHz;
132 return false;
133 }
134 const auto channelCount =
135 aidl::android::hardware::audio::common::getChannelCount(config.channelMask);
136 if ((pcmConfig.channelMode == ChannelMode::MONO && channelCount != 1) ||
137 (pcmConfig.channelMode == ChannelMode::STEREO && channelCount != 2)) {
138 LOG(ERROR) << __func__ << ": Channel count mismatch, stream value=" << channelCount
139 << ", BT HAL value=" << toString(pcmConfig.channelMode);
140 return false;
141 }
142 if (config.format.type != AudioFormatType::PCM) {
143 LOG(ERROR) << __func__
144 << ": unexpected stream format type: " << toString(config.format.type);
145 return false;
146 }
147 const int8_t bitsPerSample =
148 aidl::android::hardware::audio::common::getPcmSampleSizeInBytes(config.format.pcm) * 8;
149 if (bitsPerSample != pcmConfig.bitsPerSample) {
150 LOG(ERROR) << __func__ << ": bits per sample mismatch, stream value=" << bitsPerSample
151 << ", BT HAL value=" << pcmConfig.bitsPerSample;
152 return false;
153 }
154 return true;
155 }
156
prepareToClose()157 ndk::ScopedAStatus StreamBluetooth::prepareToClose() {
158 std::lock_guard guard(mLock);
159 if (mBtDeviceProxy != nullptr) {
160 if (mBtDeviceProxy->getState() != BluetoothStreamState::DISABLED) {
161 mBtDeviceProxy->stop();
162 }
163 }
164 return ndk::ScopedAStatus::ok();
165 }
166
standby()167 ::android::status_t StreamBluetooth::standby() {
168 std::lock_guard guard(mLock);
169 if (mBtDeviceProxy != nullptr) mBtDeviceProxy->suspend();
170 return ::android::OK;
171 }
172
start()173 ::android::status_t StreamBluetooth::start() {
174 std::lock_guard guard(mLock);
175 if (mBtDeviceProxy != nullptr) mBtDeviceProxy->start();
176 return ::android::OK;
177 }
178
shutdown()179 void StreamBluetooth::shutdown() {
180 std::lock_guard guard(mLock);
181 if (mBtDeviceProxy != nullptr) {
182 mBtDeviceProxy->stop();
183 mBtDeviceProxy = nullptr;
184 }
185 }
186
updateMetadataCommon(const Metadata & metadata)187 ndk::ScopedAStatus StreamBluetooth::updateMetadataCommon(const Metadata& metadata) {
188 std::lock_guard guard(mLock);
189 if (mBtDeviceProxy == nullptr) {
190 return ndk::ScopedAStatus::ok();
191 }
192 bool isOk = true;
193 if (isInput(metadata)) {
194 isOk = mBtDeviceProxy->updateSinkMetadata(std::get<SinkMetadata>(metadata));
195 } else {
196 isOk = mBtDeviceProxy->updateSourceMetadata(std::get<SourceMetadata>(metadata));
197 }
198 return isOk ? ndk::ScopedAStatus::ok()
199 : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
200 }
201
bluetoothParametersUpdated()202 ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {
203 if (mIsInput) {
204 return ndk::ScopedAStatus::ok();
205 }
206 auto applyParam = [](const std::shared_ptr<BluetoothAudioPortAidl>& proxy,
207 bool isEnabled) -> bool {
208 if (!isEnabled) {
209 if (proxy->suspend()) return proxy->setState(BluetoothStreamState::DISABLED);
210 return false;
211 }
212 return proxy->standby();
213 };
214 bool hasA2dpParam, enableA2dp;
215 auto btA2dp = mBluetoothA2dp.lock();
216 hasA2dpParam = btA2dp != nullptr && btA2dp->isEnabled(&enableA2dp).isOk();
217 bool hasLeParam, enableLe;
218 auto btLe = mBluetoothLe.lock();
219 hasLeParam = btLe != nullptr && btLe->isEnabled(&enableLe).isOk();
220 std::lock_guard guard(mLock);
221 if (mBtDeviceProxy != nullptr) {
222 if ((hasA2dpParam && mBtDeviceProxy->isA2dp() && !applyParam(mBtDeviceProxy, enableA2dp)) ||
223 (hasLeParam && mBtDeviceProxy->isLeAudio() && !applyParam(mBtDeviceProxy, enableLe))) {
224 LOG(DEBUG) << __func__ << ": applyParam failed";
225 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
226 }
227 }
228 return ndk::ScopedAStatus::ok();
229 }
230
231 // static
getNominalLatencyMs(size_t dataIntervalUs)232 int32_t StreamInBluetooth::getNominalLatencyMs(size_t dataIntervalUs) {
233 if (dataIntervalUs == 0) dataIntervalUs = kBluetoothDefaultInputBufferMs * 1000LL;
234 return dataIntervalUs / 1000LL;
235 }
236
StreamInBluetooth(StreamContext && context,const SinkMetadata & sinkMetadata,const std::vector<MicrophoneInfo> & microphones,ModuleBluetooth::BtProfileHandles && btProfileHandles,const std::shared_ptr<BluetoothAudioPortAidl> & btDeviceProxy,const PcmConfiguration & pcmConfig)237 StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
238 const std::vector<MicrophoneInfo>& microphones,
239 ModuleBluetooth::BtProfileHandles&& btProfileHandles,
240 const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
241 const PcmConfiguration& pcmConfig)
242 : StreamIn(std::move(context), microphones),
243 StreamBluetooth(&mContextInstance, sinkMetadata, std::move(btProfileHandles), btDeviceProxy,
244 pcmConfig) {}
245
getActiveMicrophones(std::vector<MicrophoneDynamicInfo> * _aidl_return __unused)246 ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
247 std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
248 LOG(DEBUG) << __func__ << ": not supported";
249 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
250 }
251
252 // static
getNominalLatencyMs(size_t dataIntervalUs)253 int32_t StreamOutBluetooth::getNominalLatencyMs(size_t dataIntervalUs) {
254 if (dataIntervalUs == 0) dataIntervalUs = kBluetoothDefaultOutputBufferMs * 1000LL;
255 return dataIntervalUs / 1000LL;
256 }
257
StreamOutBluetooth(StreamContext && context,const SourceMetadata & sourceMetadata,const std::optional<AudioOffloadInfo> & offloadInfo,ModuleBluetooth::BtProfileHandles && btProfileHandles,const std::shared_ptr<BluetoothAudioPortAidl> & btDeviceProxy,const PcmConfiguration & pcmConfig)258 StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
259 const SourceMetadata& sourceMetadata,
260 const std::optional<AudioOffloadInfo>& offloadInfo,
261 ModuleBluetooth::BtProfileHandles&& btProfileHandles,
262 const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
263 const PcmConfiguration& pcmConfig)
264 : StreamOut(std::move(context), offloadInfo),
265 StreamBluetooth(&mContextInstance, sourceMetadata, std::move(btProfileHandles), btDeviceProxy,
266 pcmConfig) {}
267
268 } // namespace aidl::android::hardware::audio::core
269