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

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

Make sure the Hearing Aid source is ready before resuming or suspending calls

Those calls to resume / suspend streaming are from the audio's IPC
threads like HwBinder or UIPC, and calls to start / end session are from
the stack main thread. There is timing that those threads may run in
parallel, and trys to change the streaming state when the Hearing Aid
source is not ready. This change checks the source state before resuming
or suspending streaming, and breaks the deadlock between IPC threads and
the stack main thread.

Bug: 132860565
Test: 1. Connected to a Hearing Aids and disable the Bluetooth
      2. Switch the active device manually

Change-Id: I6ae11faab3d530c65f55ffa9b8a9f3cae2bde5f4
parent effb3013
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -174,7 +174,8 @@ class BluetoothAudioDeathRecipient
      // restart the session on the correct thread
      message_loop_->DoInThread(
          FROM_HERE,
          base::BindOnce(&RenewAudioProviderAndSession,
          base::BindOnce(
              &BluetoothAudioClientInterface::RenewAudioProviderAndSession,
              base::Unretained(bluetooth_audio_clientif_)));
    } else {
      LOG(ERROR) << __func__ << ": BluetoothAudioClientInterface corrupted";
@@ -184,12 +185,6 @@ class BluetoothAudioDeathRecipient
 private:
  BluetoothAudioClientInterface* bluetooth_audio_clientif_;
  bluetooth::common::MessageLoopThread* message_loop_;
  static void RenewAudioProviderAndSession(
      BluetoothAudioClientInterface* bluetooth_audio_clientif) {
    if (bluetooth_audio_clientif != nullptr) {
      bluetooth_audio_clientif->RenewAudioProviderAndSession();
    }
  }
};

BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransportInstance* sink,
+5 −5
Original line number Diff line number Diff line
@@ -68,12 +68,12 @@ class HearingAidTransport

  void StopRequest() override {
    LOG(INFO) << __func__;
    stream_cb_.on_suspend_();

    if (stream_cb_.on_suspend_()) {
      // flush
      uint8_t p_buf[AUDIO_STREAM_OUTPUT_BUFFER_SZ * 2];
      ::bluetooth::audio::hearing_aid::read(p_buf, sizeof(p_buf));
    }
  }

  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
                               uint64_t* total_bytes_read,
+13 −7
Original line number Diff line number Diff line
@@ -38,8 +38,8 @@ int sample_rate = -1;
int data_interval_ms = -1;
int num_channels = 2;
bluetooth::common::RepeatingTimer audio_timer;
HearingAidAudioReceiver* localAudioReceiver;
std::unique_ptr<tUIPC_STATE> uipc_hearing_aid;
HearingAidAudioReceiver* localAudioReceiver = nullptr;
std::unique_ptr<tUIPC_STATE> uipc_hearing_aid = nullptr;

struct AudioHalStats {
  size_t media_read_total_underflow_bytes;
@@ -85,8 +85,10 @@ void send_audio_data() {

  std::vector<uint8_t> data(p_buf, p_buf + bytes_read);

  if (localAudioReceiver != nullptr) {
    localAudioReceiver->OnAudioDataReady(data);
  }
}

void hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status) {
  uint8_t ack = status;
@@ -305,7 +307,7 @@ void hearing_aid_ctrl_cb(tUIPC_CH_ID, tUIPC_EVENT event) {

bool hearing_aid_on_resume_req(bool start_media_task) {
  // hearing_aid_recv_ctrl_data(HEARING_AID_CTRL_CMD_START)
  if (localAudioReceiver) {
  if (localAudioReceiver != nullptr) {
    // Call OnAudioResume and block till it returns.
    std::promise<void> do_resume_promise;
    std::future<void> do_resume_future = do_resume_promise.get_future();
@@ -342,7 +344,7 @@ bool hearing_aid_on_resume_req(bool start_media_task) {
bool hearing_aid_on_suspend_req() {
  // hearing_aid_recv_ctrl_data(HEARING_AID_CTRL_CMD_SUSPEND): stop_media_task
  stop_audio_ticks();
  if (localAudioReceiver) {
  if (localAudioReceiver != nullptr) {
    // Call OnAudioSuspend and block till it returns.
    std::promise<void> do_suspend_promise;
    std::future<void> do_suspend_future = do_suspend_promise.get_future();
@@ -369,8 +371,7 @@ bool hearing_aid_on_suspend_req() {
void HearingAidAudioSource::Start(const CodecConfiguration& codecConfiguration,
                                  HearingAidAudioReceiver* audioReceiver,
                                  uint16_t remote_delay_ms) {
  localAudioReceiver = audioReceiver;
  VLOG(2) << "Hearing Aid UIPC Open";
  LOG(INFO) << __func__ << ": Hearing Aid Source Open";

  bit_rate = codecConfiguration.bit_rate;
  sample_rate = codecConfiguration.sample_rate;
@@ -382,9 +383,13 @@ void HearingAidAudioSource::Start(const CodecConfiguration& codecConfiguration,
    bluetooth::audio::hearing_aid::start_session();
    bluetooth::audio::hearing_aid::set_remote_delay(remote_delay_ms);
  }
  localAudioReceiver = audioReceiver;
}

void HearingAidAudioSource::Stop() {
  LOG(INFO) << __func__ << ": Hearing Aid Source Close";

  localAudioReceiver = nullptr;
  if (bluetooth::audio::hearing_aid::is_hal_2_0_enabled()) {
    bluetooth::audio::hearing_aid::end_session();
  }
@@ -409,6 +414,7 @@ void HearingAidAudioSource::CleanUp() {
    bluetooth::audio::hearing_aid::cleanup();
  } else {
    UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_ALL);
    uipc_hearing_aid = nullptr;
  }
}