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)