stack_manager.cc revision 713993d1784ab7c23aee1fa3cf1ab8676cc0aa69
1/****************************************************************************** 2 * 3 * Copyright (C) 2014 Google, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19#define LOG_TAG "bt_stack_manager" 20 21#include "stack_manager.h" 22 23#include <hardware/bluetooth.h> 24 25#include "btcore/include/module.h" 26#include "btcore/include/osi_module.h" 27#include "btif_api.h" 28#include "btif_common.h" 29#include "device/include/controller.h" 30#include "osi/include/log.h" 31#include "osi/include/osi.h" 32#include "osi/include/semaphore.h" 33#include "osi/include/thread.h" 34 35// Temp includes 36#include "btif_config.h" 37#include "btif_profile_queue.h" 38#include "bt_utils.h" 39 40static thread_t *management_thread; 41 42// If initialized, any of the bluetooth API functions can be called. 43// (e.g. turning logging on and off, enabling/disabling the stack, etc) 44static bool stack_is_initialized; 45// If running, the stack is fully up and able to bluetooth. 46static bool stack_is_running; 47 48static void event_init_stack(void *context); 49static void event_start_up_stack(void *context); 50static void event_shut_down_stack(void *context); 51static void event_clean_up_stack(void *context); 52 53static void event_signal_stack_up(void *context); 54static void event_signal_stack_down(void *context); 55 56// Unvetted includes/imports, etc which should be removed or vetted in the future 57static future_t *hack_future; 58extern "C" void bte_main_enable(); 59void btif_thread_post(thread_fn func, void *context); 60// End unvetted section 61 62// Interface functions 63 64static void init_stack(void) { 65 // This is a synchronous process. Post it to the thread though, so 66 // state modification only happens there. Using the thread to perform 67 // all stack operations ensures that the operations are done serially 68 // and do not overlap. 69 semaphore_t *semaphore = semaphore_new(0); 70 thread_post(management_thread, event_init_stack, semaphore); 71 semaphore_wait(semaphore); 72 semaphore_free(semaphore); 73} 74 75static void start_up_stack_async(void) { 76 thread_post(management_thread, event_start_up_stack, NULL); 77} 78 79static void shut_down_stack_async(void) { 80 thread_post(management_thread, event_shut_down_stack, NULL); 81} 82 83static void clean_up_stack(void) { 84 // This is a synchronous process. Post it to the thread though, so 85 // state modification only happens there. 86 semaphore_t *semaphore = semaphore_new(0); 87 thread_post(management_thread, event_clean_up_stack, semaphore); 88 semaphore_wait(semaphore); 89 semaphore_free(semaphore); 90} 91 92static bool get_stack_is_running(void) { 93 return stack_is_running; 94} 95 96// Internal functions 97 98// Synchronous function to initialize the stack 99static void event_init_stack(void *context) { 100 semaphore_t *semaphore = (semaphore_t *)context; 101 102 LOG_INFO(LOG_TAG, "%s is initializing the stack", __func__); 103 104 if (stack_is_initialized) { 105 LOG_INFO(LOG_TAG, "%s found the stack already in initialized state", 106 __func__); 107 } else { 108 module_management_start(); 109 110 module_init(get_module(OSI_MODULE)); 111 module_init(get_module(BT_UTILS_MODULE)); 112 module_init(get_module(BTIF_CONFIG_MODULE)); 113 btif_init_bluetooth(); 114 115 // stack init is synchronous, so no waiting necessary here 116 stack_is_initialized = true; 117 } 118 119 LOG_INFO(LOG_TAG, "%s finished", __func__); 120 121 if (semaphore) 122 semaphore_post(semaphore); 123} 124 125static void ensure_stack_is_initialized(void) { 126 if (!stack_is_initialized) { 127 LOG_WARN(LOG_TAG, "%s found the stack was uninitialized. Initializing now.", __func__); 128 // No semaphore needed since we are calling it directly 129 event_init_stack(NULL); 130 } 131} 132 133// Synchronous function to start up the stack 134static void event_start_up_stack(UNUSED_ATTR void *context) { 135 if (stack_is_running) { 136 LOG_INFO(LOG_TAG, "%s stack already brought up", __func__); 137 return; 138 } 139 140 ensure_stack_is_initialized(); 141 142 LOG_INFO(LOG_TAG, "%s is bringing up the stack", __func__); 143 future_t *local_hack_future = future_new(); 144 hack_future = local_hack_future; 145 146 // Include this for now to put btif config into a shutdown-able state 147 module_start_up(get_module(BTIF_CONFIG_MODULE)); 148 bte_main_enable(); 149 150 if (future_await(local_hack_future) != FUTURE_SUCCESS) { 151 LOG_ERROR(LOG_TAG, "%s failed to start up the stack", __func__); 152 stack_is_running = true; // So stack shutdown actually happens 153 event_shut_down_stack(NULL); 154 return; 155 } 156 157 stack_is_running = true; 158 LOG_INFO(LOG_TAG, "%s finished", __func__); 159 btif_thread_post(event_signal_stack_up, NULL); 160} 161 162// Synchronous function to shut down the stack 163static void event_shut_down_stack(UNUSED_ATTR void *context) { 164 if (!stack_is_running) { 165 LOG_INFO(LOG_TAG, "%s stack is already brought down", __func__); 166 return; 167 } 168 169 LOG_INFO(LOG_TAG, "%s is bringing down the stack", __func__); 170 future_t *local_hack_future = future_new(); 171 hack_future = local_hack_future; 172 stack_is_running = false; 173 174 btif_disable_bluetooth(); 175 module_shut_down(get_module(BTIF_CONFIG_MODULE)); 176 177 future_await(local_hack_future); 178 module_shut_down(get_module(CONTROLLER_MODULE)); // Doesn't do any work, just puts it in a restartable state 179 180 LOG_INFO(LOG_TAG, "%s finished", __func__); 181 btif_thread_post(event_signal_stack_down, NULL); 182} 183 184static void ensure_stack_is_not_running(void) { 185 if (stack_is_running) { 186 LOG_WARN(LOG_TAG, "%s found the stack was still running. Bringing it down now.", __func__); 187 event_shut_down_stack(NULL); 188 } 189} 190 191// Synchronous function to clean up the stack 192static void event_clean_up_stack(void *context) { 193 194 future_t *local_hack_future; 195 196 if (!stack_is_initialized) { 197 LOG_INFO(LOG_TAG, "%s found the stack already in a clean state", __func__); 198 goto cleanup; 199 } 200 201 ensure_stack_is_not_running(); 202 203 LOG_INFO(LOG_TAG, "%s is cleaning up the stack", __func__); 204 local_hack_future = future_new(); 205 hack_future = local_hack_future; 206 stack_is_initialized = false; 207 208 btif_cleanup_bluetooth(); 209 module_clean_up(get_module(BTIF_CONFIG_MODULE)); 210 module_clean_up(get_module(BT_UTILS_MODULE)); 211 module_clean_up(get_module(OSI_MODULE)); 212 module_management_stop(); 213 LOG_INFO(LOG_TAG, "%s finished", __func__); 214 215cleanup:; 216 semaphore_t *semaphore = (semaphore_t *)context; 217 if (semaphore) 218 semaphore_post(semaphore); 219} 220 221static void event_signal_stack_up(UNUSED_ATTR void *context) { 222 // Notify BTIF connect queue that we've brought up the stack. It's 223 // now time to dispatch all the pending profile connect requests. 224 btif_queue_connect_next(); 225 HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON); 226} 227 228static void event_signal_stack_down(UNUSED_ATTR void *context) { 229 HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF); 230} 231 232static void ensure_manager_initialized(void) { 233 if (management_thread) 234 return; 235 236 management_thread = thread_new("stack_manager"); 237 if (!management_thread) { 238 LOG_ERROR(LOG_TAG, "%s unable to create stack management thread", __func__); 239 return; 240 } 241} 242 243static const stack_manager_t interface = { 244 init_stack, 245 start_up_stack_async, 246 shut_down_stack_async, 247 clean_up_stack, 248 249 get_stack_is_running 250}; 251 252const stack_manager_t *stack_manager_get_interface() { 253 ensure_manager_initialized(); 254 return &interface; 255} 256 257future_t *stack_manager_get_hack_future() { 258 return hack_future; 259} 260