#include <mutex>
#include "btcore/include/module.h"
+#include "btif/include/btif_bqr.h"
#include "btsnoop.h"
#include "buffer_allocator.h"
#include "common/message_loop_thread.h"
#include "common/metrics.h"
+#include "common/once_timer.h"
#include "hci_inject.h"
#include "hci_internals.h"
#include "hcidefs.h"
#define BT_HCI_TIMEOUT_TAG_NUM 1010000
using bluetooth::common::MessageLoopThread;
+using bluetooth::common::OnceTimer;
extern void hci_initialize();
extern void hci_transmit(BT_HDR* packet);
static alarm_t* command_response_timer;
static list_t* commands_pending_response;
static std::recursive_timed_mutex commands_pending_response_mutex;
-static alarm_t* hci_timeout_abort_timer;
+static OnceTimer abort_timer;
// The hand-off point for data going to a higher layer, set by the higher layer
static base::Callback<void(const base::Location&, BT_HDR*)> send_data_upwards;
packet_fragmenter->reassemble_and_dispatch(packet);
}
+void hal_service_died() {
+ if (abort_timer.IsScheduled()) {
+ LOG(ERROR) << "abort_timer is scheduled, wait for timeout";
+ return;
+ }
+ abort();
+}
+
// Module lifecycle functions
static future_t* hci_module_shut_down();
packet_fragmenter->cleanup();
- // Clean up abort timer, if it exists.
- if (hci_timeout_abort_timer != NULL) {
- alarm_free(hci_timeout_abort_timer);
- hci_timeout_abort_timer = NULL;
- }
-
if (hci_firmware_log_fd != INVALID_FD) {
hci_close_firmware_log_file(hci_firmware_log_fd);
hci_firmware_log_fd = INVALID_FD;
}
// Abort. The chip has had time to write any debugging information.
-static void hci_timeout_abort(void* unused_data) {
+static void hci_timeout_abort(void) {
LOG_ERROR(LOG_TAG, "%s restarting the Bluetooth process.", __func__);
hci_close_firmware_log_file(hci_firmware_log_fd);
abort();
}
+static void hci_root_inflamed_abort(uint8_t error_code,
+ uint8_t vendor_error_code) {
+ LOG(FATAL) << __func__ << ": error_code = " << std::to_string(error_code)
+ << ", vendor_error_code = " << std::to_string(vendor_error_code);
+}
+
static void command_timed_out_log_info(void* original_wait_entry) {
LOG_ERROR(LOG_TAG, "%s: %d commands pending response", __func__,
get_num_waiting_commands());
}
// Don't request a firmware dump for multiple hci timeouts
- if (hci_timeout_abort_timer != NULL || hci_firmware_log_fd != INVALID_FD) {
+ if (hci_firmware_log_fd != INVALID_FD) {
return;
}
osi_free(bt_hdr);
LOG_ERROR(LOG_TAG, "%s: Setting a timer to restart.", __func__);
- hci_timeout_abort_timer = alarm_new("hci.hci_timeout_aborter");
- if (!hci_timeout_abort_timer) {
+ // alarm_default_callbacks thread post to hci_thread.
+ if (!abort_timer.Schedule(
+ hci_thread.GetWeakPtr(), FROM_HERE, base::Bind(hci_timeout_abort),
+ base::TimeDelta::FromMilliseconds(COMMAND_TIMEOUT_RESTART_MS))) {
LOG_ERROR(LOG_TAG, "%s unable to create an abort timer.", __func__);
abort();
}
- alarm_set(hci_timeout_abort_timer, COMMAND_TIMEOUT_RESTART_MS,
- hci_timeout_abort, nullptr);
}
// Event/packet receiving functions
}
goto intercepted;
- } else if (event_code == HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT) {
- if (hci_firmware_log_fd == INVALID_FD)
- hci_firmware_log_fd = hci_open_firmware_log_file();
+ } else if (event_code == HCI_VENDOR_SPECIFIC_EVT) {
+ uint8_t sub_event_code;
+ STREAM_TO_UINT8(sub_event_code, stream);
- if (hci_firmware_log_fd != INVALID_FD)
- hci_log_firmware_debug_packet(hci_firmware_log_fd, packet);
+ if (sub_event_code == HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT) {
+ if (hci_firmware_log_fd == INVALID_FD)
+ hci_firmware_log_fd = hci_open_firmware_log_file();
- buffer_allocator->free(packet);
- return true;
+ if (hci_firmware_log_fd != INVALID_FD)
+ hci_log_firmware_debug_packet(hci_firmware_log_fd, packet);
+
+ buffer_allocator->free(packet);
+ return true;
+ } else if (sub_event_code == HCI_VSE_SUBCODE_BQR_SUB_EVT) {
+ uint8_t bqr_report_id;
+ STREAM_TO_UINT8(bqr_report_id, stream);
+
+ if (bqr_report_id ==
+ bluetooth::bqr::QUALITY_REPORT_ID_ROOT_INFLAMMATION &&
+ packet->len >= bluetooth::bqr::kRootInflammationPacketMinSize) {
+ uint8_t error_code;
+ uint8_t vendor_error_code;
+ STREAM_TO_UINT8(error_code, stream);
+ STREAM_TO_UINT8(vendor_error_code, stream);
+ // TODO(ugoyu) Report to bluetooth metrics here
+
+ LOG(ERROR) << __func__
+ << ": Root inflammation event! setting timer to restart.";
+ {
+ // Try to stop hci command and startup timers
+ std::unique_lock<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex, std::defer_lock);
+ if (lock.try_lock_for(std::chrono::milliseconds(
+ COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS))) {
+ if (alarm_is_scheduled(startup_timer)) {
+ alarm_cancel(startup_timer);
+ }
+ if (alarm_is_scheduled(command_response_timer)) {
+ alarm_cancel(command_response_timer);
+ }
+ } else {
+ LOG(ERROR) << __func__ << ": Failed to obtain mutex";
+ }
+ }
+
+ // HwBinder thread post to hci_thread
+ if (!abort_timer.Schedule(hci_thread.GetWeakPtr(), FROM_HERE,
+ base::Bind(hci_root_inflamed_abort,
+ error_code, vendor_error_code),
+ base::TimeDelta::FromMilliseconds(
+ COMMAND_TIMEOUT_RESTART_MS))) {
+ LOG(ERROR) << "Failed to schedule abort_timer!";
+ hci_root_inflamed_abort(error_code, vendor_error_code);
+ }
+ }
+ }
}
return false;