aosp aidl bluetooth parameter support

Bug: 228804498
Test: atest VtsHalAudioCoreTargetTest
Change-Id: If1820018d5a6750eed0d0b486e15fc7c717aa11c
(cherry picked from commit 18f0d5121a)
Merged-In: If1820018d5a6750eed0d0b486e15fc7c717aa11c
This commit is contained in:
Ram Mohan 2023-07-01 00:47:09 +05:30 committed by Mikhail Naganov
parent 59df2f67e4
commit e77db70308
14 changed files with 199 additions and 26 deletions

View file

@ -82,19 +82,18 @@ ndk::ScopedAStatus Bluetooth::setHfpConfig(const HfpConfig& in_config, HfpConfig
ndk::ScopedAStatus BluetoothA2dp::isEnabled(bool* _aidl_return) {
*_aidl_return = mEnabled;
LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothA2dp::setEnabled(bool in_enabled) {
mEnabled = in_enabled;
LOG(DEBUG) << __func__ << ": " << mEnabled;
if (mHandler) return mHandler();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothA2dp::supportsOffloadReconfiguration(bool* _aidl_return) {
*_aidl_return = true;
LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
*_aidl_return = false;
return ndk::ScopedAStatus::ok();
}
@ -102,24 +101,22 @@ ndk::ScopedAStatus BluetoothA2dp::reconfigureOffload(
const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
__unused) {
LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
return ndk::ScopedAStatus::ok();
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus BluetoothLe::isEnabled(bool* _aidl_return) {
*_aidl_return = mEnabled;
LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothLe::setEnabled(bool in_enabled) {
mEnabled = in_enabled;
LOG(DEBUG) << __func__ << ": " << mEnabled;
if (mHandler) return mHandler();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothLe::supportsOffloadReconfiguration(bool* _aidl_return) {
*_aidl_return = true;
LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
*_aidl_return = false;
return ndk::ScopedAStatus::ok();
}
@ -127,7 +124,7 @@ ndk::ScopedAStatus BluetoothLe::reconfigureOffload(
const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
__unused) {
LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
return ndk::ScopedAStatus::ok();
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
} // namespace aidl::android::hardware::audio::core

View file

@ -1371,4 +1371,13 @@ ndk::ScopedAStatus Module::onMasterVolumeChanged(float volume __unused) {
return ndk::ScopedAStatus::ok();
}
Module::BtProfileHandles Module::getBtProfileManagerHandles() {
return std::make_tuple(std::weak_ptr<IBluetooth>(), std::weak_ptr<IBluetoothA2dp>(),
std::weak_ptr<IBluetoothLe>());
}
ndk::ScopedAStatus Module::bluetoothParametersUpdated() {
return mStreams.bluetoothParametersUpdated();
}
} // namespace aidl::android::hardware::audio::core

View file

@ -723,6 +723,11 @@ ndk::ScopedAStatus StreamCommonImpl::setConnectedDevices(
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus StreamCommonImpl::bluetoothParametersUpdated() {
LOG(DEBUG) << __func__;
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
namespace {
static std::map<AudioDevice, std::string> transformMicrophones(
const std::vector<MicrophoneInfo>& microphones) {

View file

@ -233,8 +233,28 @@ ndk::ScopedAStatus StreamSwitcher::setConnectedDevices(const std::vector<AudioDe
<< status.getDescription();
}
}
if (mBluetoothParametersUpdated) {
if (auto status = mStream->bluetoothParametersUpdated(); !status.isOk()) {
LOG(WARNING) << __func__
<< ": error while updating BT parameters for a new stream: "
<< status.getDescription();
}
}
mBluetoothParametersUpdated = false;
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus StreamSwitcher::bluetoothParametersUpdated() {
if (mStream == nullptr) {
LOG(ERROR) << __func__ << ": stream was closed";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
if (mIsStubStream) {
mBluetoothParametersUpdated = true;
return ndk::ScopedAStatus::ok();
}
return mStream->bluetoothParametersUpdated();
}
} // namespace aidl::android::hardware::audio::core

View file

@ -302,6 +302,21 @@ bool BluetoothAudioPortAidl::loadAudioConfig(PcmConfiguration* audio_cfg) const
return true;
}
bool BluetoothAudioPortAidl::standby() {
if (!inUse()) {
LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
return false;
}
std::lock_guard guard(mCvMutex);
LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
if (mState == BluetoothStreamState::DISABLED) {
mState = BluetoothStreamState::STANDBY;
LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " done";
return true;
}
return false;
}
bool BluetoothAudioPortAidl::condWaitState(BluetoothStreamState state) {
const auto waitTime = std::chrono::milliseconds(kMaxWaitingTimeMs);
std::unique_lock lock(mCvMutex);

View file

@ -28,6 +28,34 @@ using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
ndk::ScopedAStatus ModuleBluetooth::getBluetoothA2dp(
std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
if (!mBluetoothA2dp) {
auto handle = ndk::SharedRefBase::make<BluetoothA2dp>();
handle->registerHandler(std::bind(&ModuleBluetooth::bluetoothParametersUpdated, this));
mBluetoothA2dp = handle;
}
*_aidl_return = mBluetoothA2dp.getInstance();
LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus ModuleBluetooth::getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) {
if (!mBluetoothLe) {
auto handle = ndk::SharedRefBase::make<BluetoothLe>();
handle->registerHandler(std::bind(&ModuleBluetooth::bluetoothParametersUpdated, this));
mBluetoothLe = handle;
}
*_aidl_return = mBluetoothLe.getInstance();
LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
return ndk::ScopedAStatus::ok();
}
Module::BtProfileHandles ModuleBluetooth::getBtProfileManagerHandles() {
return std::make_tuple(std::weak_ptr<IBluetooth>(), mBluetoothA2dp.getInstance(),
mBluetoothLe.getInstance());
}
ndk::ScopedAStatus ModuleBluetooth::getMicMute(bool* _aidl_return __unused) {
LOG(DEBUG) << __func__ << ": is not supported";
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@ -42,14 +70,14 @@ ndk::ScopedAStatus ModuleBluetooth::createInputStream(
StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
return createStreamInstance<StreamInBluetooth>(result, std::move(context), sinkMetadata,
microphones);
microphones, getBtProfileManagerHandles());
}
ndk::ScopedAStatus ModuleBluetooth::createOutputStream(
StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
return createStreamInstance<StreamOutBluetooth>(result, std::move(context), sourceMetadata,
offloadInfo);
offloadInfo, getBtProfileManagerHandles());
}
ndk::ScopedAStatus ModuleBluetooth::onMasterMuteChanged(bool) {

View file

@ -53,13 +53,16 @@ size_t getFrameCount(uint64_t durationUs, uint32_t sampleRate) {
}
// pcm configuration params are not really used by the module
StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata)
StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata,
Module::BtProfileHandles&& btHandles)
: StreamCommonImpl(context, metadata),
mSampleRate(getContext().getSampleRate()),
mChannelLayout(getContext().getChannelLayout()),
mFormat(getContext().getFormat()),
mFrameSizeBytes(getContext().getFrameSize()),
mIsInput(isInput(metadata)) {
mIsInput(isInput(metadata)),
mBluetoothA2dp(std::move(std::get<Module::BtInterface::BTA2DP>(btHandles))),
mBluetoothLe(std::move(std::get<Module::BtInterface::BTLE>(btHandles))) {
mPreferredDataIntervalUs =
mIsInput ? kBluetoothDefaultInputBufferMs : kBluetoothDefaultOutputBufferMs;
mPreferredFrameCount = getFrameCount(mPreferredDataIntervalUs, mSampleRate);
@ -278,10 +281,46 @@ ndk::ScopedAStatus StreamBluetooth::updateMetadataCommon(const Metadata& metadat
: ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {
if (mIsInput) {
LOG(WARNING) << __func__ << ": not handled";
return ndk::ScopedAStatus::ok();
}
auto applyParam = [](const std::shared_ptr<BluetoothAudioPortAidl>& proxy,
bool isEnabled) -> bool {
if (!isEnabled) {
if (proxy->suspend()) return proxy->setState(BluetoothStreamState::DISABLED);
return false;
}
return proxy->standby();
};
bool hasA2dpParam, enableA2dp;
auto btA2dp = mBluetoothA2dp.lock();
hasA2dpParam = btA2dp != nullptr && btA2dp->isEnabled(&enableA2dp).isOk();
bool hasLeParam, enableLe;
auto btLe = mBluetoothLe.lock();
hasLeParam = btLe != nullptr && btLe->isEnabled(&enableLe).isOk();
std::unique_lock lock(mLock);
::android::base::ScopedLockAssertion lock_assertion(mLock);
if (!mIsInitialized) {
LOG(WARNING) << __func__ << ": init not done";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
for (auto proxy : mBtDeviceProxies) {
if ((hasA2dpParam && proxy->isA2dp() && !applyParam(proxy, enableA2dp)) ||
(hasLeParam && proxy->isLeAudio() && !applyParam(proxy, enableLe))) {
LOG(DEBUG) << __func__ << ": applyParam failed";
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
}
return ndk::ScopedAStatus::ok();
}
StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
const std::vector<MicrophoneInfo>& microphones,
Module::BtProfileHandles&& btProfileHandles)
: StreamIn(std::move(context), microphones),
StreamBluetooth(&(StreamIn::mContext), sinkMetadata) {}
StreamBluetooth(&(StreamIn::mContext), sinkMetadata, std::move(btProfileHandles)) {}
ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
@ -291,8 +330,9 @@ ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
const std::optional<AudioOffloadInfo>& offloadInfo,
Module::BtProfileHandles&& btProfileHandles)
: StreamOut(std::move(context), offloadInfo),
StreamBluetooth(&(StreamOut::mContext), sourceMetadata) {}
StreamBluetooth(&(StreamOut::mContext), sourceMetadata, std::move(btProfileHandles)) {}
} // namespace aidl::android::hardware::audio::core

View file

@ -22,6 +22,15 @@
namespace aidl::android::hardware::audio::core {
class ParamChangeHandler {
public:
ParamChangeHandler() = default;
void registerHandler(std::function<ndk::ScopedAStatus()> handler) { mHandler = handler; }
protected:
std::function<ndk::ScopedAStatus()> mHandler = nullptr;
};
class Bluetooth : public BnBluetooth {
public:
Bluetooth();
@ -34,7 +43,7 @@ class Bluetooth : public BnBluetooth {
HfpConfig mHfpConfig;
};
class BluetoothA2dp : public BnBluetoothA2dp {
class BluetoothA2dp : public BnBluetoothA2dp, public ParamChangeHandler {
public:
BluetoothA2dp() = default;
@ -49,7 +58,7 @@ class BluetoothA2dp : public BnBluetoothA2dp {
bool mEnabled = false;
};
class BluetoothLe : public BnBluetoothLe {
class BluetoothLe : public BnBluetoothLe, public ParamChangeHandler {
public:
BluetoothLe() = default;

View file

@ -83,8 +83,16 @@ class BluetoothAudioPort {
/**
* When the Audio framework / HAL wants to change the stream state, it invokes
* these 3 functions to control the Bluetooth stack (Audio Control Path).
* Note: Both start() and suspend() will return true when there are no errors.
* these 4 functions to control the Bluetooth stack (Audio Control Path).
* Note: standby(), start() and suspend() will return true when there are no errors.
* Called by Audio framework / HAL to change the state to stand by. When A2DP/LE profile is
* disabled, the port is first set to STANDBY by calling suspend and then mState is set to
* DISABLED. To reset the state back to STANDBY this method is called.
*/
virtual bool standby() = 0;
/**
* Called by Audio framework / HAL to start the stream
*/
virtual bool start() = 0;
@ -160,6 +168,7 @@ class BluetoothAudioPortAidl : public BluetoothAudioPort {
void forcePcmStereoToMono(bool force) override { mIsStereoToMono = force; }
bool standby() override;
bool start() override;
bool suspend() override;
void stop() override;

View file

@ -34,11 +34,16 @@ class Module : public BnModule {
// This value is used for all AudioPatches and reported by all streams.
static constexpr int32_t kLatencyMs = 10;
enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH };
enum BtInterface : int { BTCONF, BTA2DP, BTLE };
static std::shared_ptr<Module> createInstance(Type type);
explicit Module(Type type) : mType(type) {}
typedef std::tuple<std::weak_ptr<IBluetooth>, std::weak_ptr<IBluetoothA2dp>,
std::weak_ptr<IBluetoothLe>>
BtProfileHandles;
protected:
// The vendor extension done via inheritance can override interface methods and augment
// a call to the base implementation.
@ -185,6 +190,7 @@ class Module : public BnModule {
virtual std::unique_ptr<internal::Configuration> initializeConfig();
// Utility and helper functions accessible to subclasses.
ndk::ScopedAStatus bluetoothParametersUpdated();
void cleanUpPatch(int32_t patchId);
ndk::ScopedAStatus createStreamContext(
int32_t in_portConfigId, int64_t in_bufferSizeFrames,
@ -196,6 +202,7 @@ class Module : public BnModule {
std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
ndk::ScopedAStatus findPortIdForNewStream(
int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
virtual BtProfileHandles getBtProfileManagerHandles();
internal::Configuration& getConfig();
const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
bool getMasterMute() const { return mMasterMute; }

View file

@ -16,6 +16,7 @@
#pragma once
#include "core-impl/Bluetooth.h"
#include "core-impl/Module.h"
namespace aidl::android::hardware::audio::core {
@ -25,6 +26,10 @@ class ModuleBluetooth final : public Module {
ModuleBluetooth() : Module(Type::BLUETOOTH) {}
private:
BtProfileHandles getBtProfileManagerHandles() override;
ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) override;
ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
ndk::ScopedAStatus setMicMute(bool in_mute) override;
@ -41,6 +46,9 @@ class ModuleBluetooth final : public Module {
std::shared_ptr<StreamOut>* result) override;
ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
ChildInterface<IBluetoothLe> mBluetoothLe;
};
} // namespace aidl::android::hardware::audio::core

View file

@ -354,6 +354,7 @@ struct StreamCommonInterface {
virtual const ConnectedDevices& getConnectedDevices() const = 0;
virtual ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
virtual ndk::ScopedAStatus bluetoothParametersUpdated() = 0;
};
// This is equivalent to automatically generated 'IStreamCommonDelegator' but uses
@ -454,6 +455,7 @@ class StreamCommonImpl : virtual public StreamCommonInterface, virtual public Dr
ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
ndk::ScopedAStatus bluetoothParametersUpdated() override;
protected:
static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
@ -584,6 +586,11 @@ class StreamWrapper {
if (s) return s->setConnectedDevices(devices);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus bluetoothParametersUpdated() {
auto s = mStream.lock();
if (s) return s->bluetoothParametersUpdated();
return ndk::ScopedAStatus::ok();
}
private:
std::weak_ptr<StreamCommonInterface> mStream;
@ -612,6 +619,14 @@ class Streams {
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus bluetoothParametersUpdated() {
bool isOk = true;
for (auto& it : mStreams) {
if (!it.second.bluetoothParametersUpdated().isOk()) isOk = false;
}
return isOk ? ndk::ScopedAStatus::ok()
: ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
private:
// Maps port ids and port config ids to streams. Multimap because a port

View file

@ -19,15 +19,20 @@
#include <mutex>
#include <vector>
#include <aidl/android/hardware/audio/core/IBluetooth.h>
#include <aidl/android/hardware/audio/core/IBluetoothA2dp.h>
#include <aidl/android/hardware/audio/core/IBluetoothLe.h>
#include "core-impl/DevicePortProxy.h"
#include "core-impl/Module.h"
#include "core-impl/Stream.h"
namespace aidl::android::hardware::audio::core {
class StreamBluetooth : public StreamCommonImpl {
public:
StreamBluetooth(StreamContext* context, const Metadata& metadata);
StreamBluetooth(StreamContext* context, const Metadata& metadata,
Module::BtProfileHandles&& btHandles);
// Methods of 'DriverInterface'.
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
@ -44,6 +49,7 @@ class StreamBluetooth : public StreamCommonImpl {
ndk::ScopedAStatus prepareToClose() override;
const ConnectedDevices& getConnectedDevices() const override;
ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
ndk::ScopedAStatus bluetoothParametersUpdated() override;
private:
// Audio Pcm Config
@ -52,7 +58,8 @@ class StreamBluetooth : public StreamCommonImpl {
const ::aidl::android::media::audio::common::AudioFormatDescription mFormat;
const size_t mFrameSizeBytes;
const bool mIsInput;
const std::weak_ptr<IBluetoothA2dp> mBluetoothA2dp;
const std::weak_ptr<IBluetoothLe> mBluetoothLe;
size_t mPreferredDataIntervalUs;
size_t mPreferredFrameCount;
@ -72,7 +79,8 @@ class StreamInBluetooth final : public StreamIn, public StreamBluetooth {
StreamInBluetooth(
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
Module::BtProfileHandles&& btHandles);
private:
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
@ -88,7 +96,8 @@ class StreamOutBluetooth final : public StreamOut, public StreamBluetooth {
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
offloadInfo,
Module::BtProfileHandles&& btHandles);
private:
void onClose(StreamDescriptor::State) override { defaultOnClose(); }

View file

@ -129,6 +129,7 @@ class StreamSwitcher : virtual public StreamCommonInterface {
ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
ndk::ScopedAStatus bluetoothParametersUpdated() override;
protected:
// Since switching a stream requires closing down the current stream, StreamSwitcher
@ -187,6 +188,7 @@ class StreamSwitcher : virtual public StreamCommonInterface {
std::optional<int32_t> mHwAvSyncId;
std::vector<VndParam> mMissedParameters;
std::vector<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>> mEffects;
bool mBluetoothParametersUpdated = false;
};
} // namespace aidl::android::hardware::audio::core