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

Commit b553e858 authored by Cheney Ni's avatar Cheney Ni
Browse files

BluetoothAudioHAL: Supports the A2dpSuspended parameter

When establishing a SCO connection, HFP will use the A2dpSuspended
parameter to inform audio HALs for preventing A2DP playback and SCO
coexistence. Since some Bluetooth headset could not handle both A2DP
streaming and SCO at the same time but became abnormal, usually APPs who
was going to use SCO should first acquire the audio focus to pause the
A2DP playback, and then asked for SCO. Because some APPs did not do so,
we need this change to help preventing such IOPs.

Bug: 138698886
Bug: 144820778
Test: make A2DP and SCO connections manually
Change-Id: Id9a1ad08908b30055e02c12a671fc02537ac7100
parent 1e1766e6
Loading
Loading
Loading
Loading
+24 −4
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@

#include <android-base/logging.h>
#include <errno.h>
#include <hardware/audio.h>
#include <hardware/hardware.h>
#include <log/log.h>
#include <malloc.h>
@@ -28,12 +27,33 @@
#include "stream_apis.h"
#include "utils.h"

using ::android::bluetooth::audio::utils::GetAudioParamString;
using ::android::bluetooth::audio::utils::ParseAudioParams;

static int adev_set_parameters(struct audio_hw_device* dev,
                               const char* kvpairs) {
  LOG(VERBOSE) << __func__ << ": kevpairs=[" << kvpairs << "]";
  std::unordered_map<std::string, std::string> params =
      ParseAudioParams(kvpairs);
  if (params.empty()) return 0;

  LOG(VERBOSE) << __func__ << ": ParamsMap=[" << GetAudioParamString(params)
               << "]";
  if (params.find("A2dpSuspended") == params.end()) {
    return -ENOSYS;
  }

  auto* bluetooth_device = reinterpret_cast<BluetoothAudioDevice*>(dev);
  std::lock_guard<std::mutex> guard(bluetooth_device->mutex_);
  for (auto sout : bluetooth_device->opened_stream_outs_) {
    if (sout->stream_out_.common.set_parameters != nullptr) {
      sout->stream_out_.common.set_parameters(&sout->stream_out_.common,
                                              kvpairs);
    }
  }
  return 0;
}

static char* adev_get_parameters(const struct audio_hw_device* dev,
                                 const char* keys) {
  LOG(VERBOSE) << __func__ << ": keys=[" << keys << "]";
@@ -91,8 +111,8 @@ static int adev_open(const hw_module_t* module, const char* name,
  LOG(VERBOSE) << __func__ << ": name=[" << name << "]";
  if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;

  struct audio_hw_device* adev =
      (struct audio_hw_device*)calloc(1, sizeof(struct audio_hw_device));
  auto bluetooth_audio_device = new BluetoothAudioDevice;
  struct audio_hw_device* adev = &bluetooth_audio_device->audio_device_;
  if (!adev) return -ENOMEM;

  adev->common.tag = HARDWARE_DEVICE_TAG;
+0 −1
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
using ::android::hardware::bluetooth::audio::V2_0::SampleRate;
using ::android::hardware::bluetooth::audio::V2_0::SessionType;
using BluetoothAudioStatus =
    ::android::hardware::bluetooth::audio::V2_0::Status;
using ControlResultCallback = std::function<void(
+8 −1
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ namespace android {
namespace bluetooth {
namespace audio {

using ::android::hardware::bluetooth::audio::V2_0::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
// lock. Note: currently, in stream_apis.cc, if GetState() is only used for
@@ -84,9 +86,14 @@ class BluetoothAudioPortOut {
  // Set the current BluetoothStreamState
  void SetState(BluetoothStreamState state);

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

 private:
  BluetoothStreamState state_;
  ::android::hardware::bluetooth::audio::V2_0::SessionType session_type_;
  SessionType session_type_;
  uint16_t cookie_;
  mutable std::mutex cv_mutex_;
  std::condition_variable internal_cv_;
+12 −1
Original line number Diff line number Diff line
@@ -289,7 +289,8 @@ static int out_set_parameters(struct audio_stream* stream,
              << routing_param->second.c_str() << "'";
  }

  if (params.find("A2dpSuspended") != params.end()) {
  if (params.find("A2dpSuspended") != params.end() &&
      out->bluetooth_output_.IsA2dp()) {
    if (params["A2dpSuspended"] == "true") {
      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
                << " stream param stopped";
@@ -683,6 +684,11 @@ int adev_open_output_stream(struct audio_hw_device* dev,
  out->frames_rendered_ = 0;
  out->frames_presented_ = 0;

  {
    auto* bluetooth_device = reinterpret_cast<BluetoothAudioDevice*>(dev);
    std::lock_guard<std::mutex> guard(bluetooth_device->mutex_);
    bluetooth_device->opened_stream_outs_.push_back(out);
  }
  *stream_out = &out->stream_out_;
  LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() << ", sample_rate=" << out->sample_rate_
            << ", channels=" << StringPrintf("%#x", out->channel_mask_) << ", format=" << out->format_
@@ -695,6 +701,11 @@ void adev_close_output_stream(struct audio_hw_device* dev,
  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
               << ", stopping";
  {
    auto* bluetooth_device = reinterpret_cast<BluetoothAudioDevice*>(dev);
    std::lock_guard<std::mutex> guard(bluetooth_device->mutex_);
    bluetooth_device->opened_stream_outs_.remove(out);
  }
  if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) {
    out->frames_rendered_ = 0;
    out->frames_presented_ = 0;
+11 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <hardware/audio.h>
#include <system/audio.h>
#include <list>

#include "device_port_proxy.h"

@@ -62,6 +63,16 @@ struct BluetoothStreamOut {
  mutable std::mutex mutex_;
};

struct BluetoothAudioDevice {
  // Important: device must be first as an audio_hw_device* may be cast to
  // BluetoothAudioDevice* when the type is implicitly known.
  audio_hw_device audio_device_;
  // protect against device->output and stream_out from being inconsistent
  std::mutex mutex_;
  std::list<BluetoothStreamOut*> opened_stream_outs_ =
      std::list<BluetoothStreamOut*>(0);
};

int adev_open_output_stream(struct audio_hw_device* dev,
                            audio_io_handle_t handle, audio_devices_t devices,
                            audio_output_flags_t flags,