Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55045b5f authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

audio: Clean up and fix the bluetooth HAL module

Fix the issue with retrieving BluetoothA2dp and BluetoothLe
instances access.

In 'Module::connectExternalDevice', always call
'populateConnectedDevicePort' to allow the module implementation
to cancel device connection.

Move frame count calculation into Utils.
Clean up includes and 'using' directives.

Bug: 302132812
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I22f65b8bcdcdd9bcd67a8290520eb4a465d4c720
parent 1350187c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -174,4 +174,12 @@ constexpr U makeBitPositionFlagMask(std::initializer_list<E> flags) {
    return result;
}

constexpr int32_t frameCountFromDurationUs(long durationUs, int32_t sampleRateHz) {
    return (durationUs * sampleRateHz) / 1000000LL;
}

constexpr int32_t frameCountFromDurationMs(int32_t durationMs, int32_t sampleRateHz) {
    return frameCountFromDurationUs(durationMs * 1000, sampleRateHz);
}

}  // namespace aidl::android::hardware::audio::common
+26 −33
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
#include <set>

#define LOG_TAG "AHAL_Module"
#include <Utils.h>
#include <aidl/android/media/audio/common/AudioInputFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
#include <android-base/logging.h>
@@ -35,6 +34,7 @@
#include "core-impl/SoundDose.h"
#include "core-impl/utils.h"

using aidl::android::hardware::audio::common::frameCountFromDurationMs;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::common::isValidAudioMode;
@@ -617,10 +617,11 @@ ndk::ScopedAStatus Module::connectExternalDevice(const AudioPort& in_templateIdA

    std::vector<AudioRoute*> routesToMixPorts = getAudioRoutesForAudioPortImpl(templateId);
    std::set<int32_t> routableMixPortIds = getRoutableAudioPortIds(templateId, &routesToMixPorts);
    if (hasDynamicProfilesOnly(connectedPort.profiles)) {
    if (!mDebug.simulateDeviceConnections) {
        // Even if the device port has static profiles, the HAL module might need to update
        // them, or abort the connection process.
        RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
        } else {
    } else if (hasDynamicProfilesOnly(connectedPort.profiles)) {
        auto& connectedProfiles = getConfig().connectedProfiles;
        if (auto connectedProfilesIt = connectedProfiles.find(templateId);
            connectedProfilesIt != connectedProfiles.end()) {
@@ -631,20 +632,17 @@ ndk::ScopedAStatus Module::connectExternalDevice(const AudioPort& in_templateIdA
        // Possible case 2. Check if all routable mix ports have static profiles.
        if (auto dynamicMixPortIt = std::find_if(ports.begin(), ports.end(),
                                                 [&routableMixPortIds](const auto& p) {
                                                         return routableMixPortIds.count(p.id) >
                                                                        0 &&
                                                     return routableMixPortIds.count(p.id) > 0 &&
                                                            hasDynamicProfilesOnly(p.profiles);
                                                 });
            dynamicMixPortIt != ports.end()) {
                LOG(ERROR) << __func__
                           << ": connected port only has dynamic profiles after connecting "
            LOG(ERROR) << __func__ << ": connected port only has dynamic profiles after connecting "
                       << "external device " << connectedPort.toString() << ", and there exist "
                       << "a routable mix port with dynamic profiles: "
                       << dynamicMixPortIt->toString();
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }
    }
    }

    connectedPort.id = getConfig().nextPortId++;
    auto [connectedPortsIt, _] =
@@ -1229,7 +1227,7 @@ ndk::ScopedAStatus Module::setMasterMute(bool in_mute) {
        // Reset master mute if it failed.
        onMasterMuteChanged(mMasterMute);
    }
    return std::move(result);
    return result;
}

ndk::ScopedAStatus Module::getMasterVolume(float* _aidl_return) {
@@ -1251,7 +1249,7 @@ ndk::ScopedAStatus Module::setMasterVolume(float in_volume) {
                       << "), error=" << result;
            onMasterVolumeChanged(mMasterVolume);
        }
        return std::move(result);
        return result;
    }
    LOG(ERROR) << __func__ << ": invalid master volume value: " << in_volume;
    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
@@ -1572,11 +1570,6 @@ std::vector<MicrophoneInfo> Module::getMicrophoneInfos() {
    return result;
}

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();
}
+15 −15
Original line number Diff line number Diff line
@@ -19,11 +19,25 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <audio_utils/primitives.h>
#include <inttypes.h>
#include <log/log.h>

#include "BluetoothAudioSessionControl.h"
#include "core-impl/DevicePortProxy.h"

using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
using aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl;
using aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus;
using aidl::android::hardware::bluetooth::audio::ChannelMode;
using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
using aidl::android::hardware::bluetooth::audio::PortStatusCallbacks;
using aidl::android::hardware::bluetooth::audio::PresentationPosition;
using aidl::android::hardware::bluetooth::audio::SessionType;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using android::base::StringPrintf;

namespace android::bluetooth::audio::aidl {

namespace {
@@ -33,20 +47,6 @@ constexpr unsigned int kMaxWaitingTimeMs = 4500;

}  // namespace

using ::aidl::android::hardware::audio::common::SinkMetadata;
using ::aidl::android::hardware::audio::common::SourceMetadata;
using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration;
using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl;
using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus;
using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
using ::aidl::android::hardware::bluetooth::audio::PortStatusCallbacks;
using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
using ::aidl::android::hardware::bluetooth::audio::SessionType;
using ::aidl::android::media::audio::common::AudioDeviceDescription;
using ::aidl::android::media::audio::common::AudioDeviceType;
using ::android::base::StringPrintf;

std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state) {
    switch (state) {
        case BluetoothStreamState::DISABLED:
+37 −26
Original line number Diff line number Diff line
@@ -18,50 +18,56 @@

#include <android-base/logging.h>

#include "BluetoothAudioSessionControl.h"
#include "BluetoothAudioSession.h"
#include "core-impl/ModuleBluetooth.h"
#include "core-impl/StreamBluetooth.h"

namespace aidl::android::hardware::audio::core {
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::MicrophoneInfo;
using android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
using android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;

using ::aidl::android::hardware::audio::common::SinkMetadata;
using ::aidl::android::hardware::audio::common::SourceMetadata;
using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession;
using ::aidl::android::media::audio::common::AudioDeviceDescription;
using ::aidl::android::media::audio::common::AudioDeviceType;
using ::aidl::android::media::audio::common::AudioOffloadInfo;
using ::aidl::android::media::audio::common::AudioPort;
using ::aidl::android::media::audio::common::AudioPortExt;
using ::aidl::android::media::audio::common::MicrophoneInfo;
using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
namespace aidl::android::hardware::audio::core {

ndk::ScopedAStatus ModuleBluetooth::getBluetoothA2dp(
        std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
    *_aidl_return = getBtA2dp().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) {
    *_aidl_return = getBtLe().getInstance();
    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
    return ndk::ScopedAStatus::ok();
}

ChildInterface<BluetoothA2dp>& ModuleBluetooth::getBtA2dp() {
    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();
    return mBluetoothA2dp;
}

ndk::ScopedAStatus ModuleBluetooth::getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) {
ChildInterface<BluetoothLe>& ModuleBluetooth::getBtLe() {
    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();
    return mBluetoothLe;
}

Module::BtProfileHandles ModuleBluetooth::getBtProfileManagerHandles() {
    return std::make_tuple(std::weak_ptr<IBluetooth>(), mBluetoothA2dp.getInstance(),
                           mBluetoothLe.getInstance());
ModuleBluetooth::BtProfileHandles ModuleBluetooth::getBtProfileManagerHandles() {
    return std::make_tuple(std::weak_ptr<IBluetooth>(), getBtA2dp().getPtr(), getBtLe().getPtr());
}

ndk::ScopedAStatus ModuleBluetooth::getMicMute(bool* _aidl_return __unused) {
@@ -101,30 +107,35 @@ ndk::ScopedAStatus ModuleBluetooth::populateConnectedDevicePort(AudioPort* audio
    if (description.connection == AudioDeviceDescription::CONNECTION_BT_A2DP) {
        bool isA2dpEnabled = false;
        if (!!mBluetoothA2dp) {
            RETURN_STATUS_IF_ERROR(mBluetoothA2dp.getInstance()->isEnabled(&isA2dpEnabled));
            RETURN_STATUS_IF_ERROR((*mBluetoothA2dp).isEnabled(&isA2dpEnabled));
        }
        LOG(DEBUG) << __func__ << ": isA2dpEnabled: " << isA2dpEnabled;
        return isA2dpEnabled ? ndk::ScopedAStatus::ok()
                             : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE) {
        bool isLeEnabled = false;
        if (!!mBluetoothLe) {
            RETURN_STATUS_IF_ERROR(mBluetoothLe.getInstance()->isEnabled(&isLeEnabled));
            RETURN_STATUS_IF_ERROR((*mBluetoothLe).isEnabled(&isLeEnabled));
        }
        LOG(DEBUG) << __func__ << ": isLeEnabled: " << isLeEnabled;
        return isLeEnabled ? ndk::ScopedAStatus::ok()
                           : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    } else if (description.connection == AudioDeviceDescription::CONNECTION_WIRELESS &&
               description.type == AudioDeviceType::OUT_HEARING_AID) {
        // Hearing aids can use a number of profiles, thus the only way to check
        // connectivity is to try to talk to the BT HAL.
        if (!BluetoothAudioSession::IsAidlAvailable()) {
        if (!::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession::
                    IsAidlAvailable()) {
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }
        std::shared_ptr<BluetoothAudioPortAidl> proxy = std::shared_ptr<BluetoothAudioPortAidl>(
                std::make_shared<BluetoothAudioPortAidlOut>());
        if (proxy->registerPort(description)) {
            LOG(DEBUG) << __func__ << ": registered hearing aid port";
            proxy->unregisterPort();
            return ndk::ScopedAStatus::ok();
        }
        LOG(DEBUG) << __func__ << ": failed to register hearing aid port";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    LOG(ERROR) << __func__ << ": unsupported device type: " << audioPort->toString();
+29 −32
Original line number Diff line number Diff line
@@ -20,52 +20,49 @@
#include <android-base/logging.h>
#include <audio_utils/clock.h>

#include "BluetoothAudioSessionControl.h"
#include "BluetoothAudioSession.h"
#include "core-impl/StreamBluetooth.h"

namespace aidl::android::hardware::audio::core {
using aidl::android::hardware::audio::common::frameCountFromDurationUs;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::hardware::audio::core::VendorParameter;
using aidl::android::hardware::bluetooth::audio::ChannelMode;
using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
using aidl::android::hardware::bluetooth::audio::PresentationPosition;
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
using android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
using android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn;
using android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
using android::bluetooth::audio::aidl::BluetoothStreamState;

using ::aidl::android::hardware::audio::common::SinkMetadata;
using ::aidl::android::hardware::audio::common::SourceMetadata;
using ::aidl::android::hardware::audio::core::VendorParameter;
using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
using ::aidl::android::media::audio::common::AudioChannelLayout;
using ::aidl::android::media::audio::common::AudioDevice;
using ::aidl::android::media::audio::common::AudioDeviceAddress;
using ::aidl::android::media::audio::common::AudioFormatDescription;
using ::aidl::android::media::audio::common::AudioFormatType;
using ::aidl::android::media::audio::common::AudioOffloadInfo;
using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
using ::aidl::android::media::audio::common::MicrophoneInfo;
using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn;
using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
using ::android::bluetooth::audio::aidl::BluetoothStreamState;
namespace aidl::android::hardware::audio::core {

constexpr int kBluetoothDefaultInputBufferMs = 20;
constexpr int kBluetoothDefaultOutputBufferMs = 10;
// constexpr int kBluetoothSpatializerOutputBufferMs = 10;

size_t getFrameCount(uint64_t durationUs, uint32_t sampleRate) {
    return (durationUs * sampleRate) / 1000000;
}

// pcm configuration params are not really used by the module
StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata,
                                 Module::BtProfileHandles&& btHandles)
                                 ModuleBluetooth::BtProfileHandles&& btHandles)
    : StreamCommonImpl(context, metadata),
      mSampleRate(getContext().getSampleRate()),
      mChannelLayout(getContext().getChannelLayout()),
      mFormat(getContext().getFormat()),
      mFrameSizeBytes(getContext().getFrameSize()),
      mIsInput(isInput(metadata)),
      mBluetoothA2dp(std::move(std::get<Module::BtInterface::BTA2DP>(btHandles))),
      mBluetoothLe(std::move(std::get<Module::BtInterface::BTLE>(btHandles))) {
      mBluetoothA2dp(std::move(std::get<ModuleBluetooth::BtInterface::BTA2DP>(btHandles))),
      mBluetoothLe(std::move(std::get<ModuleBluetooth::BtInterface::BTLE>(btHandles))) {
    mPreferredDataIntervalUs =
            mIsInput ? kBluetoothDefaultInputBufferMs : kBluetoothDefaultOutputBufferMs;
    mPreferredFrameCount = getFrameCount(mPreferredDataIntervalUs, mSampleRate);
            (mIsInput ? kBluetoothDefaultInputBufferMs : kBluetoothDefaultOutputBufferMs) * 1000;
    mPreferredFrameCount = frameCountFromDurationUs(mPreferredDataIntervalUs, mSampleRate);
    mIsInitialized = false;
    mIsReadyToClose = false;
}
@@ -226,7 +223,7 @@ bool StreamBluetooth::checkConfigParams(
    if (config.dataIntervalUs > 0) {
        mPreferredDataIntervalUs =
                std::min((int32_t)mPreferredDataIntervalUs, config.dataIntervalUs);
        mPreferredFrameCount = getFrameCount(mPreferredDataIntervalUs, mSampleRate);
        mPreferredFrameCount = frameCountFromDurationUs(mPreferredDataIntervalUs, mSampleRate);
    }
    return true;
}
@@ -318,7 +315,7 @@ ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {

StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
                                     const std::vector<MicrophoneInfo>& microphones,
                                     Module::BtProfileHandles&& btProfileHandles)
                                     ModuleBluetooth::BtProfileHandles&& btProfileHandles)
    : StreamIn(std::move(context), microphones),
      StreamBluetooth(&mContextInstance, sinkMetadata, std::move(btProfileHandles)) {}

@@ -331,7 +328,7 @@ ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
                                       const SourceMetadata& sourceMetadata,
                                       const std::optional<AudioOffloadInfo>& offloadInfo,
                                       Module::BtProfileHandles&& btProfileHandles)
                                       ModuleBluetooth::BtProfileHandles&& btProfileHandles)
    : StreamOut(std::move(context), offloadInfo),
      StreamBluetooth(&mContextInstance, sourceMetadata, std::move(btProfileHandles)) {}

Loading