From 63d2fa3e785424d537b1a8cfe8bcb2c0026725ef Mon Sep 17 00:00:00 2001 From: Jack He <siyuanh@google.com> Date: Wed, 25 Jul 2018 21:43:01 -0700 Subject: [PATCH] Use MessageLoopThread in A2DP source, JNI, BTA, HCI and module bring-up * Replace OSI thread with MessageLoopThread in - btif_a2dp_source (A2DP encoding thread) - btif_core (JNI thread) - btu_init (BTA thread) - hci_layer (HCI thread) - module (module bring up thread) - various unit test threads * Code that uses reactor from OSI thread is not replaced in this change because they need to move from using reactor to message loop first * Main difference: - HCI layer no longer has access to mutex protecting message loop set up and tear down. Messages posted to thread after ShutDown() is called become no-op - In all cases QuitClosure() is used instead of QuitWhenIdleClosure(). This means that we will never force kill a thread. An infinite loop will delay the shutdown of Bluetooth stack. * do_in_hci_thread is actually do_in_bta_thread * Move the definition of do_in_bta_thread from bta to btu since btu is where the thread actually lives * Remove bta_closure_api.h and replace it with stack/include/btu.h * Remove header inclusion in bta_sys.h and include stack/include/btu.h in individual compilation units * Fixed a bug in btif_cleanup_bluetooth where btif_jni_disassociate() was not called on the JNI thread * Make setting real time priority a requirement * Crash during the following scenario: - When btif_profile_queue cleanup failed to be scheduled on JNI thread - When A2DP encoder thread failed to gain real time priority - When BTA thread failed to start up - When BTA thread failed to gain real time priority - When BTA thread failed to schedule its first callback * Turn off Bluetooth in the following scenario: - When HCI thread failed to gain real time priority - When bt_workqueue thread failed to gain real time priority Bug: 110303473 Test: make, native and Java unit tests, Connect to headset and listen to music through A2DP, testplans/details/184455/3975 Change-Id: Ib448992fc0ba5af82c2d117dd65f1abd45d2acb6 --- system/bta/ag/bta_ag_api.cc | 1 + system/bta/ag/bta_ag_rfc.cc | 1 + system/bta/ag/bta_ag_sco.cc | 1 + system/bta/ag/bta_ag_sdp.cc | 1 + system/bta/dm/bta_dm_api.cc | 2 +- system/bta/dm/bta_dm_ci.cc | 3 +- system/bta/dm/bta_dm_pm.cc | 1 + system/bta/gatt/bta_gattc_act.cc | 2 +- system/bta/gatt/bta_gattc_api.cc | 2 +- system/bta/gatt/bta_gatts_api.cc | 2 +- system/bta/include/bta_closure_api.h | 38 ------ system/bta/jv/bta_jv_api.cc | 2 +- system/bta/sys/bta_sys.h | 2 - system/bta/sys/bta_sys_main.cc | 36 ------ system/btcore/include/module.h | 7 +- system/btcore/src/module.cc | 75 +++++------ system/btif/Android.bp | 1 + system/btif/avrcp/avrcp_service.cc | 2 +- system/btif/include/btif_common.h | 4 +- system/btif/src/btif_a2dp_audio_interface.cc | 1 + system/btif/src/btif_a2dp_source.cc | 104 ++------------- system/btif/src/btif_av.cc | 1 - system/btif/src/btif_ble_advertiser.cc | 2 +- system/btif/src/btif_ble_scanner.cc | 2 +- system/btif/src/btif_core.cc | 126 +++++-------------- system/btif/src/btif_dm.cc | 1 - system/btif/src/btif_gatt_client.cc | 2 +- system/btif/src/btif_gatt_server.cc | 2 +- system/btif/src/btif_hearing_aid.cc | 2 +- system/btif/src/btif_pan.cc | 2 +- system/btif/src/btif_profile_queue.cc | 3 +- system/btif/src/btif_storage.cc | 1 - system/btif/src/stack_manager.cc | 55 ++++---- system/btif/test/btif_profile_queue_test.cc | 4 +- system/hci/src/hci_layer.cc | 85 ++++--------- system/main/Android.bp | 1 + system/main/bte_main.cc | 1 - system/osi/Android.bp | 1 + system/osi/test/alarm_test.cc | 36 ++---- system/osi/test/future_test.cc | 11 +- system/osi/test/semaphore_test.cc | 14 ++- system/stack/Android.bp | 2 + system/stack/btm/btm_devctl.cc | 8 +- system/stack/btu/btu_hcif.cc | 20 +-- system/stack/btu/btu_init.cc | 59 ++++----- system/stack/btu/btu_task.cc | 57 ++++----- system/stack/include/btu.h | 3 + system/stack/test/stack_btu_test.cc | 15 +-- 48 files changed, 246 insertions(+), 558 deletions(-) delete mode 100644 system/bta/include/bta_closure_api.h diff --git a/system/bta/ag/bta_ag_api.cc b/system/bta/ag/bta_ag_api.cc index 7497fa75fb3..7bd475283ce 100644 --- a/system/bta/ag/bta_ag_api.cc +++ b/system/bta/ag/bta_ag_api.cc @@ -31,6 +31,7 @@ #include "bta_ag_int.h" #include "bta_api.h" #include "bta_sys.h" +#include "stack/include/btu.h" /***************************************************************************** * Constants diff --git a/system/bta/ag/bta_ag_rfc.cc b/system/bta/ag/bta_ag_rfc.cc index ba9bd7fbdf7..14f11169a03 100644 --- a/system/bta/ag/bta_ag_rfc.cc +++ b/system/bta/ag/bta_ag_rfc.cc @@ -34,6 +34,7 @@ #include "osi/include/osi.h" #include "port_api.h" #include "rfcdefs.h" +#include "stack/include/btu.h" #include "utl.h" /* Event mask for RfCOMM port callback */ diff --git a/system/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index 1ff4c7eed93..8e51e874593 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -32,6 +32,7 @@ #include "device/include/controller.h" #include "device/include/esco_parameters.h" #include "osi/include/osi.h" +#include "stack/include/btu.h" #include "utl.h" /* Codec negotiation timeout */ diff --git a/system/bta/ag/bta_ag_sdp.cc b/system/bta/ag/bta_ag_sdp.cc index 8ff39fd78f5..2ae56a2bdc9 100644 --- a/system/bta/ag/bta_ag_sdp.cc +++ b/system/bta/ag/bta_ag_sdp.cc @@ -36,6 +36,7 @@ #include "btm_api.h" #include "osi/include/osi.h" #include "sdp_api.h" +#include "stack/include/btu.h" #include "utl.h" using bluetooth::Uuid; diff --git a/system/bta/dm/bta_dm_api.cc b/system/bta/dm/bta_dm_api.cc index 0740da0d2b5..b3e3a46f74e 100644 --- a/system/bta/dm/bta_dm_api.cc +++ b/system/bta/dm/bta_dm_api.cc @@ -26,13 +26,13 @@ #include "bt_common.h" #include "bta_api.h" -#include "bta_closure_api.h" #include "bta_dm_int.h" #include "bta_sys.h" #include "bta_sys_int.h" #include "btm_api.h" #include "btm_int.h" #include "osi/include/osi.h" +#include "stack/include/btu.h" #include "utl.h" using bluetooth::Uuid; diff --git a/system/bta/dm/bta_dm_ci.cc b/system/bta/dm/bta_dm_ci.cc index 16174c0ad2d..968c3d59eb9 100644 --- a/system/bta/dm/bta_dm_ci.cc +++ b/system/bta/dm/bta_dm_ci.cc @@ -21,11 +21,12 @@ * This is the API implementation file for the BTA device manager. * ******************************************************************************/ +#include "bta_dm_ci.h" #include "bt_common.h" #include "bta_api.h" -#include "bta_dm_ci.h" #include "bta_dm_int.h" #include "bta_sys.h" +#include "stack/include/btu.h" #include <base/bind.h> #include <memory> diff --git a/system/bta/dm/bta_dm_pm.cc b/system/bta/dm/bta_dm_pm.cc index 731d2531202..03b1801a197 100644 --- a/system/bta/dm/bta_dm_pm.cc +++ b/system/bta/dm/bta_dm_pm.cc @@ -35,6 +35,7 @@ #include "bta_dm_int.h" #include "bta_sys.h" #include "btm_api.h" +#include "stack/include/btu.h" static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id, uint8_t app_id, const RawAddress& peer_addr); diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index cb9d1586a59..d49cd7f1634 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -30,13 +30,13 @@ #include <base/callback.h> #include "bt_common.h" #include "bt_target.h" -#include "bta_closure_api.h" #include "bta_gattc_int.h" #include "bta_sys.h" #include "btif/include/btif_debug_conn.h" #include "l2c_api.h" #include "osi/include/log.h" #include "osi/include/osi.h" +#include "stack/include/btu.h" #include "stack/l2cap/l2c_int.h" #include "utl.h" diff --git a/system/bta/gatt/bta_gattc_api.cc b/system/bta/gatt/bta_gattc_api.cc index c60d2993e81..eac97696ff8 100644 --- a/system/bta/gatt/bta_gattc_api.cc +++ b/system/bta/gatt/bta_gattc_api.cc @@ -30,11 +30,11 @@ #include <base/bind_helpers.h> #include <base/callback.h> #include "bt_common.h" -#include "bta_closure_api.h" #include "bta_gatt_api.h" #include "bta_gattc_int.h" #include "bta_sys.h" #include "device/include/controller.h" +#include "stack/include/btu.h" using bluetooth::Uuid; diff --git a/system/bta/gatt/bta_gatts_api.cc b/system/bta/gatt/bta_gatts_api.cc index 9d7cda0d6e2..67e65e15932 100644 --- a/system/bta/gatt/bta_gatts_api.cc +++ b/system/bta/gatt/bta_gatts_api.cc @@ -28,10 +28,10 @@ #include <string.h> #include "bt_common.h" -#include "bta_closure_api.h" #include "bta_gatt_api.h" #include "bta_gatts_int.h" #include "bta_sys.h" +#include "stack/include/btu.h" /***************************************************************************** * Constants diff --git a/system/bta/include/bta_closure_api.h b/system/bta/include/bta_closure_api.h deleted file mode 100644 index a4c0188cf1e..00000000000 --- a/system/bta/include/bta_closure_api.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * - * Copyright 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#ifndef BTA_CLOSURE_API_H -#define BTA_CLOSURE_API_H - -#include <base/bind.h> -#include <base/callback_forward.h> -#include <base/location.h> - -#include <hardware/bluetooth.h> - -/* - * This method post a closure for execution on bta thread. Please see - * documentation at - * https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures - * for how to handle dynamic memory ownership/smart pointers with base::Owned(), - * base::Passed(), base::ConstRef() and others. - */ -bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here, - const base::Closure& task); - -#endif /* BTA_CLOSURE_API_H */ diff --git a/system/bta/jv/bta_jv_api.cc b/system/bta/jv/bta_jv_api.cc index 74818b6a981..40165864008 100644 --- a/system/bta/jv/bta_jv_api.cc +++ b/system/bta/jv/bta_jv_api.cc @@ -29,13 +29,13 @@ #include "bt_common.h" #include "bta_api.h" -#include "bta_closure_api.h" #include "bta_jv_api.h" #include "bta_jv_int.h" #include "bta_sys.h" #include "gap_api.h" #include "port_api.h" #include "sdp_api.h" +#include "stack/include/btu.h" #include "utl.h" using base::Bind; diff --git a/system/bta/sys/bta_sys.h b/system/bta/sys/bta_sys.h index a72f34b0950..ff1d0626570 100644 --- a/system/bta/sys/bta_sys.h +++ b/system/bta/sys/bta_sys.h @@ -31,8 +31,6 @@ #include <base/logging.h> #include <base/threading/thread.h> -#include "bta/include/bta_closure_api.h" - /***************************************************************************** * Constants and data types ****************************************************************************/ diff --git a/system/bta/sys/bta_sys_main.cc b/system/bta/sys/bta_sys_main.cc index bdedcde78dd..7088214432f 100644 --- a/system/bta/sys/bta_sys_main.cc +++ b/system/bta/sys/bta_sys_main.cc @@ -26,8 +26,6 @@ #include <base/bind.h> #include <base/logging.h> -#include <base/threading/thread.h> -#include <pthread.h> #include <string.h> #include "bt_common.h" @@ -40,7 +38,6 @@ #include "osi/include/fixed_queue.h" #include "osi/include/log.h" #include "osi/include/osi.h" -#include "osi/include/thread.h" #include "utl.h" #if (defined BTA_AR_INCLUDED) && (BTA_AR_INCLUDED == TRUE) @@ -50,8 +47,6 @@ /* system manager control block definition */ tBTA_SYS_CB bta_sys_cb; -extern thread_t* bt_workqueue_thread; - /* trace level */ /* TODO Hard-coded trace levels - Needs to be configurable */ uint8_t appl_trace_level = BT_TRACE_LEVEL_WARNING; // APPL_INITIAL_TRACE_LEVEL; @@ -541,37 +536,6 @@ void bta_sys_sendmsg(void* p_msg) { FROM_HERE, base::Bind(&bta_sys_event, static_cast<BT_HDR*>(p_msg))); } -/******************************************************************************* - * - * Function do_in_bta_thread - * - * Description Post a closure to be ran in the bta thread - * - * Returns BT_STATUS_SUCCESS on success - * - ******************************************************************************/ -bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here, - const base::Closure& task) { - base::MessageLoop* bta_message_loop = get_message_loop(); - if (!bta_message_loop) { - APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__); - return BT_STATUS_FAIL; - } - - scoped_refptr<base::SingleThreadTaskRunner> task_runner = - bta_message_loop->task_runner(); - if (!task_runner.get()) { - APPL_TRACE_ERROR("%s: task runner is dead", __func__); - return BT_STATUS_FAIL; - } - - if (!task_runner->PostTask(from_here, task)) { - APPL_TRACE_ERROR("%s: Post task to task runner failed!", __func__); - return BT_STATUS_FAIL; - } - return BT_STATUS_SUCCESS; -} - /******************************************************************************* * * Function bta_sys_start_timer diff --git a/system/btcore/include/module.h b/system/btcore/include/module.h index 949d1473359..ca1d8b41f99 100644 --- a/system/btcore/include/module.h +++ b/system/btcore/include/module.h @@ -20,6 +20,7 @@ #include <stdbool.h> +#include "common/message_loop_thread.h" #include "osi/include/future.h" #include "osi/include/thread.h" @@ -63,6 +64,6 @@ void module_clean_up(const module_t* module); // has finished, |callback| is called within the context of |callback_thread| // with |FUTURE_SUCCESS| or |FUTURE_FAIL| depending on whether startup succeeded // or not. -void module_start_up_callbacked_wrapper(const module_t* module, - thread_t* callback_thread, - thread_fn callback); +void module_start_up_callbacked_wrapper( + const module_t* module, + bluetooth::common::MessageLoopThread* callback_thread, thread_fn callback); diff --git a/system/btcore/src/module.cc b/system/btcore/src/module.cc index 88d4f80f25c..8f8e5f06976 100644 --- a/system/btcore/src/module.cc +++ b/system/btcore/src/module.cc @@ -26,10 +26,13 @@ #include <unordered_map> #include "btcore/include/module.h" +#include "common/message_loop_thread.h" #include "osi/include/allocator.h" #include "osi/include/log.h" #include "osi/include/osi.h" +using bluetooth::common::MessageLoopThread; + typedef enum { MODULE_STATE_NONE = 0, MODULE_STATE_INITIALIZED = 1, @@ -159,55 +162,45 @@ static void set_module_state(const module_t* module, module_state_t state) { // TODO(zachoverflow): remove when everything modulized // Temporary callback-wrapper-related code - -typedef struct { +class CallbackWrapper { + public: + explicit CallbackWrapper(const module_t* module, + MessageLoopThread* callback_thread, + thread_fn callback) + : module(module), + lifecycle_thread("module_wrapper"), + callback_thread(callback_thread), + callback(callback), + success(false) {} const module_t* module; - thread_t* lifecycle_thread; - thread_t* callback_thread; // we don't own this thread + MessageLoopThread lifecycle_thread; + // we don't own this thread + MessageLoopThread* callback_thread; thread_fn callback; bool success; -} callbacked_wrapper_t; - -static void run_wrapped_start_up(void* context); -static void post_result_to_callback(void* context); +}; -void module_start_up_callbacked_wrapper(const module_t* module, - thread_t* callback_thread, - thread_fn callback) { - callbacked_wrapper_t* wrapper = - (callbacked_wrapper_t*)osi_calloc(sizeof(callbacked_wrapper_t)); - - wrapper->module = module; - wrapper->lifecycle_thread = thread_new("module_wrapper"); - wrapper->callback_thread = callback_thread; - wrapper->callback = callback; - - // Run the actual module start up - thread_post(wrapper->lifecycle_thread, run_wrapped_start_up, wrapper); +static void post_result_to_callback(std::shared_ptr<CallbackWrapper> wrapper) { + CHECK(wrapper); + wrapper->lifecycle_thread.ShutDown(); + wrapper->callback(wrapper->success ? FUTURE_SUCCESS : FUTURE_FAIL); } -static void run_wrapped_start_up(void* context) { - CHECK(context); - - callbacked_wrapper_t* wrapper = (callbacked_wrapper_t*)context; +static void run_wrapped_start_up(std::shared_ptr<CallbackWrapper> wrapper) { + CHECK(wrapper); wrapper->success = module_start_up(wrapper->module); - // Post the result back to the callback - thread_post(wrapper->callback_thread, post_result_to_callback, wrapper); + wrapper->callback_thread->DoInThread( + FROM_HERE, base::BindOnce(post_result_to_callback, wrapper)); } -static void post_result_to_callback(void* context) { - CHECK(context); - - callbacked_wrapper_t* wrapper = (callbacked_wrapper_t*)context; - - // Save the values we need for callback - void* result = wrapper->success ? FUTURE_SUCCESS : FUTURE_FAIL; - thread_fn callback = wrapper->callback; - - // Clean up the resources we used - thread_free(wrapper->lifecycle_thread); - osi_free(wrapper); - - callback(result); +void module_start_up_callbacked_wrapper(const module_t* module, + MessageLoopThread* callback_thread, + thread_fn callback) { + std::shared_ptr<CallbackWrapper> wrapper = + std::make_shared<CallbackWrapper>(module, callback_thread, callback); + wrapper->lifecycle_thread.StartUp(); + // Run the actual module start up + wrapper->lifecycle_thread.DoInThread( + FROM_HERE, base::BindOnce(run_wrapped_start_up, wrapper)); } diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 3af4a7aa6d0..5887463a345 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -131,6 +131,7 @@ cc_test { static_libs: [ "libbt-bta", "libbtcore", + "libbt-common", "libbt-stack", "libbt-sbc-encoder", "libbt-utils", diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc index 186866b78d3..e30ff647d31 100644 --- a/system/btif/avrcp/avrcp_service.cc +++ b/system/btif/avrcp/avrcp_service.cc @@ -23,10 +23,10 @@ #include <mutex> #include <sstream> -#include "bta_closure_api.h" #include "btif_av.h" #include "btif_common.h" #include "device.h" +#include "stack/include/btu.h" namespace bluetooth { namespace avrcp { diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h index af0beb0c584..9ceaac68890 100644 --- a/system/btif/include/btif_common.h +++ b/system/btif/include/btif_common.h @@ -174,9 +174,9 @@ typedef struct { * Functions ******************************************************************************/ -extern bt_status_t do_in_jni_thread(const base::Closure& task); +extern bt_status_t do_in_jni_thread(base::OnceClosure task); extern bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here, - const base::Closure& task); + base::OnceClosure task); extern bool is_on_jni_thread(); extern base::MessageLoop* get_jni_message_loop(); /** diff --git a/system/btif/src/btif_a2dp_audio_interface.cc b/system/btif/src/btif_a2dp_audio_interface.cc index 944318e8a3f..ff0312993f0 100644 --- a/system/btif/src/btif_a2dp_audio_interface.cc +++ b/system/btif/src/btif_a2dp_audio_interface.cc @@ -42,6 +42,7 @@ #include "btif_hf.h" #include "osi/include/metrics.h" #include "osi/include/osi.h" +#include "stack/include/btu.h" using system_bt_osi::A2dpSessionMetrics; using system_bt_osi::BluetoothMetricsLogger; diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index efd842b7f9e..a385c6a5314 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -39,17 +39,14 @@ #include "btif_av.h" #include "btif_av_co.h" #include "btif_util.h" +#include "common/message_loop_thread.h" #include "osi/include/fixed_queue.h" #include "osi/include/log.h" #include "osi/include/metrics.h" #include "osi/include/osi.h" -#include "osi/include/thread.h" #include "osi/include/time.h" #include "uipc.h" -#include <condition_variable> -#include <mutex> - using system_bt_osi::BluetoothMetricsLogger; using system_bt_osi::A2dpSessionMetrics; @@ -165,95 +162,6 @@ class BtifMediaStats { int codec_index = -1; }; -class BtWorkerThread { - public: - BtWorkerThread(const std::string& thread_name) - : thread_name_(thread_name), - message_loop_(nullptr), - run_loop_(nullptr), - message_loop_thread_(nullptr), - started_(false) {} - - void StartUp() { - if (message_loop_thread_ != nullptr) { - return; // Already started up - } - message_loop_thread_ = thread_new(thread_name_.c_str()); - CHECK(message_loop_thread_ != nullptr); - started_ = false; - thread_post(message_loop_thread_, &BtWorkerThread::RunThread, this); - { - // Block until run_loop_ is allocated and ready to run - std::unique_lock<std::mutex> start_lock(start_up_mutex_); - while (!started_) { - start_up_cv_.wait(start_lock); - } - } - } - - bool DoInThread(const tracked_objects::Location& from_here, - const base::Closure& task) { - if ((message_loop_ == nullptr) || !message_loop_->task_runner().get()) { - LOG_ERROR( - LOG_TAG, - "%s: Dropping message for thread %s: message loop is not initialized", - __func__, thread_name_.c_str()); - return false; - } - if (!message_loop_->task_runner()->PostTask(from_here, task)) { - LOG_ERROR(LOG_TAG, - "%s: Posting task to message loop for thread %s failed", - __func__, thread_name_.c_str()); - return false; - } - return true; - } - - void ShutDown() { - if ((run_loop_ != nullptr) && (message_loop_ != nullptr)) { - message_loop_->task_runner()->PostTask(FROM_HERE, - run_loop_->QuitClosure()); - } - thread_free(message_loop_thread_); - message_loop_thread_ = nullptr; - } - - private: - static void RunThread(void* context) { - auto wt = static_cast<BtWorkerThread*>(context); - wt->Run(); - } - - void Run() { - LOG_INFO(LOG_TAG, "%s: message loop for thread %s started", __func__, - thread_name_.c_str()); - message_loop_ = new base::MessageLoop(); - run_loop_ = new base::RunLoop(); - { - std::unique_lock<std::mutex> start_lock(start_up_mutex_); - started_ = true; - start_up_cv_.notify_all(); - } - // Blocking util ShutDown() is called - run_loop_->Run(); - delete message_loop_; - message_loop_ = nullptr; - delete run_loop_; - run_loop_ = nullptr; - LOG_INFO(LOG_TAG, "%s: message loop for thread %s finished", __func__, - thread_name_.c_str()); - } - - std::string thread_name_; - base::MessageLoop* message_loop_; - base::RunLoop* run_loop_; - thread_t* message_loop_thread_; - // For start-up - bool started_; - std::mutex start_up_mutex_; - std::condition_variable start_up_cv_; -}; - class BtifA2dpSource { public: enum RunState { @@ -312,7 +220,8 @@ class BtifA2dpSource { BtifA2dpSource::RunState state_; }; -static BtWorkerThread btif_a2dp_source_thread("btif_a2dp_source_thread"); +static bluetooth::common::MessageLoopThread btif_a2dp_source_thread( + "btif_a2dp_source_thread"); static BtifA2dpSource btif_a2dp_source_cb; static void btif_a2dp_source_init_delayed(void); @@ -439,11 +348,12 @@ bool btif_a2dp_source_startup(void) { return true; } -static void btif_a2dp_source_startup_delayed(void) { +static void btif_a2dp_source_startup_delayed() { LOG_INFO(LOG_TAG, "%s: state=%s", __func__, btif_a2dp_source_cb.StateStr().c_str()); - - raise_priority_a2dp(TASK_HIGH_MEDIA); + if (!btif_a2dp_source_thread.EnableRealTimeScheduling()) { + LOG(FATAL) << __func__ << ": unable to enable real time scheduling"; + } btif_a2dp_control_init(); btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateRunning); } diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index 8d416c132e2..92abb220b42 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -34,7 +34,6 @@ #include "bt_common.h" #include "bt_utils.h" #include "bta/include/bta_api.h" -#include "bta/include/bta_closure_api.h" #include "btif/include/btif_a2dp_source.h" #include "btif_a2dp.h" #include "btif_a2dp_audio_interface.h" diff --git a/system/btif/src/btif_ble_advertiser.cc b/system/btif/src/btif_ble_advertiser.cc index e24bcde2b53..d11e7337289 100644 --- a/system/btif/src/btif_ble_advertiser.cc +++ b/system/btif/src/btif_ble_advertiser.cc @@ -25,8 +25,8 @@ #include <vector> #include "ble_advertiser.h" -#include "bta_closure_api.h" #include "btif_common.h" +#include "stack/include/btu.h" using base::Bind; using base::Owned; diff --git a/system/btif/src/btif_ble_scanner.cc b/system/btif/src/btif_ble_scanner.cc index 2587c8d8301..493bd1c511d 100644 --- a/system/btif/src/btif_ble_scanner.cc +++ b/system/btif/src/btif_ble_scanner.cc @@ -35,7 +35,6 @@ #include "advertise_data_parser.h" #include "bta_api.h" -#include "bta_closure_api.h" #include "bta_gatt_api.h" #include "btif_config.h" #include "btif_dm.h" @@ -43,6 +42,7 @@ #include "btif_gatt_util.h" #include "btif_storage.h" #include "osi/include/log.h" +#include "stack/include/btu.h" #include "vendor_api.h" using base::Bind; diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc index 9fa4590cd4e..d2d8865d2f5 100644 --- a/system/btif/src/btif_core.cc +++ b/system/btif/src/btif_core.cc @@ -46,7 +46,6 @@ #include "bt_common.h" #include "bt_utils.h" #include "bta_api.h" -#include "bta_closure_api.h" #include "bte.h" #include "btif_api.h" #include "btif_av.h" @@ -58,17 +57,18 @@ #include "btif_uid.h" #include "btif_util.h" #include "btu.h" +#include "common/message_loop_thread.h" #include "device/include/controller.h" #include "osi/include/fixed_queue.h" #include "osi/include/future.h" #include "osi/include/log.h" #include "osi/include/osi.h" #include "osi/include/properties.h" -#include "osi/include/thread.h" #include "stack_manager.h" using base::PlatformThread; using bluetooth::Uuid; +using bluetooth::common::MessageLoopThread; /******************************************************************************* * Constants & Macros @@ -128,12 +128,9 @@ static tBTA_SERVICE_MASK btif_enabled_services = 0; */ static uint8_t btif_dut_mode = 0; -static thread_t* bt_jni_workqueue_thread; -static const char* BT_JNI_WORKQUEUE_NAME = "bt_jni_workqueue"; -static uid_set_t* uid_set = NULL; -base::MessageLoop* message_loop_ = NULL; -base::RunLoop* jni_run_loop = NULL; -static base::PlatformThreadId btif_thread_id_ = -1; +static MessageLoopThread bt_jni_workqueue_thread("bt_jni_workqueue"); +static base::AtExitManager* exit_manager; +static uid_set_t* uid_set; /******************************************************************************* * Static functions @@ -224,35 +221,25 @@ bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event, * the JNI message loop. **/ bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here, - const base::Closure& task) { - if (!message_loop_) { - BTIF_TRACE_WARNING("%s: Dropped message, message_loop not initialized yet!", - __func__); + base::OnceClosure task) { + if (!bt_jni_workqueue_thread.DoInThread(from_here, std::move(task))) { + LOG(ERROR) << __func__ << ": Post task to task runner failed!"; return BT_STATUS_FAIL; } - - scoped_refptr<base::SingleThreadTaskRunner> task_runner = - message_loop_->task_runner(); - if (!task_runner.get()) { - BTIF_TRACE_WARNING("%s: task runner is dead", __func__); - return BT_STATUS_FAIL; - } - - if (task_runner->PostTask(from_here, task)) return BT_STATUS_SUCCESS; - - BTIF_TRACE_ERROR("%s: Post task to task runner failed!", __func__); - return BT_STATUS_FAIL; + return BT_STATUS_SUCCESS; } -bt_status_t do_in_jni_thread(const base::Closure& task) { - return do_in_jni_thread(FROM_HERE, task); +bt_status_t do_in_jni_thread(base::OnceClosure task) { + return do_in_jni_thread(FROM_HERE, std::move(task)); } bool is_on_jni_thread() { - return btif_thread_id_ == PlatformThread::CurrentId(); + return bt_jni_workqueue_thread.GetThreadId() == PlatformThread::CurrentId(); } -base::MessageLoop* get_jni_message_loop() { return message_loop_; } +base::MessageLoop* get_jni_message_loop() { + return bt_jni_workqueue_thread.message_loop(); +} /******************************************************************************* * @@ -260,11 +247,11 @@ base::MessageLoop* get_jni_message_loop() { return message_loop_; } * * Description checks if BTIF is currently in DUT mode * - * Returns 1 if test mode, otherwize 0 + * Returns true if test mode, otherwise false * ******************************************************************************/ -uint8_t btif_is_dut_mode(void) { return (btif_dut_mode == 1); } +bool btif_is_dut_mode() { return btif_dut_mode == 1; } /******************************************************************************* * @@ -327,38 +314,6 @@ void btif_sendmsg(void* p_msg) { do_in_jni_thread(base::Bind(&bt_jni_msg_ready, p_msg)); } -void btif_thread_post(thread_fn func, void* context) { - do_in_jni_thread(base::Bind(func, context)); -} - -void run_message_loop(UNUSED_ATTR void* context) { - LOG_INFO(LOG_TAG, "%s entered", __func__); - btif_thread_id_ = PlatformThread::CurrentId(); - - // TODO(jpawlowski): exit_manager should be defined in main(), but there is no - // main method. - // It is therefore defined in bt_jni_workqueue_thread, and will be deleted - // when we free it. - base::AtExitManager exit_manager; - - message_loop_ = new base::MessageLoop(base::MessageLoop::Type::TYPE_DEFAULT); - - // Associate this workqueue thread with JNI. - message_loop_->task_runner()->PostTask(FROM_HERE, - base::Bind(&btif_jni_associate)); - - jni_run_loop = new base::RunLoop(); - jni_run_loop->Run(); - - delete message_loop_; - message_loop_ = NULL; - - delete jni_run_loop; - jni_run_loop = NULL; - - btif_thread_id_ = -1; - LOG_INFO(LOG_TAG, "%s finished", __func__); -} /******************************************************************************* * * Function btif_init_bluetooth @@ -370,27 +325,12 @@ void run_message_loop(UNUSED_ATTR void* context) { ******************************************************************************/ bt_status_t btif_init_bluetooth() { LOG_INFO(LOG_TAG, "%s entered", __func__); - + exit_manager = new base::AtExitManager(); bte_main_boot_entry(); - - bt_jni_workqueue_thread = thread_new(BT_JNI_WORKQUEUE_NAME); - if (bt_jni_workqueue_thread == NULL) { - LOG_ERROR(LOG_TAG, "%s Unable to create thread %s", __func__, - BT_JNI_WORKQUEUE_NAME); - goto error_exit; - } - - thread_post(bt_jni_workqueue_thread, run_message_loop, nullptr); - + bt_jni_workqueue_thread.StartUp(); + bt_jni_workqueue_thread.DoInThread(FROM_HERE, base::Bind(btif_jni_associate)); LOG_INFO(LOG_TAG, "%s finished", __func__); return BT_STATUS_SUCCESS; - -error_exit:; - thread_free(bt_jni_workqueue_thread); - - bt_jni_workqueue_thread = NULL; - - return BT_STATUS_FAIL; } /******************************************************************************* @@ -475,7 +415,7 @@ void btif_enable_bluetooth_evt(tBTA_STATUS status) { * Returns void * ******************************************************************************/ -bt_status_t btif_disable_bluetooth(void) { +bt_status_t btif_disable_bluetooth() { LOG_INFO(LOG_TAG, "%s entered", __func__); do_in_bta_thread(FROM_HERE, base::Bind(&btm_ble_multi_adv_cleanup)); @@ -505,7 +445,7 @@ bt_status_t btif_disable_bluetooth(void) { * ******************************************************************************/ -void btif_disable_bluetooth_evt(void) { +void btif_disable_bluetooth_evt() { LOG_INFO(LOG_TAG, "%s entered", __func__); bte_main_disable(); @@ -526,29 +466,19 @@ void btif_disable_bluetooth_evt(void) { * ******************************************************************************/ -bt_status_t btif_cleanup_bluetooth(void) { +bt_status_t btif_cleanup_bluetooth() { LOG_INFO(LOG_TAG, "%s entered", __func__); - do_in_bta_thread(FROM_HERE, base::Bind(&BTA_VendorCleanup)); - btif_dm_cleanup(); - btif_jni_disassociate(); + bt_jni_workqueue_thread.DoInThread(FROM_HERE, + base::BindOnce(btif_jni_disassociate)); btif_queue_release(); - - if (jni_run_loop && message_loop_) { - message_loop_->task_runner()->PostTask(FROM_HERE, - jni_run_loop->QuitClosure()); - } - - thread_free(bt_jni_workqueue_thread); - bt_jni_workqueue_thread = NULL; - + bt_jni_workqueue_thread.ShutDown(); bte_main_cleanup(); - + delete exit_manager; + exit_manager = nullptr; btif_dut_mode = 0; - LOG_INFO(LOG_TAG, "%s finished", __func__); - return BT_STATUS_SUCCESS; } diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 91afabfa311..8a8da8514fc 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -47,7 +47,6 @@ #include "advertise_data_parser.h" #include "bt_common.h" -#include "bta_closure_api.h" #include "bta_gatt_api.h" #include "btif_api.h" #include "btif_av.h" diff --git a/system/btif/src/btif_gatt_client.cc b/system/btif/src/btif_gatt_client.cc index 0e06bbb9083..f05e7a046b4 100644 --- a/system/btif/src/btif_gatt_client.cc +++ b/system/btif/src/btif_gatt_client.cc @@ -41,7 +41,6 @@ #include <hardware/bt_gatt.h> #include "bta_api.h" -#include "bta_closure_api.h" #include "bta_gatt_api.h" #include "btif_config.h" #include "btif_dm.h" @@ -49,6 +48,7 @@ #include "btif_gatt_util.h" #include "btif_storage.h" #include "osi/include/log.h" +#include "stack/include/btu.h" #include "vendor_api.h" using base::Bind; diff --git a/system/btif/src/btif_gatt_server.cc b/system/btif/src/btif_gatt_server.cc index b7fdc8c8608..2c10842d28f 100644 --- a/system/btif/src/btif_gatt_server.cc +++ b/system/btif/src/btif_gatt_server.cc @@ -40,7 +40,6 @@ #include "bt_common.h" #include "bta_api.h" -#include "bta_closure_api.h" #include "bta_gatt_api.h" #include "btif_config.h" #include "btif_dm.h" @@ -48,6 +47,7 @@ #include "btif_gatt_util.h" #include "btif_storage.h" #include "osi/include/log.h" +#include "stack/include/btu.h" using base::Bind; using base::Owned; diff --git a/system/btif/src/btif_hearing_aid.cc b/system/btif/src/btif_hearing_aid.cc index 1614a7378e6..7244cf0ad0c 100644 --- a/system/btif/src/btif_hearing_aid.cc +++ b/system/btif/src/btif_hearing_aid.cc @@ -18,10 +18,10 @@ /* Hearing Aid Profile Interface */ -#include "bta_closure_api.h" #include "bta_hearing_aid_api.h" #include "btif_common.h" #include "btif_storage.h" +#include "stack/include/btu.h" #include <base/bind.h> #include <base/location.h> diff --git a/system/btif/src/btif_pan.cc b/system/btif/src/btif_pan.cc index 9828c4bc886..b210989e782 100644 --- a/system/btif/src/btif_pan.cc +++ b/system/btif/src/btif_pan.cc @@ -54,7 +54,6 @@ #include "bt_common.h" #include "bta_api.h" -#include "bta_closure_api.h" #include "bta_pan_api.h" #include "btif_common.h" #include "btif_pan_internal.h" @@ -65,6 +64,7 @@ #include "device/include/controller.h" #include "osi/include/log.h" #include "osi/include/osi.h" +#include "stack/include/btu.h" #define FORWARD_IGNORE 1 #define FORWARD_SUCCESS 0 diff --git a/system/btif/src/btif_profile_queue.cc b/system/btif/src/btif_profile_queue.cc index 10acaded8e5..02d6ddf0cbb 100644 --- a/system/btif/src/btif_profile_queue.cc +++ b/system/btif/src/btif_profile_queue.cc @@ -210,7 +210,6 @@ void btif_queue_release() { LOG_INFO(LOG_TAG, "%s", __func__); if (do_in_jni_thread(FROM_HERE, base::Bind(&queue_int_release)) != BT_STATUS_SUCCESS) { - // Scheduling failed - the thread to schedule on is probably dead - queue_int_release(); + LOG(FATAL) << __func__ << ": Failed to schedule on JNI thread"; } } diff --git a/system/btif/src/btif_storage.cc b/system/btif/src/btif_storage.cc index 826244af3db..22689f53717 100644 --- a/system/btif/src/btif_storage.cc +++ b/system/btif/src/btif_storage.cc @@ -40,7 +40,6 @@ #include <time.h> #include "bt_common.h" -#include "bta_closure_api.h" #include "bta_hd_api.h" #include "bta_hearing_aid_api.h" #include "bta_hh_api.h" diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc index e37db87014b..518f1c50c0b 100644 --- a/system/btif/src/stack_manager.cc +++ b/system/btif/src/stack_manager.cc @@ -26,18 +26,20 @@ #include "btcore/include/osi_module.h" #include "btif_api.h" #include "btif_common.h" +#include "common/message_loop_thread.h" #include "device/include/controller.h" #include "osi/include/log.h" #include "osi/include/osi.h" #include "osi/include/semaphore.h" -#include "osi/include/thread.h" // Temp includes #include "bt_utils.h" #include "btif_config.h" #include "btif_profile_queue.h" -static thread_t* management_thread; +using bluetooth::common::MessageLoopThread; + +static MessageLoopThread management_thread("stack_manager"); // If initialized, any of the bluetooth API functions can be called. // (e.g. turning logging on and off, enabling/disabling the stack, etc) @@ -56,40 +58,44 @@ static void event_signal_stack_down(void* context); // Unvetted includes/imports, etc which should be removed or vetted in the // future static future_t* hack_future; -void btif_thread_post(thread_fn func, void* context); // End unvetted section // Interface functions -static void init_stack(void) { +static void init_stack() { // This is a synchronous process. Post it to the thread though, so // state modification only happens there. Using the thread to perform // all stack operations ensures that the operations are done serially // and do not overlap. semaphore_t* semaphore = semaphore_new(0); - thread_post(management_thread, event_init_stack, semaphore); + management_thread.DoInThread(FROM_HERE, + base::Bind(event_init_stack, semaphore)); semaphore_wait(semaphore); semaphore_free(semaphore); } -static void start_up_stack_async(void) { - thread_post(management_thread, event_start_up_stack, NULL); +static void start_up_stack_async() { + management_thread.DoInThread(FROM_HERE, + base::Bind(event_start_up_stack, nullptr)); } -static void shut_down_stack_async(void) { - thread_post(management_thread, event_shut_down_stack, NULL); +static void shut_down_stack_async() { + management_thread.DoInThread(FROM_HERE, + base::Bind(event_shut_down_stack, nullptr)); } -static void clean_up_stack(void) { +static void clean_up_stack() { // This is a synchronous process. Post it to the thread though, so // state modification only happens there. semaphore_t* semaphore = semaphore_new(0); - thread_post(management_thread, event_clean_up_stack, semaphore); + management_thread.DoInThread(FROM_HERE, + base::Bind(event_clean_up_stack, semaphore)); semaphore_wait(semaphore); semaphore_free(semaphore); + management_thread.ShutDown(); } -static bool get_stack_is_running(void) { return stack_is_running; } +static bool get_stack_is_running() { return stack_is_running; } // Internal functions @@ -119,12 +125,12 @@ static void event_init_stack(void* context) { if (semaphore) semaphore_post(semaphore); } -static void ensure_stack_is_initialized(void) { +static void ensure_stack_is_initialized() { if (!stack_is_initialized) { LOG_WARN(LOG_TAG, "%s found the stack was uninitialized. Initializing now.", __func__); // No semaphore needed since we are calling it directly - event_init_stack(NULL); + event_init_stack(nullptr); } } @@ -148,13 +154,13 @@ static void event_start_up_stack(UNUSED_ATTR void* context) { if (future_await(local_hack_future) != FUTURE_SUCCESS) { LOG_ERROR(LOG_TAG, "%s failed to start up the stack", __func__); stack_is_running = true; // So stack shutdown actually happens - event_shut_down_stack(NULL); + event_shut_down_stack(nullptr); return; } stack_is_running = true; LOG_INFO(LOG_TAG, "%s finished", __func__); - btif_thread_post(event_signal_stack_up, NULL); + do_in_jni_thread(FROM_HERE, base::Bind(event_signal_stack_up, nullptr)); } // Synchronous function to shut down the stack @@ -178,17 +184,17 @@ static void event_shut_down_stack(UNUSED_ATTR void* context) { // state hack_future = future_new(); - btif_thread_post(event_signal_stack_down, NULL); + do_in_jni_thread(FROM_HERE, base::Bind(event_signal_stack_down, nullptr)); future_await(hack_future); LOG_INFO(LOG_TAG, "%s finished", __func__); } -static void ensure_stack_is_not_running(void) { +static void ensure_stack_is_not_running() { if (stack_is_running) { LOG_WARN(LOG_TAG, "%s found the stack was still running. Bringing it down now.", __func__); - event_shut_down_stack(NULL); + event_shut_down_stack(nullptr); } } @@ -228,19 +234,18 @@ static void event_signal_stack_down(UNUSED_ATTR void* context) { future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS); } -static void ensure_manager_initialized(void) { - if (management_thread) return; +static void ensure_manager_initialized() { + if (management_thread.IsRunning()) return; - management_thread = thread_new("stack_manager"); - if (!management_thread) { - LOG_ERROR(LOG_TAG, "%s unable to create stack management thread", __func__); + management_thread.StartUp(); + if (!management_thread.IsRunning()) { + LOG_ERROR(LOG_TAG, "%s unable to start stack management thread", __func__); return; } } static const stack_manager_t interface = {init_stack, start_up_stack_async, shut_down_stack_async, clean_up_stack, - get_stack_is_running}; const stack_manager_t* stack_manager_get_interface() { diff --git a/system/btif/test/btif_profile_queue_test.cc b/system/btif/test/btif_profile_queue_test.cc index f7bce86e332..efa9461d051 100644 --- a/system/btif/test/btif_profile_queue_test.cc +++ b/system/btif/test/btif_profile_queue_test.cc @@ -34,8 +34,8 @@ static stack_manager_t sStackManager = {nullptr, nullptr, nullptr, nullptr, get_stack_is_running}; const stack_manager_t* stack_manager_get_interface() { return &sStackManager; } bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here, - const base::Closure& task) { - task.Run(); + base::OnceClosure task) { + std::move(task).Run(); return BT_STATUS_SUCCESS; } bool is_on_jni_thread() { return true; } diff --git a/system/hci/src/hci_layer.cc b/system/hci/src/hci_layer.cc index f1e0e7a605e..aa012d6af26 100644 --- a/system/hci/src/hci_layer.cc +++ b/system/hci/src/hci_layer.cc @@ -37,6 +37,7 @@ #include "btcore/include/module.h" #include "btsnoop.h" #include "buffer_allocator.h" +#include "common/message_loop_thread.h" #include "hci_inject.h" #include "hci_internals.h" #include "hcidefs.h" @@ -50,6 +51,8 @@ #define BT_HCI_TIMEOUT_TAG_NUM 1010000 +using bluetooth::common::MessageLoopThread; + extern void hci_initialize(); extern void hci_transmit(BT_HDR* packet); extern void hci_close(); @@ -73,9 +76,6 @@ typedef struct { #define DEFAULT_STARTUP_TIMEOUT_MS 8000 #define STRING_VALUE_OF(x) #x -// RT priority for HCI thread -static const int BT_HCI_RT_PRIORITY = 1; - // Abort if there is no response to an HCI command. static const uint32_t COMMAND_PENDING_TIMEOUT_MS = 2000; static const uint32_t COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS = 500; @@ -92,10 +92,7 @@ static const btsnoop_t* btsnoop; static const packet_fragmenter_t* packet_fragmenter; static future_t* startup_future; -static thread_t* thread; // We own this -static std::mutex message_loop_mutex; -static base::MessageLoop* message_loop_ = nullptr; -static base::RunLoop* run_loop_ = nullptr; +static MessageLoopThread thread("hci_thread"); // We own this static alarm_t* startup_timer; @@ -138,9 +135,7 @@ static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = { transmit_fragment, dispatch_reassembled, fragmenter_transmit_finished}; void initialization_complete() { - std::lock_guard<std::mutex> lock(message_loop_mutex); - message_loop_->task_runner()->PostTask( - FROM_HERE, base::Bind(&event_finish_startup, nullptr)); + thread.DoInThread(FROM_HERE, base::Bind(&event_finish_startup, nullptr)); } void hci_event_received(const tracked_objects::Location& from_here, @@ -166,26 +161,6 @@ void sco_data_received(BT_HDR* packet) { static future_t* hci_module_shut_down(); -void message_loop_run(UNUSED_ATTR void* context) { - { - std::lock_guard<std::mutex> lock(message_loop_mutex); - message_loop_ = new base::MessageLoop(); - run_loop_ = new base::RunLoop(); - } - - message_loop_->task_runner()->PostTask(FROM_HERE, - base::Bind(&hci_initialize)); - run_loop_->Run(); - - { - std::lock_guard<std::mutex> lock(message_loop_mutex); - delete message_loop_; - message_loop_ = nullptr; - delete run_loop_; - run_loop_ = nullptr; - } -} - static future_t* hci_module_start_up(void) { LOG_INFO(LOG_TAG, "%s", __func__); @@ -217,13 +192,14 @@ static future_t* hci_module_start_up(void) { goto error; } - thread = thread_new("hci_thread"); - if (!thread) { - LOG_ERROR(LOG_TAG, "%s unable to create thread.", __func__); + thread.StartUp(); + if (!thread.IsRunning()) { + LOG_ERROR(LOG_TAG, "%s unable to start thread.", __func__); goto error; } - if (!thread_set_rt_priority(thread, BT_HCI_RT_PRIORITY)) { + if (!thread.EnableRealTimeScheduling()) { LOG_ERROR(LOG_TAG, "%s unable to make thread RT.", __func__); + goto error; } commands_pending_response = list_new(NULL); @@ -242,7 +218,7 @@ static future_t* hci_module_start_up(void) { packet_fragmenter->init(&packet_fragmenter_callbacks); - thread_post(thread, message_loop_run, NULL); + thread.DoInThread(FROM_HERE, base::Bind(&hci_initialize)); LOG_DEBUG(LOG_TAG, "%s starting async portion", __func__); return local_startup_future; @@ -265,16 +241,7 @@ static future_t* hci_module_shut_down() { startup_timer = NULL; } - { - std::lock_guard<std::mutex> lock(message_loop_mutex); - message_loop_->task_runner()->PostTask(FROM_HERE, run_loop_->QuitClosure()); - } - - // Stop the thread to prevent Send() calls. - if (thread) { - thread_stop(thread); - thread_join(thread); - } + thread.ShutDown(); // Close HCI to prevent callbacks. hci_close(); @@ -288,9 +255,6 @@ static future_t* hci_module_shut_down() { packet_fragmenter->cleanup(); - thread_free(thread); - thread = NULL; - // Clean up abort timer, if it exists. if (hci_timeout_abort_timer != NULL) { alarm_free(hci_timeout_abort_timer); @@ -405,14 +369,12 @@ static void enqueue_command(waiting_command_t* wait_entry) { std::lock_guard<std::mutex> command_credits_lock(command_credits_mutex); if (command_credits > 0) { - std::lock_guard<std::mutex> message_loop_lock(message_loop_mutex); - if (message_loop_ == nullptr) { - // HCI Layer was shut down + if (!thread.DoInThread(FROM_HERE, std::move(callback))) { + // HCI Layer was shut down or not running buffer_allocator->free(wait_entry->command); osi_free(wait_entry); return; } - message_loop_->task_runner()->PostTask(FROM_HERE, std::move(callback)); command_credits--; } else { command_queue.push(std::move(callback)); @@ -434,14 +396,11 @@ static void event_command_ready(waiting_command_t* wait_entry) { } static void enqueue_packet(void* packet) { - std::lock_guard<std::mutex> lock(message_loop_mutex); - if (message_loop_ == nullptr) { - // HCI Layer was shut down + if (!thread.DoInThread(FROM_HERE, base::Bind(&event_packet_ready, packet))) { + // HCI Layer was shut down or not running buffer_allocator->free(packet); return; } - message_loop_->task_runner()->PostTask( - FROM_HERE, base::Bind(&event_packet_ready, packet)); } static void event_packet_ready(void* pkt) { @@ -576,19 +535,19 @@ static void command_timed_out(void* original_wait_entry) { // Event/packet receiving functions void process_command_credits(int credits) { std::lock_guard<std::mutex> command_credits_lock(command_credits_mutex); - std::lock_guard<std::mutex> message_loop_lock(message_loop_mutex); - if (message_loop_ == nullptr) { - // HCI Layer was shut down + if (!thread.IsRunning()) { + // HCI Layer was shut down or not running return; } // Subtract commands in flight. command_credits = credits - get_num_waiting_commands(); - while (command_credits > 0 && command_queue.size() > 0) { - message_loop_->task_runner()->PostTask(FROM_HERE, - std::move(command_queue.front())); + while (command_credits > 0 && !command_queue.empty()) { + if (!thread.DoInThread(FROM_HERE, std::move(command_queue.front()))) { + LOG(ERROR) << __func__ << ": failed to enqueue command"; + } command_queue.pop(); command_credits--; } diff --git a/system/main/Android.bp b/system/main/Android.bp index 03861996c98..dcd9a0c0bca 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -61,6 +61,7 @@ cc_library_shared { ], whole_static_libs: [ "libbt-bta", + "libbt-common", "libbtdevice", "libbtif", "libbt-hci", diff --git a/system/main/bte_main.cc b/system/main/bte_main.cc index 7fdeef031db..f3cca3ed98c 100644 --- a/system/main/bte_main.cc +++ b/system/main/bte_main.cc @@ -53,7 +53,6 @@ #include "osi/include/future.h" #include "osi/include/log.h" #include "osi/include/osi.h" -#include "osi/include/thread.h" #include "stack_config.h" /******************************************************************************* diff --git a/system/osi/Android.bp b/system/osi/Android.bp index 5439b283d95..de33bfa80e1 100644 --- a/system/osi/Android.bp +++ b/system/osi/Android.bp @@ -122,6 +122,7 @@ cc_test { "libcutils", ], static_libs: [ + "libbt-common", "libbt-protos-lite", "libgmock", "libosi", diff --git a/system/osi/test/alarm_test.cc b/system/osi/test/alarm_test.cc index f7f473d7d37..df6592a22ce 100644 --- a/system/osi/test/alarm_test.cc +++ b/system/osi/test/alarm_test.cc @@ -22,14 +22,15 @@ #include "AlarmTestHarness.h" +#include "common/message_loop_thread.h" #include "osi/include/alarm.h" #include "osi/include/fixed_queue.h" #include "osi/include/osi.h" #include "osi/include/semaphore.h" -#include "osi/include/thread.h" using base::Closure; using base::TimeDelta; +using bluetooth::common::MessageLoopThread; static semaphore_t* semaphore; static int cb_counter; @@ -39,23 +40,7 @@ static const uint64_t EPSILON_MS = 50; static void msleep(uint64_t ms) { usleep(ms * 1000); } -base::MessageLoop* message_loop_; -base::RunLoop* run_loop_; -static semaphore_t* msg_loop_ready; - -void message_loop_run(UNUSED_ATTR void* context) { - message_loop_ = new base::MessageLoop(); - run_loop_ = new base::RunLoop(); - - semaphore_post(msg_loop_ready); - run_loop_->Run(); - - delete message_loop_; - message_loop_ = nullptr; - - delete run_loop_; - run_loop_ = nullptr; -} +static base::MessageLoop* message_loop_; base::MessageLoop* get_message_loop() { return message_loop_; } @@ -318,15 +303,12 @@ TEST_F(AlarmTest, test_callback_ordering_on_mloop) { alarm_t* alarms[100]; // Initialize MesageLoop, and wait till it's initialized. - msg_loop_ready = semaphore_new(0); - thread_t* message_loop_thread_ = thread_new("btu message loop"); - if (!message_loop_thread_) { + MessageLoopThread message_loop_thread("btu message loop"); + message_loop_thread.StartUp(); + if (!message_loop_thread.IsRunning()) { FAIL() << "unable to create btu message loop thread."; } - - thread_post(message_loop_thread_, message_loop_run, nullptr); - semaphore_wait(msg_loop_ready); - semaphore_free(msg_loop_ready); + message_loop_ = message_loop_thread.message_loop(); for (int i = 0; i < 100; i++) { const std::string alarm_name = @@ -347,9 +329,7 @@ TEST_F(AlarmTest, test_callback_ordering_on_mloop) { for (int i = 0; i < 100; i++) alarm_free(alarms[i]); - message_loop_->task_runner()->PostTask(FROM_HERE, - run_loop_->QuitWhenIdleClosure()); - thread_free(message_loop_thread_); + message_loop_thread.ShutDown(); EXPECT_FALSE(WakeLockHeld()); } diff --git a/system/osi/test/future_test.cc b/system/osi/test/future_test.cc index 26d319ac6e0..5e787392775 100644 --- a/system/osi/test/future_test.cc +++ b/system/osi/test/future_test.cc @@ -20,9 +20,11 @@ #include "AllocationTestHarness.h" +#include "common/message_loop_thread.h" #include "osi/include/future.h" #include "osi/include/osi.h" -#include "osi/include/thread.h" + +using bluetooth::common::MessageLoopThread; static const char* pass_back_data0 = "fancy a sandwich? it's a fancy sandwich"; static const char* pass_back_data1 = @@ -38,12 +40,13 @@ TEST_F(FutureTest, test_future_non_immediate) { future_t* future = future_new(); ASSERT_TRUE(future != NULL); - thread_t* worker_thread = thread_new("worker thread"); - thread_post(worker_thread, post_to_future, future); + MessageLoopThread worker_thread("worker_thread"); + worker_thread.StartUp(); + worker_thread.DoInThread(FROM_HERE, base::Bind(post_to_future, future)); EXPECT_EQ(pass_back_data0, future_await(future)); - thread_free(worker_thread); + worker_thread.ShutDown(); } TEST_F(FutureTest, test_future_immediate) { diff --git a/system/osi/test/semaphore_test.cc b/system/osi/test/semaphore_test.cc index 44aee8d0d57..54046a85159 100644 --- a/system/osi/test/semaphore_test.cc +++ b/system/osi/test/semaphore_test.cc @@ -6,10 +6,12 @@ #include <sys/select.h> #include <unistd.h> +#include "common/message_loop_thread.h" #include "osi/include/osi.h" #include "osi/include/reactor.h" #include "osi/include/semaphore.h" -#include "osi/include/thread.h" + +using bluetooth::common::MessageLoopThread; struct SemaphoreTestSequenceHelper { semaphore_t* semaphore; @@ -71,16 +73,18 @@ TEST_F(SemaphoreTest, test_wait_after_post) { TEST_F(SemaphoreTest, test_ensure_wait) { semaphore_t* semaphore = semaphore_new(0); ASSERT_TRUE(semaphore != NULL); - thread_t* thread = thread_new("semaphore_test_thread"); - ASSERT_TRUE(thread != NULL); + MessageLoopThread thread("semaphore_test_thread"); + thread.StartUp(); + ASSERT_TRUE(thread.IsRunning()); EXPECT_FALSE(semaphore_try_wait(semaphore)); SemaphoreTestSequenceHelper sequence_helper = {semaphore, 0}; - thread_post(thread, sleep_then_increment_counter, &sequence_helper); + thread.DoInThread(FROM_HERE, + base::Bind(sleep_then_increment_counter, &sequence_helper)); semaphore_wait(semaphore); EXPECT_EQ(sequence_helper.counter, 1) << "semaphore_wait() did not wait for counter to increment"; semaphore_free(semaphore); - thread_free(thread); + thread.ShutDown(); } diff --git a/system/stack/Android.bp b/system/stack/Android.bp index f073048cbaf..722a4e5aedf 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -213,6 +213,7 @@ cc_test { ], static_libs: [ "libbt-bta", + "libbt-common", "libbt-stack", "libbt-sbc-decoder", "libbt-sbc-encoder", @@ -393,6 +394,7 @@ cc_test { "libprotobuf-cpp-lite", ], static_libs: [ + "libbt-common", "libbluetooth-types", "libgmock", "libosi", diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc index 2e425aa8ae5..f99ee5decee 100644 --- a/system/stack/btm/btm_devctl.cc +++ b/system/stack/btm/btm_devctl.cc @@ -34,16 +34,16 @@ #include "btcore/include/module.h" #include "btm_int.h" #include "btu.h" +#include "common/message_loop_thread.h" #include "device/include/controller.h" #include "hci_layer.h" #include "hcimsgs.h" #include "l2c_int.h" #include "osi/include/osi.h" -#include "osi/include/thread.h" #include "gatt_int.h" -extern thread_t* bt_workqueue_thread; +extern bluetooth::common::MessageLoopThread bt_workqueue_thread; /******************************************************************************/ /* L O C A L D A T A D E F I N I T I O N S */ @@ -76,7 +76,7 @@ static void btm_decode_ext_features_page(uint8_t page_number, * Returns void * ******************************************************************************/ -void btm_dev_init(void) { +void btm_dev_init() { /* Initialize nonzero defaults */ memset(btm_cb.cfg.bd_name, 0, sizeof(tBTM_LOC_BD_NAME)); @@ -231,7 +231,7 @@ void BTM_DeviceReset(UNUSED_ATTR tBTM_CMPL_CB* p_cb) { btm_db_reset(); module_start_up_callbacked_wrapper(get_module(CONTROLLER_MODULE), - bt_workqueue_thread, reset_complete); + &bt_workqueue_thread, reset_complete); } /******************************************************************************* diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc index 0f54a69d25d..e2d8a2f7abe 100644 --- a/system/stack/btu/btu_hcif.cc +++ b/system/stack/btu/btu_hcif.cc @@ -126,18 +126,6 @@ static void btu_ble_rc_param_req_evt(uint8_t* p); static void btu_ble_proc_enhanced_conn_cmpl(uint8_t* p, uint16_t evt_len); #endif -static void do_in_hci_thread(const tracked_objects::Location& from_here, - const base::Closure& task) { - base::MessageLoop* hci_message_loop = get_message_loop(); - if (!hci_message_loop || !hci_message_loop->task_runner().get()) { - LOG_ERROR(LOG_TAG, "%s: HCI message loop not running, accessed from %s", - __func__, from_here.ToString().c_str()); - return; - } - - hci_message_loop->task_runner()->PostTask(from_here, task); -} - /******************************************************************************* * * Function btu_hcif_process_event @@ -433,7 +421,7 @@ static void btu_hcif_command_complete_evt_with_cb_on_task(BT_HDR* event, static void btu_hcif_command_complete_evt_with_cb(BT_HDR* response, void* context) { - do_in_hci_thread(FROM_HERE, + do_in_bta_thread(FROM_HERE, base::Bind(btu_hcif_command_complete_evt_with_cb_on_task, response, context)); } @@ -466,7 +454,7 @@ static void btu_hcif_command_status_evt_with_cb(uint8_t status, BT_HDR* command, return; } - do_in_hci_thread( + do_in_bta_thread( FROM_HERE, base::Bind(btu_hcif_command_status_evt_with_cb_on_task, status, command, context)); } @@ -1039,7 +1027,7 @@ static void btu_hcif_command_complete_evt_on_task(BT_HDR* event, } static void btu_hcif_command_complete_evt(BT_HDR* response, void* context) { - do_in_hci_thread(FROM_HERE, base::Bind(btu_hcif_command_complete_evt_on_task, + do_in_bta_thread(FROM_HERE, base::Bind(btu_hcif_command_complete_evt_on_task, response, context)); } @@ -1214,7 +1202,7 @@ static void btu_hcif_command_status_evt_on_task(uint8_t status, BT_HDR* event, static void btu_hcif_command_status_evt(uint8_t status, BT_HDR* command, void* context) { - do_in_hci_thread(FROM_HERE, base::Bind(btu_hcif_command_status_evt_on_task, + do_in_bta_thread(FROM_HERE, base::Bind(btu_hcif_command_status_evt_on_task, status, command, context)); } diff --git a/system/stack/btu/btu_init.cc b/system/stack/btu/btu_init.cc index 3f24813c597..7f26fed112a 100644 --- a/system/stack/btu/btu_init.cc +++ b/system/stack/btu/btu_init.cc @@ -25,6 +25,7 @@ #include "bt_target.h" #include "btm_int.h" #include "btu.h" +#include "common/message_loop_thread.h" #include "device/include/controller.h" #include "gatt_api.h" #include "gatt_int.h" @@ -32,20 +33,12 @@ #include "osi/include/alarm.h" #include "osi/include/fixed_queue.h" #include "osi/include/log.h" -#include "osi/include/thread.h" #include "sdpint.h" #include "smp_int.h" -// RT priority for audio-related tasks -#define BTU_TASK_RT_PRIORITY 1 +using bluetooth::common::MessageLoopThread; -// Communication queue from hci thread to bt_workqueue. -extern fixed_queue_t* btu_hci_msg_queue; - -thread_t* bt_workqueue_thread; -static const char* BT_WORKQUEUE_NAME = "bt_workqueue"; - -extern void PLATFORM_DisableHciTransport(uint8_t bDisable); +MessageLoopThread bt_workqueue_thread("bt_workqueue"); void btu_task_start_up(void* context); void btu_task_shut_down(void* context); @@ -60,7 +53,7 @@ void btu_task_shut_down(void* context); * Returns void * *****************************************************************************/ -void btu_init_core(void) { +void btu_init_core() { /* Initialize the mandatory core stack components */ btm_init(); @@ -85,7 +78,7 @@ void btu_init_core(void) { * Returns void * *****************************************************************************/ -void btu_free_core(void) { +void btu_free_core() { /* Free the mandatory core stack components */ gatt_free(); @@ -106,29 +99,27 @@ void btu_free_core(void) { * Returns void * *****************************************************************************/ -void BTU_StartUp(void) { +void BTU_StartUp() { btu_trace_level = HCI_INITIAL_TRACE_LEVEL; - - bt_workqueue_thread = thread_new(BT_WORKQUEUE_NAME); - if (bt_workqueue_thread == NULL) goto error_exit; - - thread_set_rt_priority(bt_workqueue_thread, BTU_TASK_RT_PRIORITY); - - // Continue startup on bt workqueue thread. - thread_post(bt_workqueue_thread, btu_task_start_up, NULL); - return; - -error_exit:; - LOG_ERROR(LOG_TAG, "%s Unable to allocate resources for bt_workqueue", - __func__); - BTU_ShutDown(); + bt_workqueue_thread.StartUp(); + if (!bt_workqueue_thread.EnableRealTimeScheduling()) { + LOG(ERROR) << __func__ + << ": Unable to set real time scheduling policy for" + " bt_workqueue thread"; + BTU_ShutDown(); + return; + } + if (!bt_workqueue_thread.DoInThread(FROM_HERE, + base::Bind(btu_task_start_up, nullptr))) { + LOG(ERROR) << __func__ + << ": Unable to continue start-up on bt_workqueue" + " thread"; + BTU_ShutDown(); + return; + } } -void BTU_ShutDown(void) { - btu_task_shut_down(NULL); - - - thread_free(bt_workqueue_thread); - - bt_workqueue_thread = NULL; +void BTU_ShutDown() { + btu_task_shut_down(nullptr); + bt_workqueue_thread.ShutDown(); } diff --git a/system/stack/btu/btu_task.cc b/system/stack/btu/btu_task.cc index 7d2527a4193..736d30de5ad 100644 --- a/system/stack/btu/btu_task.cc +++ b/system/stack/btu/btu_task.cc @@ -32,22 +32,18 @@ #include "btcore/include/module.h" #include "bte.h" #include "btif/include/btif_common.h" +#include "common/message_loop_thread.h" #include "osi/include/osi.h" -#include "osi/include/thread.h" #include "stack/btm/btm_int.h" #include "stack/include/btu.h" #include "stack/l2cap/l2c_int.h" -static const int THREAD_RT_PRIORITY = 1; +using bluetooth::common::MessageLoopThread; /* Define BTU storage area */ uint8_t btu_trace_level = HCI_INITIAL_TRACE_LEVEL; -extern thread_t* bt_workqueue_thread; - -static base::MessageLoop* message_loop_ = NULL; -static base::RunLoop* run_loop_ = NULL; -static thread_t* message_loop_thread_; +static MessageLoopThread btu_message_loop_thread("btu_message_loop"); void btu_hci_msg_process(BT_HDR* p_msg) { /* Determine the input message type. */ @@ -83,24 +79,16 @@ void btu_hci_msg_process(BT_HDR* p_msg) { } } -base::MessageLoop* get_message_loop() { return message_loop_; } - -void btu_message_loop_run(UNUSED_ATTR void* context) { - message_loop_ = new base::MessageLoop(); - run_loop_ = new base::RunLoop(); - - // Inform the bt jni thread initialization is ok. - message_loop_->task_runner()->PostTask( - FROM_HERE, base::Bind(base::IgnoreResult(&btif_transfer_context), - btif_init_ok, 0, nullptr, 0, nullptr)); - - run_loop_->Run(); - - delete message_loop_; - message_loop_ = NULL; +base::MessageLoop* get_message_loop() { + return btu_message_loop_thread.message_loop(); +} - delete run_loop_; - run_loop_ = NULL; +bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here, + base::OnceClosure task) { + if (!btu_message_loop_thread.DoInThread(from_here, std::move(task))) { + return BT_STATUS_FAIL; + } + return BT_STATUS_SUCCESS; } void btu_task_start_up(UNUSED_ATTR void* context) { @@ -123,21 +111,22 @@ void btu_task_start_up(UNUSED_ATTR void* context) { */ module_init(get_module(BTE_LOGMSG_MODULE)); - message_loop_thread_ = thread_new("btu message loop"); - if (!message_loop_thread_) { - LOG(FATAL) << __func__ << " unable to create btu message loop thread."; + btu_message_loop_thread.StartUp(); + if (!btu_message_loop_thread.IsRunning()) { + LOG(FATAL) << __func__ << ": unable to start btu message loop thread."; + } + if (!btu_message_loop_thread.EnableRealTimeScheduling()) { + LOG(FATAL) << __func__ << ": unable to enable real time scheduling"; + } + if (do_in_jni_thread(FROM_HERE, base::Bind(btif_init_ok, 0, nullptr)) != + BT_STATUS_SUCCESS) { + LOG(FATAL) << __func__ << ": unable to continue starting Bluetooth"; } - - thread_set_rt_priority(message_loop_thread_, THREAD_RT_PRIORITY); - thread_post(message_loop_thread_, btu_message_loop_run, nullptr); - } void btu_task_shut_down(UNUSED_ATTR void* context) { // Shutdown message loop on task completed - if (run_loop_ && message_loop_) { - message_loop_->task_runner()->PostTask(FROM_HERE, run_loop_->QuitClosure()); - } + btu_message_loop_thread.ShutDown(); module_clean_up(get_module(BTE_LOGMSG_MODULE)); diff --git a/system/stack/include/btu.h b/system/stack/include/btu.h index 5841efa5e4c..505df69a369 100644 --- a/system/stack/include/btu.h +++ b/system/stack/include/btu.h @@ -32,6 +32,7 @@ #include <base/threading/thread.h> #include "bt_common.h" #include "bt_target.h" +#include "common/message_loop_thread.h" #include "osi/include/alarm.h" /* Global BTU data */ @@ -57,6 +58,8 @@ void btu_free_core(void); *********************************** */ base::MessageLoop* get_message_loop(); +bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here, + base::OnceClosure task); void BTU_StartUp(void); void BTU_ShutDown(void); diff --git a/system/stack/test/stack_btu_test.cc b/system/stack/test/stack_btu_test.cc index 97e95d2677e..d048b8937f4 100644 --- a/system/stack/test/stack_btu_test.cc +++ b/system/stack/test/stack_btu_test.cc @@ -26,9 +26,9 @@ #include <unistd.h> #include "btcore/include/module.h" +#include "common/message_loop_thread.h" #include "osi/include/alarm.h" #include "osi/include/fixed_queue.h" -#include "osi/include/thread.h" #include "stack/include/btu.h" class TimeoutHelper { @@ -67,10 +67,11 @@ void btu_task_shut_down(void* context); /* Below are methods and variables that must be implemented if we don't want to * compile the whole stack. They will be removed, or changed into mocks one by * one in the future, as the refactoring progresses */ -void btif_transfer_context(void (*)(unsigned short, char*), uint16_t, char*, - int, void (*)(unsigned short, char*, char*)) { +bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here, + base::OnceClosure task) { helper.notify(); -}; + return BT_STATUS_SUCCESS; +} void btu_init_core(){}; void btif_init_ok(unsigned short, char*){}; @@ -82,7 +83,7 @@ const module_t* get_module(const char*) { return nullptr; }; bool module_init(module_t const*) { return true; }; void module_clean_up(module_t const*){}; -thread_t* bt_workqueue_thread; +bluetooth::common::MessageLoopThread bt_workqueue_thread("test alarm thread"); class BtuMessageLoopTest : public testing::Test { public: @@ -92,8 +93,7 @@ class BtuMessageLoopTest : public testing::Test { virtual void SetUp() { // Initialize alarms to prevent btu_task_shut_down from crashing alarm_new("test alarm"); - bt_workqueue_thread = thread_new("test alarm thread"); - + bt_workqueue_thread.StartUp(); // btu_task_start_up calls btif_transfer_context to let the stack know // start up is finished btu_task_start_up(nullptr); @@ -104,6 +104,7 @@ class BtuMessageLoopTest : public testing::Test { virtual void TearDown() { btu_task_shut_down(nullptr); alarm_cleanup(); + bt_workqueue_thread.ShutDown(); } void Fail(std::string message) { FAIL() << message; } -- GitLab