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

Commit 75ac2490 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Load bluetooth.audio HAL as either 2.0 or 2.1

Test: atest bluetooth-test-audio-hal-interface
Bug: 150670922
Change-Id: I8024901283839c9ee25db732b42f5f9c4a3e5c24
parent fb913efd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ cc_library_shared {
    header_libs: ["libhardware_headers"],
    shared_libs: [
        "android.hardware.bluetooth.audio@2.0",
        "android.hardware.bluetooth.audio@2.1",
        "libaudioutils",
        "libbase",
        "libbluetooth_audio_session",
+21 −18
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@
#include <log/log.h>
#include <stdlib.h>

#include "BluetoothAudioSessionControl.h"
#include "BluetoothAudioSessionControl_2_1.h"
#include "device_port_proxy.h"
#include "stream_apis.h"
#include "utils.h"
@@ -33,7 +33,7 @@ namespace bluetooth {
namespace audio {

using ::android::base::StringPrintf;
using ::android::bluetooth::audio::BluetoothAudioSessionControl;
using ::android::bluetooth::audio::BluetoothAudioSessionControl_2_1;
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
@@ -99,7 +99,7 @@ constexpr unsigned int kMaxWaitingTimeMs = 4500;

BluetoothAudioPortOut::BluetoothAudioPortOut()
    : state_(BluetoothStreamState::DISABLED),
      session_type_(SessionType::UNKNOWN),
      session_type_(SessionType_2_1::UNKNOWN),
      cookie_(android::bluetooth::audio::kObserversCookieUndefined) {}

bool BluetoothAudioPortOut::SetUp(audio_devices_t devices) {
@@ -135,7 +135,7 @@ bool BluetoothAudioPortOut::SetUp(audio_devices_t devices) {
  ::android::bluetooth::audio::PortStatusCallbacks cbacks = {
      .control_result_cb_ = control_result_cb,
      .session_changed_cb_ = session_changed_cb};
  cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(
  cookie_ = BluetoothAudioSessionControl_2_1::RegisterControlResultCback(
      session_type_, cbacks);
  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);

@@ -149,19 +149,19 @@ bool BluetoothAudioPortOut::init_session_type(audio_devices_t device) {
    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
      LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
                   << StringPrintf("%#x", device) << ")";
      session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
      session_type_ = SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH;
      break;
    case AUDIO_DEVICE_OUT_HEARING_AID:
      LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) (" << StringPrintf("%#x", device)
                   << ")";
      session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
      session_type_ = SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
      break;
    default:
      LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
      return false;
  }

  if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
  if (!BluetoothAudioSessionControl_2_1::IsSessionReady(session_type_)) {
    LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device) << ", session_type=" << toString(session_type_)
               << " is not ready";
    return false;
@@ -177,7 +177,7 @@ void BluetoothAudioPortOut::TearDown() {
  }

  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
  BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_,
  BluetoothAudioSessionControl_2_1::UnregisterControlResultCback(session_type_,
                                                                 cookie_);
  cookie_ = android::bluetooth::audio::kObserversCookieUndefined;
}
@@ -260,7 +260,7 @@ bool BluetoothAudioPortOut::LoadAudioConfig(audio_config_t* audio_cfg) const {
  }

  const AudioConfiguration& hal_audio_cfg =
      BluetoothAudioSessionControl::GetAudioConfig(session_type_);
      BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_);
  if (hal_audio_cfg.getDiscriminator() !=
      AudioConfiguration::hidl_discriminator::pcmConfig) {
    audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
@@ -324,7 +324,7 @@ bool BluetoothAudioPortOut::Start() {
  bool retval = false;
  if (state_ == BluetoothStreamState::STANDBY) {
    state_ = BluetoothStreamState::STARTING;
    if (BluetoothAudioSessionControl::StartStream(session_type_)) {
    if (BluetoothAudioSessionControl_2_1::StartStream(session_type_)) {
      retval = CondwaitState(BluetoothStreamState::STARTING);
    } else {
      LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
@@ -355,7 +355,7 @@ bool BluetoothAudioPortOut::Suspend() {
  bool retval = false;
  if (state_ == BluetoothStreamState::STARTED) {
    state_ = BluetoothStreamState::SUSPENDING;
    if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
    if (BluetoothAudioSessionControl_2_1::SuspendStream(session_type_)) {
      retval = CondwaitState(BluetoothStreamState::SUSPENDING);
    } else {
      LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
@@ -382,7 +382,7 @@ void BluetoothAudioPortOut::Stop() {
  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
            << ", state=" << state_ << " request";
  state_ = BluetoothStreamState::DISABLED;
  BluetoothAudioSessionControl::StopStream(session_type_);
  BluetoothAudioSessionControl_2_1::StopStream(session_type_);
  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
            << ", state=" << state_ << " done";
}
@@ -390,7 +390,8 @@ void BluetoothAudioPortOut::Stop() {
size_t BluetoothAudioPortOut::WriteData(const void* buffer, size_t bytes) const {
  if (!in_use()) return 0;
  if (!is_stereo_to_mono_) {
    return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer, bytes);
    return BluetoothAudioSessionControl_2_1::OutWritePcmData(session_type_,
                                                             buffer, bytes);
  }

  // WAR to mix the stereo into Mono (16 bits per sample)
@@ -400,7 +401,9 @@ size_t BluetoothAudioPortOut::WriteData(const void* buffer, size_t bytes) const
  std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
  downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
  // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
  return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(), write_frames * 2) * 2;
  return BluetoothAudioSessionControl_2_1::OutWritePcmData(
             session_type_, dst.get(), write_frames * 2) *
         2;
}

bool BluetoothAudioPortOut::GetPresentationPosition(uint64_t* delay_ns,
@@ -410,7 +413,7 @@ bool BluetoothAudioPortOut::GetPresentationPosition(uint64_t* delay_ns,
    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
    return false;
  }
  bool retval = BluetoothAudioSessionControl::GetPresentationPosition(
  bool retval = BluetoothAudioSessionControl_2_1::GetPresentationPosition(
      session_type_, delay_ns, bytes, timestamp);
  LOG(VERBOSE) << __func__ << ": session_type=" << StringPrintf("%#hhx", session_type_)
               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", delay=" << *delay_ns
@@ -429,7 +432,7 @@ void BluetoothAudioPortOut::UpdateMetadata(
  LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
             << ", state=" << state_ << ", " << source_metadata->track_count << " track(s)";
  if (source_metadata->track_count == 0) return;
  BluetoothAudioSessionControl::UpdateTracksMetadata(session_type_,
  BluetoothAudioSessionControl_2_1::UpdateTracksMetadata(session_type_,
                                                         source_metadata);
}

+6 −5
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

#pragma once

#include <android/hardware/bluetooth/audio/2.0/types.h>
#include <android/hardware/bluetooth/audio/2.1/types.h>
#include <hardware/audio.h>
#include <condition_variable>
#include <mutex>
@@ -28,7 +28,8 @@ namespace android {
namespace bluetooth {
namespace audio {

using ::android::hardware::bluetooth::audio::V2_0::SessionType;
using SessionType_2_1 =
    ::android::hardware::bluetooth::audio::V2_1::SessionType;

// Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio
// Session Control. All methods are not thread safe, so users must acquire a
@@ -87,13 +88,13 @@ class BluetoothAudioPortOut {
  void SetState(BluetoothStreamState state);

  bool IsA2dp() const {
    return session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
           session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH;
    return session_type_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
           session_type_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH;
  }

 private:
  BluetoothStreamState state_;
  SessionType session_type_;
  SessionType_2_1 session_type_;
  uint16_t cookie_;
  mutable std::mutex cv_mutex_;
  std::condition_variable internal_cv_;
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ cc_library_static {
    ],
    shared_libs: [
        "android.hardware.bluetooth.audio@2.0",
        "android.hardware.bluetooth.audio@2.1",
        "libfmq",
        "libhidlbase",
    ],
@@ -45,6 +46,7 @@ cc_test {
    ],
    shared_libs: [
        "android.hardware.bluetooth.audio@2.0",
        "android.hardware.bluetooth.audio@2.1",
        "libcutils",
        "libfmq",
        "libhidlbase",
+15 −42
Original line number Diff line number Diff line
@@ -17,13 +17,11 @@
#define LOG_TAG "BTAudioClientIf"

#include "client_interface.h"
#include "hal_version_manager.h"

#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <base/logging.h>
#include <hidl/MQDescriptor.h>
#include <hidl/ServiceManagement.h>
#include <future>

#include "osi/include/log.h"
@@ -36,15 +34,15 @@ using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::audio::common::V5_0::SourceMetadata;
using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
using ::android::hardware::bluetooth::audio::V2_0::
    IBluetoothAudioProvidersFactory;

using DataMQ = ::android::hardware::MessageQueue<
    uint8_t, ::android::hardware::kSynchronizedReadWrite>;

static constexpr int kDefaultDataReadTimeoutMs = 10;      // 10 ms
static constexpr int kDefaultDataReadPollIntervalMs = 1;  // non-blocking poll
static constexpr char kFullyQualifiedInterfaceName[] =
    "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory";

std::unique_ptr<HalVersionManager> HalVersionManager::instance_ptr =
    std::unique_ptr<HalVersionManager>(new HalVersionManager());

std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) {
  switch (ack) {
@@ -191,7 +189,8 @@ BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransport
                                                             bluetooth::common::MessageLoopThread* message_loop)
    : sink_(sink), provider_(nullptr), session_started_(false), mDataMQ(nullptr),
      death_recipient_(new BluetoothAudioDeathRecipient(this, message_loop)) {
  if (IsSupported()) {
  if (HalVersionManager::GetHalVersion() !=
      BluetoothAudioHalVersion::VERSION_UNAVAILABLE) {
    FetchAudioProvider();
  } else {
    LOG(WARNING) << "IBluetoothAudioProvidersFactory not declared";
@@ -212,39 +211,17 @@ BluetoothAudioClientInterface::GetAudioCapabilities() const {
  return capabilities_;
}

bool BluetoothAudioClientInterface::IsSupported() {
  auto service_manager = android::hardware::defaultServiceManager1_2();
  CHECK(service_manager != nullptr);
  size_t instance_count = 0;
  auto listManifestByInterface_cb =
      [&instance_count](
          const hidl_vec<android::hardware::hidl_string>& instanceNames) {
        instance_count = instanceNames.size();
        LOG(INFO) << "listManifestByInterface_cb returns " << instance_count
                  << " instance(s)";
      };
  auto hidl_retval = service_manager->listManifestByInterface(
      kFullyQualifiedInterfaceName, listManifestByInterface_cb);
  if (!hidl_retval.isOk()) {
    LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: "
               << hidl_retval.description();
    return false;
  }
  return (instance_count > 0);
}

std::vector<AudioCapabilities>
BluetoothAudioClientInterface::GetAudioCapabilities(SessionType session_type) {
  std::vector<AudioCapabilities> capabilities(0);
  if (!IsSupported()) return capabilities;
  if (HalVersionManager::GetHalVersion() ==
      BluetoothAudioHalVersion::VERSION_UNAVAILABLE) {
    return capabilities;
  }

  android::sp<IBluetoothAudioProvidersFactory> providersFactory =
      IBluetoothAudioProvidersFactory::getService();
  CHECK(providersFactory != nullptr)
      << "IBluetoothAudioProvidersFactory::getService() failed";
  LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned "
            << providersFactory.get()
            << (providersFactory->isRemote() ? " (remote)" : " (local)");
  android::sp<IBluetoothAudioProvidersFactory_2_0> providersFactory =
      HalVersionManager::GetProviderFactory_2_0();

  auto getProviderCapabilities_cb =
      [&capabilities](const hidl_vec<AudioCapabilities>& audioCapabilities) {
@@ -267,12 +244,8 @@ void BluetoothAudioClientInterface::FetchAudioProvider() {
    LOG(WARNING) << __func__ << ": reflash";
  }

  android::sp<IBluetoothAudioProvidersFactory> providersFactory =
      IBluetoothAudioProvidersFactory::getService();
  CHECK(providersFactory != nullptr) << "IBluetoothAudioProvidersFactory::getService() failed";
  LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned "
            << providersFactory.get()
            << (providersFactory->isRemote() ? " (remote)" : " (local)");
  android::sp<IBluetoothAudioProvidersFactory_2_0> providersFactory =
      HalVersionManager::GetProviderFactory_2_0();

  auto getProviderCapabilities_cb =
      [& capabilities = this->capabilities_](
Loading