OSDN Git Service

Prevent potential deadlock in Hearing Aids
authorStanley Tng <stng@google.com>
Fri, 16 Nov 2018 19:34:28 +0000 (11:34 -0800)
committerStanley Tng <stng@google.com>
Tue, 20 Nov 2018 22:06:59 +0000 (14:06 -0800)
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

bta/hearing_aid/hearing_aid_audio_source.cc

index 30fe611..1d263f1 100644 (file)
@@ -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)));
-        do_resume_future.wait();
+        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)));
-        do_suspend_future.wait();
+        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;
+        }
+      } 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(HEARING_AID_CTRL_ACK_SUCCESS);
+      hearing_aid_send_ack(ctrl_ack_status);
       break;
 
     case HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG: {