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

Commit d736f196 authored by Himanshu Rawat's avatar Himanshu Rawat
Browse files

Route headtracking data to non-audio consumer

Allow registeration of ISO data consumer for headtracking data in LE
audio client.

Test: mmm packages/modules/Bluetooth
Test: Manual | LE audio streaming with device supporting DSA
Bug: 270986119
Bug: 309665975
Change-Id: Ia8f17e57fc9450bdea29709d493c3dd36c749929
parent 03734fbd
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@ class LeAudioHalVerifier {
  static bool SupportsStreamActiveApi();
};

typedef bool(LeAudioIsoDataCallback)(const RawAddress& address,
                                     uint16_t cis_conn_hdl, uint8_t* data,
                                     uint16_t size, uint32_t timestamp);
/* Interface class */
class LeAudioClient {
 public:
@@ -75,6 +78,9 @@ class LeAudioClient {
  virtual bool isOutputPreferenceLeAudio(const RawAddress& address) = 0;
  virtual bool isDuplexPreferenceLeAudio(const RawAddress& address) = 0;
  virtual std::vector<RawAddress> GetGroupDevices(const int group_id) = 0;

  static bool RegisterIsoDataConsumer(LeAudioIsoDataCallback callback);

  static void AddFromStorage(const RawAddress& addr, bool autoconnect,
                             int sink_audio_location, int source_audio_location,
                             int sink_supported_context_types,
+49 −0
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ LeAudioSinkAudioHalClient::Callbacks* audioSourceReceiver;
CigCallbacks* stateMachineHciCallbacks;
LeAudioGroupStateMachine::Callbacks* stateMachineCallbacks;
DeviceGroupsCallbacks* device_group_callbacks;
LeAudioIsoDataCallback* iso_data_callback;

/*
 * Coordinatet Set Identification Profile (CSIP) based on CSIP 1.0
@@ -3436,6 +3437,10 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    if (DsaDataConsume(group, cis_conn_hdl, data, size, timestamp)) {
      return;
    }

    uint16_t left_cis_handle = 0;
    uint16_t right_cis_handle = 0;
    for (auto [cis_handle, audio_location] :
@@ -5769,6 +5774,41 @@ class LeAudioClientImpl : public LeAudioClient {

    le_audio::MetricsCollector::Get()->OnStreamEnded(active_group_id_);
  }

  bool DsaDataConsume(LeAudioDeviceGroup* group, uint16_t cis_conn_hdl,
                      uint8_t* data, uint16_t size, uint32_t timestamp) {
    if (!IS_FLAG_ENABLED(leaudio_dynamic_spatial_audio)) {
      return false;
    }

    if (iso_data_callback == nullptr || !group->dsa_.active ||
        group->dsa_.mode != DsaMode::ISO_SW) {
      return false;
    }

    // Find LE Audio device
    LeAudioDevice* leAudioDevice = group->GetFirstDevice();
    while (leAudioDevice != nullptr) {
      if (leAudioDevice->GetDsaCisHandle() == cis_conn_hdl &&
          leAudioDevice->GetDsaDataPathState() == DataPathState::CONFIGURED) {
        break;
      }
      leAudioDevice = group->GetNextDevice(leAudioDevice);
    }
    if (leAudioDevice == nullptr) {
      LOG_WARN("No LE Audio device found for CIS handle: %d", cis_conn_hdl);
      return false;
    }

    bool consumed = iso_data_callback(leAudioDevice->address_, cis_conn_hdl,
                                      data, size, timestamp);
    if (consumed) {
      return true;
    } else {
      LOG_VERBOSE("ISO data consumer not ready to accept data");
      return false;
    }
  }
};

static void le_audio_health_status_callback(const RawAddress& addr,
@@ -6122,3 +6162,12 @@ void LeAudioClient::Cleanup(void) {
  IsoManager::GetInstance()->Stop();
  le_audio::MetricsCollector::Get()->Flush();
}

bool LeAudioClient::RegisterIsoDataConsumer(LeAudioIsoDataCallback callback) {
  if (!IS_FLAG_ENABLED(leaudio_dynamic_spatial_audio)) {
    return false;
  }

  iso_data_callback = callback;
  return true;
}
+18 −3
Original line number Diff line number Diff line
@@ -356,7 +356,7 @@ void LeAudioDevice::RegisterPACs(
    pac_db->clear();
  }

  dsa_modes_ = {DsaMode::DISABLED};
  dsa_.modes = {DsaMode::DISABLED};

  /* TODO wrap this logging part with debug flag */
  for (const struct types::acs_ac_record& pac : *pac_recs) {
@@ -375,7 +375,7 @@ void LeAudioDevice::RegisterPACs(
      if (pac.codec_id == types::kLeAudioCodecHeadtracking) {
        LOG(INFO) << __func__ << ": Headtracking supported";
        /* Todo: Set DSA modes according to the codec configuration */
        dsa_modes_ = {
        dsa_.modes = {
            DsaMode::DISABLED,
            DsaMode::ISO_SW,
            DsaMode::ISO_HW,
@@ -1024,7 +1024,22 @@ void LeAudioDevice::UpdateDeviceAllowlistFlag(void) {
    }
  }
}
DsaModes LeAudioDevice::GetDsaModes(void) { return dsa_modes_; }

DsaModes LeAudioDevice::GetDsaModes(void) { return dsa_.modes; }

types::DataPathState LeAudioDevice::GetDsaDataPathState(void) {
  return dsa_.state;
}

void LeAudioDevice::SetDsaDataPathState(types::DataPathState state) {
  dsa_.state = state;
}

uint16_t LeAudioDevice::GetDsaCisHandle(void) { return dsa_.cis_handle; }

void LeAudioDevice::SetDsaCisHandle(uint16_t cis_handle) {
  dsa_.cis_handle = cis_handle;
}

/* LeAudioDevices Class methods implementation */
void LeAudioDevices::Add(const RawAddress& address, DeviceConnectState state,
+13 −5
Original line number Diff line number Diff line
@@ -141,8 +141,9 @@ class LeAudioDevice {
        model_name_(""),
        allowlist_flag_(false),
        link_quality_timer(nullptr),
        dsa_state_(types::DataPathState::IDLE),
        dsa_modes_({DsaMode::DISABLED}) {}
        dsa_({{DsaMode::DISABLED},
              types::DataPathState::IDLE,
              GATT_INVALID_CONN_ID}) {}
  ~LeAudioDevice(void);

  void SetConnectionState(DeviceConnectState state);
@@ -251,13 +252,20 @@ class LeAudioDevice {
  void GetDeviceModelName(void);
  void UpdateDeviceAllowlistFlag(void);
  DsaModes GetDsaModes(void);

  types::DataPathState dsa_state_;
  types::DataPathState GetDsaDataPathState(void);
  void SetDsaDataPathState(types::DataPathState state);
  uint16_t GetDsaCisHandle(void);
  void SetDsaCisHandle(uint16_t cis_handle);

 private:
  types::BidirectionalPair<types::AudioContexts> avail_contexts_;
  types::BidirectionalPair<types::AudioContexts> supp_contexts_;
  DsaModes dsa_modes_;
  struct {
    DsaModes modes;
    types::DataPathState state;
    uint16_t cis_handle;
  } dsa_;

  static constexpr char kLeAudioDeviceAllowListProp[] =
      "persist.bluetooth.leaudio.allow_list";

+9 −7
Original line number Diff line number Diff line
@@ -613,9 +613,9 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
      if (group->dsa_.active &&
          (group->dsa_.mode == DsaMode::ISO_SW ||
           group->dsa_.mode == DsaMode::ISO_HW) &&
          leAudioDevice->dsa_state_ == DataPathState::CONFIGURING) {
          leAudioDevice->GetDsaDataPathState() == DataPathState::CONFIGURING) {
        LOG_INFO("Datapath configured for headtracking");
        leAudioDevice->dsa_state_ = DataPathState::CONFIGURED;
        leAudioDevice->SetDsaDataPathState(DataPathState::CONFIGURED);
        return;
      }
    }
@@ -699,9 +699,10 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
      }
    } else if (IS_FLAG_ENABLED(leaudio_dynamic_spatial_audio)) {
      if (group->dsa_.active &&
          leAudioDevice->dsa_state_ == DataPathState::REMOVING) {
          leAudioDevice->GetDsaDataPathState() == DataPathState::REMOVING) {
        LOG_INFO("DSA data path removed");
        leAudioDevice->dsa_state_ = DataPathState::IDLE;
        leAudioDevice->SetDsaDataPathState(DataPathState::IDLE);
        leAudioDevice->SetDsaCisHandle(GATT_INVALID_CONN_ID);
      }
    }

@@ -908,7 +909,8 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
        return;
    }

    leAudioDevice->dsa_state_ = DataPathState::CONFIGURING;
    leAudioDevice->SetDsaDataPathState(DataPathState::CONFIGURING);
    leAudioDevice->SetDsaCisHandle(conn_hdl);

    LOG_VERBOSE(
        "DSA mode supported on this LE Audio device: %s, apply data path: %d",
@@ -1088,10 +1090,10 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
      ases_pair.source->data_path_state = DataPathState::REMOVING;
    } else {
      if (IS_FLAG_ENABLED(leaudio_dynamic_spatial_audio)) {
        if (leAudioDevice->dsa_state_ == DataPathState::CONFIGURED) {
        if (leAudioDevice->GetDsaDataPathState() == DataPathState::CONFIGURED) {
          value |=
              bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput;
          leAudioDevice->dsa_state_ = DataPathState::REMOVING;
          leAudioDevice->SetDsaDataPathState(DataPathState::REMOVING);
        }
      }
    }
Loading