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

Commit 00b6cb93 authored by Stanley Tng's avatar Stanley Tng
Browse files

Prevent potential deadlock in Hearing Aids

Prevent a potential deadlock when calling the main thread but the main
thread is not running.

Bug: 117619792
Test: Manual test to make sure no regression
Change-Id: I6e001533144827b17b88547671765f790ed771bd
parent 340bd680
Loading
Loading
Loading
Loading
+34 −7
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ int sample_rate = -1;
int data_interval_ms = -1;
int num_channels = 2;
alarm_t* audio_timer = nullptr;

HearingAidAudioReceiver* localAudioReceiver;
std::unique_ptr<tUIPC_STATE> uipc_hearing_aid;

@@ -136,27 +135,42 @@ void hearing_aid_recv_ctrl_data() {
  LOG(INFO) << __func__ << " " << audio_ha_hw_dump_ctrl_event(cmd);
  //  a2dp_cmd_pending = cmd;

  tHEARING_AID_CTRL_ACK ctrl_ack_status;

  switch (cmd) {
    case HEARING_AID_CTRL_CMD_CHECK_READY:
      hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
      break;

    case HEARING_AID_CTRL_CMD_START:
      ctrl_ack_status = HEARING_AID_CTRL_ACK_SUCCESS;
      if (localAudioReceiver) {
        // Call OnAudioResume and block till it returns.
        std::promise<void> do_resume_promise;
        std::future<void> do_resume_future = do_resume_promise.get_future();
        do_in_main_thread(
        bt_status_t status = do_in_main_thread(
            FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
                                      base::Unretained(localAudioReceiver),
                                      std::move(do_resume_promise)));
        if (status == BT_STATUS_SUCCESS) {
          do_resume_future.wait();
        } else {
          LOG(ERROR) << __func__
                     << ": HEARING_AID_CTRL_CMD_START: do_in_main_thread err="
                     << status;
          ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
        }
      } else {
        LOG(ERROR)
            << __func__
            << ": HEARING_AID_CTRL_CMD_START: audio receiver not started";
        ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
      }

      // timer is restarted in UIPC_Open
      UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, hearing_aid_data_cb,
                HEARING_AID_DATA_PATH);
      hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
      hearing_aid_send_ack(ctrl_ack_status);
      break;

    case HEARING_AID_CTRL_CMD_STOP:
@@ -164,18 +178,31 @@ void hearing_aid_recv_ctrl_data() {
      break;

    case HEARING_AID_CTRL_CMD_SUSPEND:
      ctrl_ack_status = HEARING_AID_CTRL_ACK_SUCCESS;
      if (audio_timer) alarm_cancel(audio_timer);
      if (localAudioReceiver) {
        // Call OnAudioSuspend and block till it returns.
        std::promise<void> do_suspend_promise;
        std::future<void> do_suspend_future = do_suspend_promise.get_future();
        do_in_main_thread(
        bt_status_t status = do_in_main_thread(
            FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend,
                                      base::Unretained(localAudioReceiver),
                                      std::move(do_suspend_promise)));
        if (status == BT_STATUS_SUCCESS) {
          do_suspend_future.wait();
        } else {
          LOG(ERROR) << __func__
                     << ": HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err="
                     << status;
          ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
        }
      hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
      } else {
        LOG(ERROR)
            << __func__
            << ": HEARING_AID_CTRL_CMD_SUSPEND: audio receiver not started";
        ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
      }
      hearing_aid_send_ack(ctrl_ack_status);
      break;

    case HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG: {