Snap for 6041579 from fa6b70419dcdafca30611176df329f9feee07551 to qt-qpr2-release

Change-Id: I97dea43972bfa6991c4d058627dae718ffec3748
diff --git a/bta/hearing_aid/hearing_aid.cc b/bta/hearing_aid/hearing_aid.cc
index 465e45e..867c628 100644
--- a/bta/hearing_aid/hearing_aid.cc
+++ b/bta/hearing_aid/hearing_aid.cc
@@ -1012,13 +1012,16 @@
     }
   }
 
-  void OnAudioSuspend() {
+  void OnAudioSuspend(const std::function<void()>& stop_audio_ticks) {
+    CHECK(stop_audio_ticks) << "stop_audio_ticks is empty";
+
     if (!audio_running) {
       LOG(WARNING) << __func__ << ": Unexpected audio suspend";
     } else {
       LOG(INFO) << __func__ << ": audio_running=" << audio_running;
     }
     audio_running = false;
+    stop_audio_ticks();
 
     std::vector<uint8_t> stop({CONTROL_POINT_OP_STOP});
     for (auto& device : hearingDevices.devices) {
@@ -1039,23 +1042,33 @@
     }
   }
 
-  void OnAudioResume() {
+  void OnAudioResume(const std::function<void()>& start_audio_ticks) {
+    CHECK(start_audio_ticks) << "start_audio_ticks is empty";
+
     if (audio_running) {
       LOG(ERROR) << __func__ << ": Unexpected Audio Resume";
     } else {
       LOG(INFO) << __func__ << ": audio_running=" << audio_running;
     }
-    audio_running = true;
+
+    for (auto& device : hearingDevices.devices) {
+      if (!device.accepting_audio) continue;
+      audio_running = true;
+      SendStart(&device);
+    }
+
+    if (!audio_running) {
+      LOG(INFO) << __func__ << ": No device (0/" << GetDeviceCount()
+                << ") ready to start";
+      return;
+    }
 
     // TODO: shall we also reset the encoder ?
     encoder_state_release();
     encoder_state_init();
     seq_counter = 0;
 
-    for (auto& device : hearingDevices.devices) {
-      if (!device.accepting_audio) continue;
-      SendStart(&device);
-    }
+    start_audio_ticks();
   }
 
   uint8_t GetOtherSideStreamStatus(HearingDevice* this_side_device) {
@@ -1147,10 +1160,9 @@
     }
 
     if (left == nullptr && right == nullptr) {
-      HearingAidAudioSource::Stop();
-      audio_running = false;
-      encoder_state_release();
-      current_volume = VOLUME_UNKNOWN;
+      LOG(WARNING) << __func__ << ": No more (0/" << GetDeviceCount()
+                   << ") devices ready";
+      DoDisconnectAudioStop();
       return;
     }
 
@@ -1463,8 +1475,17 @@
 
     hearingDevices.Remove(address);
 
-    if (connected)
-      callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
+    if (!connected) {
+      return;
+    }
+
+    callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
+    for (const auto& device : hearingDevices.devices) {
+      if (device.accepting_audio) return;
+    }
+    LOG(INFO) << __func__ << ": No more (0/" << GetDeviceCount()
+              << ") devices ready";
+    DoDisconnectAudioStop();
   }
 
   void OnGattDisconnected(tGATT_STATUS status, uint16_t conn_id,
@@ -1486,7 +1507,16 @@
 
     DoDisconnectCleanUp(hearingDevice);
 
+    // Keep this hearing aid in the list, and allow to reconnect back.
+
     callbacks->OnConnectionState(ConnectionState::DISCONNECTED, remote_bda);
+
+    for (const auto& device : hearingDevices.devices) {
+      if (device.accepting_audio) return;
+    }
+    LOG(INFO) << __func__ << ": No more (0/" << GetDeviceCount()
+              << ") devices ready";
+    DoDisconnectAudioStop();
   }
 
   void DoDisconnectCleanUp(HearingDevice* hearingDevice) {
@@ -1519,6 +1549,13 @@
     hearingDevice->command_acked = false;
   }
 
+  void DoDisconnectAudioStop() {
+    HearingAidAudioSource::Stop();
+    audio_running = false;
+    encoder_state_release();
+    current_volume = VOLUME_UNKNOWN;
+  }
+
   void SetVolume(int8_t volume) override {
     VLOG(2) << __func__ << ": " << +volume;
     current_volume = volume;
@@ -1730,14 +1767,11 @@
   void OnAudioDataReady(const std::vector<uint8_t>& data) override {
     if (instance) instance->OnAudioDataReady(data);
   }
-  void OnAudioSuspend(std::promise<void> do_suspend_promise) override {
-    if (instance) instance->OnAudioSuspend();
-    do_suspend_promise.set_value();
+  void OnAudioSuspend(const std::function<void()>& stop_audio_ticks) override {
+    if (instance) instance->OnAudioSuspend(stop_audio_ticks);
   }
-
-  void OnAudioResume(std::promise<void> do_resume_promise) override {
-    if (instance) instance->OnAudioResume();
-    do_resume_promise.set_value();
+  void OnAudioResume(const std::function<void()>& start_audio_ticks) override {
+    if (instance) instance->OnAudioResume(start_audio_ticks);
   }
 };
 
diff --git a/bta/hearing_aid/hearing_aid_audio_source.cc b/bta/hearing_aid/hearing_aid_audio_source.cc
index 3b92d41..0896e2b 100644
--- a/bta/hearing_aid/hearing_aid_audio_source.cc
+++ b/bta/hearing_aid/hearing_aid_audio_source.cc
@@ -97,12 +97,20 @@
 }
 
 void start_audio_ticks() {
+  if (data_interval_ms != HA_INTERVAL_10_MS &&
+      data_interval_ms != HA_INTERVAL_20_MS) {
+    LOG(FATAL) << " Unsupported data interval: " << data_interval_ms;
+  }
+
   wakelock_acquire();
-  audio_timer.SchedulePeriodic(get_main_thread()->GetWeakPtr(), FROM_HERE, base::Bind(&send_audio_data),
-                               base::TimeDelta::FromMilliseconds(data_interval_ms));
+  audio_timer.SchedulePeriodic(
+      get_main_thread()->GetWeakPtr(), FROM_HERE, base::Bind(&send_audio_data),
+      base::TimeDelta::FromMilliseconds(data_interval_ms));
+  LOG(INFO) << __func__ << ": running with data interval: " << data_interval_ms;
 }
 
 void stop_audio_ticks() {
+  LOG(INFO) << __func__ << ": stopped";
   audio_timer.CancelAndWait();
   wakelock_release();
 }
@@ -121,17 +129,12 @@
       UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO,
                  reinterpret_cast<void*>(0));
 
-      if (data_interval_ms != HA_INTERVAL_10_MS &&
-          data_interval_ms != HA_INTERVAL_20_MS) {
-        LOG(FATAL) << " Unsupported data interval: " << data_interval_ms;
-      }
-
-      start_audio_ticks();
+      do_in_main_thread(FROM_HERE, base::BindOnce(start_audio_ticks));
       break;
     case UIPC_CLOSE_EVT:
       LOG(INFO) << __func__ << ": UIPC_CLOSE_EVT";
       hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
-      stop_audio_ticks();
+      do_in_main_thread(FROM_HERE, base::BindOnce(stop_audio_ticks));
       break;
     default:
       LOG(ERROR) << "Hearing Aid audio data event not recognized:" << event;
@@ -306,65 +309,52 @@
 }
 
 bool hearing_aid_on_resume_req(bool start_media_task) {
-  // hearing_aid_recv_ctrl_data(HEARING_AID_CTRL_CMD_START)
-  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();
-    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;
-      return false;
-    }
-  } else {
+  if (localAudioReceiver == nullptr) {
     LOG(ERROR) << __func__
                << ": HEARING_AID_CTRL_CMD_START: audio receiver not started";
     return false;
   }
-
-  // hearing_aid_data_cb(UIPC_OPEN_EVT): start_media_task
+  bt_status_t status;
   if (start_media_task) {
-    if (data_interval_ms != HA_INTERVAL_10_MS &&
-        data_interval_ms != HA_INTERVAL_20_MS) {
-      LOG(FATAL) << " Unsupported data interval: " << data_interval_ms;
-      data_interval_ms = HA_INTERVAL_10_MS;
-    }
-    start_audio_ticks();
+    status = do_in_main_thread(
+        FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
+                                  base::Unretained(localAudioReceiver),
+                                  start_audio_ticks));
+  } else {
+    auto start_dummy_ticks = []() {
+      LOG(INFO) << "start_audio_ticks: waiting for data path opened";
+    };
+    status = do_in_main_thread(
+        FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
+                                  base::Unretained(localAudioReceiver),
+                                  start_dummy_ticks));
+  }
+  if (status != BT_STATUS_SUCCESS) {
+    LOG(ERROR) << __func__
+               << ": HEARING_AID_CTRL_CMD_START: do_in_main_thread err="
+               << status;
+    return false;
   }
   return true;
 }
 
 bool hearing_aid_on_suspend_req() {
-  // hearing_aid_recv_ctrl_data(HEARING_AID_CTRL_CMD_SUSPEND): stop_media_task
-  stop_audio_ticks();
-  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();
-    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();
-      return true;
-    } else {
-      LOG(ERROR) << __func__
-                 << ": HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err="
-                 << status;
-    }
-  } else {
+  if (localAudioReceiver == nullptr) {
     LOG(ERROR) << __func__
                << ": HEARING_AID_CTRL_CMD_SUSPEND: audio receiver not started";
+    return false;
   }
-  return false;
+  bt_status_t status = do_in_main_thread(
+      FROM_HERE,
+      base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend,
+                     base::Unretained(localAudioReceiver), stop_audio_ticks));
+  if (status != BT_STATUS_SUCCESS) {
+    LOG(ERROR) << __func__
+               << ": HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err="
+               << status;
+    return false;
+  }
+  return true;
 }
 }  // namespace
 
diff --git a/bta/include/bta_hearing_aid_api.h b/bta/include/bta_hearing_aid_api.h
index 9026262..6c4954b 100644
--- a/bta/include/bta_hearing_aid_api.h
+++ b/bta/include/bta_hearing_aid_api.h
@@ -21,7 +21,6 @@
 #include <base/callback_forward.h>
 #include <hardware/bt_hearing_aid.h>
 #include <deque>
-#include <future>
 #include <vector>
 
 constexpr uint16_t HEARINGAID_MAX_NUM_UUIDS = 1;
@@ -39,8 +38,22 @@
  public:
   virtual ~HearingAidAudioReceiver() = default;
   virtual void OnAudioDataReady(const std::vector<uint8_t>& data) = 0;
-  virtual void OnAudioSuspend(std::promise<void> do_suspend_promise) = 0;
-  virtual void OnAudioResume(std::promise<void> do_resume_promise) = 0;
+
+  // API to stop our feeding timer, and notify hearing aid devices that the
+  // streaming would stop, too.
+  //
+  // @param stop_audio_ticks a callable function calls out to stop the media
+  // timer for reading data.
+  virtual void OnAudioSuspend(
+      const std::function<void()>& stop_audio_ticks) = 0;
+
+  // To notify hearing aid devices to be ready for streaming, and start the
+  // media timer to feed the audio data.
+  //
+  // @param start_audio_ticks a callable function calls out to start a periodic
+  // timer for feeding data from the audio HAL.
+  virtual void OnAudioResume(
+      const std::function<void()>& start_audio_ticks) = 0;
 };
 
 // Number of rssi reads to attempt when requested
diff --git a/stack/btm/btm_acl.cc b/stack/btm/btm_acl.cc
index be0c937..6daf2d2 100644
--- a/stack/btm/btm_acl.cc
+++ b/stack/btm/btm_acl.cc
@@ -1085,7 +1085,7 @@
  * Returns          void
  *
  ******************************************************************************/
-void btm_read_remote_ext_features_complete(uint8_t* p) {
+void btm_read_remote_ext_features_complete(uint8_t* p, uint8_t evt_len) {
   tACL_CONN* p_acl_cb;
   uint8_t page_num, max_page;
   uint16_t handle;
@@ -1093,6 +1093,14 @@
 
   BTM_TRACE_DEBUG("btm_read_remote_ext_features_complete");
 
+  if (evt_len < HCI_EXT_FEATURES_SUCCESS_EVT_LEN) {
+    android_errorWriteLog(0x534e4554, "141552859");
+    BTM_TRACE_ERROR(
+        "btm_read_remote_ext_features_complete evt length too short. length=%d",
+        evt_len);
+    return;
+  }
+
   ++p;
   STREAM_TO_UINT16(handle, p);
   STREAM_TO_UINT8(page_num, p);
@@ -1112,6 +1120,19 @@
     return;
   }
 
+  if (page_num > HCI_EXT_FEATURES_PAGE_MAX) {
+    android_errorWriteLog(0x534e4554, "141552859");
+    BTM_TRACE_ERROR("btm_read_remote_ext_features_complete num_page=%d invalid",
+                    page_num);
+    return;
+  }
+
+  if (page_num > max_page) {
+    BTM_TRACE_WARNING(
+        "btm_read_remote_ext_features_complete num_page=%d, max_page=%d "
+        "invalid", page_num, max_page);
+  }
+
   p_acl_cb = &btm_cb.acl_db[acl_idx];
 
   /* Copy the received features page */
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 6b80717..ee1d655 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -119,7 +119,7 @@
 extern tBTM_STATUS btm_remove_acl(const RawAddress& bd_addr,
                                   tBT_TRANSPORT transport);
 extern void btm_read_remote_features_complete(uint8_t* p);
-extern void btm_read_remote_ext_features_complete(uint8_t* p);
+extern void btm_read_remote_ext_features_complete(uint8_t* p, uint8_t evt_len);
 extern void btm_read_remote_ext_features_failed(uint8_t status,
                                                 uint16_t handle);
 extern void btm_read_remote_version_complete(uint8_t* p);
diff --git a/stack/btu/btu_hcif.cc b/stack/btu/btu_hcif.cc
index 4612422..c70448e 100644
--- a/stack/btu/btu_hcif.cc
+++ b/stack/btu/btu_hcif.cc
@@ -75,7 +75,8 @@
 static void btu_hcif_rmt_name_request_comp_evt(uint8_t* p, uint16_t evt_len);
 static void btu_hcif_encryption_change_evt(uint8_t* p);
 static void btu_hcif_read_rmt_features_comp_evt(uint8_t* p);
-static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p);
+static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p,
+                                                    uint8_t evt_len);
 static void btu_hcif_read_rmt_version_comp_evt(uint8_t* p);
 static void btu_hcif_qos_setup_comp_evt(uint8_t* p);
 static void btu_hcif_command_complete_evt(BT_HDR* response, void* context);
@@ -295,7 +296,7 @@
       btu_hcif_read_rmt_features_comp_evt(p);
       break;
     case HCI_READ_RMT_EXT_FEATURES_COMP_EVT:
-      btu_hcif_read_rmt_ext_features_comp_evt(p);
+      btu_hcif_read_rmt_ext_features_comp_evt(p, hci_evt_len);
       break;
     case HCI_READ_RMT_VERSION_COMP_EVT:
       btu_hcif_read_rmt_version_comp_evt(p);
@@ -1211,7 +1212,8 @@
  * Returns          void
  *
  ******************************************************************************/
-static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p) {
+static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p,
+                                                    uint8_t evt_len) {
   uint8_t* p_cur = p;
   uint8_t status;
   uint16_t handle;
@@ -1219,7 +1221,7 @@
   STREAM_TO_UINT8(status, p_cur);
 
   if (status == HCI_SUCCESS)
-    btm_read_remote_ext_features_complete(p);
+    btm_read_remote_ext_features_complete(p, evt_len);
   else {
     STREAM_TO_UINT16(handle, p_cur);
     btm_read_remote_ext_features_failed(status, handle);
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index ef87b5b..b11ea6c 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -1323,6 +1323,8 @@
 
 #define HCI_FEATURE_BYTES_PER_PAGE 8
 
+#define HCI_EXT_FEATURES_SUCCESS_EVT_LEN 13
+
 #define HCI_FEATURES_KNOWN(x) \
   (((x)[0] | (x)[1] | (x)[2] | (x)[3] | (x)[4] | (x)[5] | (x)[6] | (x)[7]) != 0)