blob: a73af1b6b449a91379d3c9f2b0adfec886896d99 [file] [log] [blame]
Mikhail Naganovb03b5c42023-07-26 13:13:35 -07001/*
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
Mikhail Naganova88cf602023-12-13 14:35:11 -080017#include <algorithm>
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070018
Mikhail Naganova88cf602023-12-13 14:35:11 -080019#define LOG_TAG "AHAL_StreamBluetooth"
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070020#include <Utils.h>
21#include <android-base/logging.h>
22#include <audio_utils/clock.h>
23
Mikhail Naganov55045b52023-10-24 17:03:50 -070024#include "BluetoothAudioSession.h"
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070025#include "core-impl/StreamBluetooth.h"
26
Mikhail Naganov55045b52023-10-24 17:03:50 -070027using aidl::android::hardware::audio::common::frameCountFromDurationUs;
28using aidl::android::hardware::audio::common::SinkMetadata;
29using aidl::android::hardware::audio::common::SourceMetadata;
30using aidl::android::hardware::audio::core::VendorParameter;
31using aidl::android::hardware::bluetooth::audio::ChannelMode;
32using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
33using aidl::android::hardware::bluetooth::audio::PresentationPosition;
34using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganova88cf602023-12-13 14:35:11 -080035using aidl::android::media::audio::common::AudioConfigBase;
Mikhail Naganov55045b52023-10-24 17:03:50 -070036using aidl::android::media::audio::common::AudioDevice;
37using aidl::android::media::audio::common::AudioDeviceAddress;
38using aidl::android::media::audio::common::AudioFormatDescription;
39using aidl::android::media::audio::common::AudioFormatType;
40using aidl::android::media::audio::common::AudioOffloadInfo;
41using aidl::android::media::audio::common::MicrophoneDynamicInfo;
42using aidl::android::media::audio::common::MicrophoneInfo;
43using android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
44using android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn;
45using android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
46using android::bluetooth::audio::aidl::BluetoothStreamState;
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070047
Mikhail Naganov55045b52023-10-24 17:03:50 -070048namespace aidl::android::hardware::audio::core {
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070049
50constexpr int kBluetoothDefaultInputBufferMs = 20;
51constexpr int kBluetoothDefaultOutputBufferMs = 10;
52// constexpr int kBluetoothSpatializerOutputBufferMs = 10;
Mikhail Naganova88cf602023-12-13 14:35:11 -080053constexpr int kBluetoothDefaultRemoteDelayMs = 200;
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070054
Ram Mohan18f0d512023-07-01 00:47:09 +053055StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata,
Mikhail Naganova88cf602023-12-13 14:35:11 -080056 ModuleBluetooth::BtProfileHandles&& btHandles,
57 const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
58 const PcmConfiguration& pcmConfig)
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070059 : StreamCommonImpl(context, metadata),
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070060 mFrameSizeBytes(getContext().getFrameSize()),
Ram Mohan18f0d512023-07-01 00:47:09 +053061 mIsInput(isInput(metadata)),
Mikhail Naganov55045b52023-10-24 17:03:50 -070062 mBluetoothA2dp(std::move(std::get<ModuleBluetooth::BtInterface::BTA2DP>(btHandles))),
Mikhail Naganova88cf602023-12-13 14:35:11 -080063 mBluetoothLe(std::move(std::get<ModuleBluetooth::BtInterface::BTLE>(btHandles))),
64 mPreferredDataIntervalUs(pcmConfig.dataIntervalUs != 0
65 ? pcmConfig.dataIntervalUs
66 : (mIsInput ? kBluetoothDefaultInputBufferMs
67 : kBluetoothDefaultOutputBufferMs) *
68 1000),
69 mPreferredFrameCount(
70 frameCountFromDurationUs(mPreferredDataIntervalUs, pcmConfig.sampleRateHz)),
71 mBtDeviceProxy(btDeviceProxy) {}
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070072
73::android::status_t StreamBluetooth::init() {
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070074 std::lock_guard guard(mLock);
Mikhail Naganova88cf602023-12-13 14:35:11 -080075 if (mBtDeviceProxy == nullptr) {
76 // This is a normal situation in VTS tests.
77 LOG(INFO) << __func__ << ": no BT HAL proxy, stream is non-functional";
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070078 }
Mikhail Naganova88cf602023-12-13 14:35:11 -080079 return ::android::OK;
Mikhail Naganovb03b5c42023-07-26 13:13:35 -070080}
81
82::android::status_t StreamBluetooth::drain(StreamDescriptor::DrainMode) {
83 usleep(1000);
84 return ::android::OK;
85}
86
87::android::status_t StreamBluetooth::flush() {
88 usleep(1000);
89 return ::android::OK;
90}
91
92::android::status_t StreamBluetooth::pause() {
93 return standby();
94}
95
96::android::status_t StreamBluetooth::transfer(void* buffer, size_t frameCount,
97 size_t* actualFrameCount, int32_t* latencyMs) {
98 std::lock_guard guard(mLock);
Mikhail Naganova88cf602023-12-13 14:35:11 -080099 if (mBtDeviceProxy == nullptr || mBtDeviceProxy->getState() == BluetoothStreamState::DISABLED) {
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700100 *actualFrameCount = 0;
101 *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
102 return ::android::OK;
103 }
104 *actualFrameCount = 0;
105 *latencyMs = 0;
Mikhail Naganova88cf602023-12-13 14:35:11 -0800106 if (!mBtDeviceProxy->start()) {
107 LOG(ERROR) << __func__ << ": state= " << mBtDeviceProxy->getState() << " failed to start";
108 return -EIO;
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700109 }
Mikhail Naganova88cf602023-12-13 14:35:11 -0800110 const size_t fc = std::min(frameCount, mPreferredFrameCount);
111 const size_t bytesToTransfer = fc * mFrameSizeBytes;
112 if (mIsInput) {
113 const size_t totalRead = mBtDeviceProxy->readData(buffer, bytesToTransfer);
114 *actualFrameCount = std::max(*actualFrameCount, totalRead / mFrameSizeBytes);
115 } else {
116 const size_t totalWrite = mBtDeviceProxy->writeData(buffer, bytesToTransfer);
117 *actualFrameCount = std::max(*actualFrameCount, totalWrite / mFrameSizeBytes);
118 }
119 PresentationPosition presentation_position;
120 if (!mBtDeviceProxy->getPresentationPosition(presentation_position)) {
121 presentation_position.remoteDeviceAudioDelayNanos =
122 kBluetoothDefaultRemoteDelayMs * NANOS_PER_MILLISECOND;
123 LOG(WARNING) << __func__ << ": getPresentationPosition failed, latency info is unavailable";
124 }
125 // TODO(b/317117580): incorporate logic from
126 // packages/modules/Bluetooth/system/audio_bluetooth_hw/stream_apis.cc
127 // out_calculate_feeding_delay_ms / in_calculate_starving_delay_ms
128 *latencyMs = std::max(*latencyMs, (int32_t)(presentation_position.remoteDeviceAudioDelayNanos /
129 NANOS_PER_MILLISECOND));
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700130 return ::android::OK;
131}
132
Mikhail Naganova88cf602023-12-13 14:35:11 -0800133// static
134bool StreamBluetooth::checkConfigParams(const PcmConfiguration& pcmConfig,
135 const AudioConfigBase& config) {
136 if ((int)config.sampleRate != pcmConfig.sampleRateHz) {
137 LOG(ERROR) << __func__ << ": sample rate mismatch, stream value=" << config.sampleRate
138 << ", BT HAL value=" << pcmConfig.sampleRateHz;
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700139 return false;
140 }
Mikhail Naganova88cf602023-12-13 14:35:11 -0800141 const auto channelCount =
142 aidl::android::hardware::audio::common::getChannelCount(config.channelMask);
143 if ((pcmConfig.channelMode == ChannelMode::MONO && channelCount != 1) ||
144 (pcmConfig.channelMode == ChannelMode::STEREO && channelCount != 2)) {
145 LOG(ERROR) << __func__ << ": Channel count mismatch, stream value=" << channelCount
146 << ", BT HAL value=" << toString(pcmConfig.channelMode);
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700147 return false;
148 }
Mikhail Naganova88cf602023-12-13 14:35:11 -0800149 if (config.format.type != AudioFormatType::PCM) {
150 LOG(ERROR) << __func__
151 << ": unexpected stream format type: " << toString(config.format.type);
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700152 return false;
153 }
Mikhail Naganova88cf602023-12-13 14:35:11 -0800154 const int8_t bitsPerSample =
155 aidl::android::hardware::audio::common::getPcmSampleSizeInBytes(config.format.pcm) * 8;
156 if (bitsPerSample != pcmConfig.bitsPerSample) {
157 LOG(ERROR) << __func__ << ": bits per sample mismatch, stream value=" << bitsPerSample
158 << ", BT HAL value=" << pcmConfig.bitsPerSample;
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700159 return false;
160 }
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700161 return true;
162}
163
164ndk::ScopedAStatus StreamBluetooth::prepareToClose() {
165 std::lock_guard guard(mLock);
Mikhail Naganova88cf602023-12-13 14:35:11 -0800166 if (mBtDeviceProxy != nullptr) {
167 if (mBtDeviceProxy->getState() != BluetoothStreamState::DISABLED) {
168 mBtDeviceProxy->stop();
169 }
170 }
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700171 return ndk::ScopedAStatus::ok();
172}
173
174::android::status_t StreamBluetooth::standby() {
175 std::lock_guard guard(mLock);
Mikhail Naganova88cf602023-12-13 14:35:11 -0800176 if (mBtDeviceProxy != nullptr) mBtDeviceProxy->suspend();
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700177 return ::android::OK;
178}
179
180::android::status_t StreamBluetooth::start() {
181 std::lock_guard guard(mLock);
Mikhail Naganova88cf602023-12-13 14:35:11 -0800182 if (mBtDeviceProxy != nullptr) mBtDeviceProxy->start();
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700183 return ::android::OK;
184}
185
186void StreamBluetooth::shutdown() {
187 std::lock_guard guard(mLock);
Mikhail Naganova88cf602023-12-13 14:35:11 -0800188 if (mBtDeviceProxy != nullptr) {
189 mBtDeviceProxy->stop();
190 mBtDeviceProxy = nullptr;
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700191 }
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700192}
193
194ndk::ScopedAStatus StreamBluetooth::updateMetadataCommon(const Metadata& metadata) {
195 std::lock_guard guard(mLock);
Mikhail Naganova88cf602023-12-13 14:35:11 -0800196 if (mBtDeviceProxy == nullptr) {
197 return ndk::ScopedAStatus::ok();
198 }
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700199 bool isOk = true;
200 if (isInput(metadata)) {
Mikhail Naganova88cf602023-12-13 14:35:11 -0800201 isOk = mBtDeviceProxy->updateSinkMetadata(std::get<SinkMetadata>(metadata));
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700202 } else {
Mikhail Naganova88cf602023-12-13 14:35:11 -0800203 isOk = mBtDeviceProxy->updateSourceMetadata(std::get<SourceMetadata>(metadata));
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700204 }
205 return isOk ? ndk::ScopedAStatus::ok()
206 : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
207}
208
Ram Mohan18f0d512023-07-01 00:47:09 +0530209ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {
210 if (mIsInput) {
Ram Mohan18f0d512023-07-01 00:47:09 +0530211 return ndk::ScopedAStatus::ok();
212 }
213 auto applyParam = [](const std::shared_ptr<BluetoothAudioPortAidl>& proxy,
214 bool isEnabled) -> bool {
215 if (!isEnabled) {
216 if (proxy->suspend()) return proxy->setState(BluetoothStreamState::DISABLED);
217 return false;
218 }
219 return proxy->standby();
220 };
221 bool hasA2dpParam, enableA2dp;
222 auto btA2dp = mBluetoothA2dp.lock();
223 hasA2dpParam = btA2dp != nullptr && btA2dp->isEnabled(&enableA2dp).isOk();
224 bool hasLeParam, enableLe;
225 auto btLe = mBluetoothLe.lock();
226 hasLeParam = btLe != nullptr && btLe->isEnabled(&enableLe).isOk();
Mikhail Naganova88cf602023-12-13 14:35:11 -0800227 std::lock_guard guard(mLock);
228 if (mBtDeviceProxy != nullptr) {
229 if ((hasA2dpParam && mBtDeviceProxy->isA2dp() && !applyParam(mBtDeviceProxy, enableA2dp)) ||
230 (hasLeParam && mBtDeviceProxy->isLeAudio() && !applyParam(mBtDeviceProxy, enableLe))) {
Ram Mohan18f0d512023-07-01 00:47:09 +0530231 LOG(DEBUG) << __func__ << ": applyParam failed";
232 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
233 }
234 }
235 return ndk::ScopedAStatus::ok();
236}
237
Mikhail Naganova88cf602023-12-13 14:35:11 -0800238// static
239int32_t StreamInBluetooth::getNominalLatencyMs(size_t dataIntervalUs) {
240 if (dataIntervalUs == 0) dataIntervalUs = kBluetoothDefaultInputBufferMs * 1000LL;
241 return dataIntervalUs / 1000LL;
242}
243
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700244StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
Ram Mohan18f0d512023-07-01 00:47:09 +0530245 const std::vector<MicrophoneInfo>& microphones,
Mikhail Naganova88cf602023-12-13 14:35:11 -0800246 ModuleBluetooth::BtProfileHandles&& btProfileHandles,
247 const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
248 const PcmConfiguration& pcmConfig)
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700249 : StreamIn(std::move(context), microphones),
Mikhail Naganova88cf602023-12-13 14:35:11 -0800250 StreamBluetooth(&mContextInstance, sinkMetadata, std::move(btProfileHandles), btDeviceProxy,
251 pcmConfig) {}
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700252
253ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
254 std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
255 LOG(DEBUG) << __func__ << ": not supported";
256 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
257}
258
Mikhail Naganova88cf602023-12-13 14:35:11 -0800259// static
260int32_t StreamOutBluetooth::getNominalLatencyMs(size_t dataIntervalUs) {
261 if (dataIntervalUs == 0) dataIntervalUs = kBluetoothDefaultOutputBufferMs * 1000LL;
262 return dataIntervalUs / 1000LL;
263}
264
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700265StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
266 const SourceMetadata& sourceMetadata,
Ram Mohan18f0d512023-07-01 00:47:09 +0530267 const std::optional<AudioOffloadInfo>& offloadInfo,
Mikhail Naganova88cf602023-12-13 14:35:11 -0800268 ModuleBluetooth::BtProfileHandles&& btProfileHandles,
269 const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
270 const PcmConfiguration& pcmConfig)
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700271 : StreamOut(std::move(context), offloadInfo),
Mikhail Naganova88cf602023-12-13 14:35:11 -0800272 StreamBluetooth(&mContextInstance, sourceMetadata, std::move(btProfileHandles), btDeviceProxy,
273 pcmConfig) {}
Mikhail Naganovb03b5c42023-07-26 13:13:35 -0700274
275} // namespace aidl::android::hardware::audio::core