Home | History | Annotate | Download | only in src
      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 <hardware/bluetooth.h>
     22 
     23 #include "btif_api.h"
     24 #include "btif_common.h"
     25 #include "device/include/controller.h"
     26 #include "btcore/include/module.h"
     27 #include "btcore/include/osi_module.h"
     28 #include "osi/include/osi.h"
     29 #include "osi/include/log.h"
     30 #include "osi/include/semaphore.h"
     31 #include "stack_manager.h"
     32 #include "osi/include/thread.h"
     33 
     34 // Temp includes
     35 #include "btif_config.h"
     36 #include "btif_profile_queue.h"
     37 #include "bt_utils.h"
     38 
     39 static thread_t *management_thread;
     40 
     41 // If initialized, any of the bluetooth API functions can be called.
     42 // (e.g. turning logging on and off, enabling/disabling the stack, etc)
     43 static bool stack_is_initialized;
     44 // If running, the stack is fully up and able to bluetooth.
     45 static bool stack_is_running;
     46 
     47 static void event_init_stack(void *context);
     48 static void event_start_up_stack(void *context);
     49 static void event_shut_down_stack(void *context);
     50 static void event_clean_up_stack(void *context);
     51 
     52 static void event_signal_stack_up(void *context);
     53 static void event_signal_stack_down(void *context);
     54 
     55 // Unvetted includes/imports, etc which should be removed or vetted in the future
     56 static future_t *hack_future;
     57 void bte_main_enable();
     58 void btif_thread_post(thread_fn func, void *context);
     59 // End unvetted section
     60 
     61 // Interface functions
     62 
     63 static void init_stack(void) {
     64   // This is a synchronous process. Post it to the thread though, so
     65   // state modification only happens there.
     66   semaphore_t *semaphore = semaphore_new(0);
     67   thread_post(management_thread, event_init_stack, semaphore);
     68   semaphore_wait(semaphore);
     69   semaphore_free(semaphore);
     70 }
     71 
     72 static void start_up_stack_async(void) {
     73   thread_post(management_thread, event_start_up_stack, NULL);
     74 }
     75 
     76 static void shut_down_stack_async(void) {
     77   thread_post(management_thread, event_shut_down_stack, NULL);
     78 }
     79 
     80 static void clean_up_stack_async(void) {
     81   thread_post(management_thread, event_clean_up_stack, NULL);
     82 }
     83 
     84 static bool get_stack_is_running(void) {
     85   return stack_is_running;
     86 }
     87 
     88 // Internal functions
     89 
     90 // Synchronous function to initialize the stack
     91 static void event_init_stack(void *context) {
     92   semaphore_t *semaphore = (semaphore_t *)context;
     93 
     94   if (!stack_is_initialized) {
     95     module_management_start();
     96 
     97     module_init(get_module(BT_UTILS_MODULE));
     98     module_init(get_module(BTIF_CONFIG_MODULE));
     99     btif_init_bluetooth();
    100 
    101     // stack init is synchronous, so no waiting necessary here
    102     stack_is_initialized = true;
    103   }
    104 
    105   if (semaphore)
    106     semaphore_post(semaphore);
    107 }
    108 
    109 static void ensure_stack_is_initialized(void) {
    110   if (!stack_is_initialized) {
    111     LOG_WARN("%s found the stack was uninitialized. Initializing now.", __func__);
    112     // No semaphore needed since we are calling it directly
    113     event_init_stack(NULL);
    114   }
    115 }
    116 
    117 // Synchronous function to start up the stack
    118 static void event_start_up_stack(UNUSED_ATTR void *context) {
    119   if (stack_is_running) {
    120     LOG_DEBUG("%s stack already brought up.", __func__);
    121     return;
    122   }
    123 
    124   ensure_stack_is_initialized();
    125 
    126   LOG_DEBUG("%s is bringing up the stack.", __func__);
    127   hack_future = future_new();
    128 
    129   // Include this for now to put btif config into a shutdown-able state
    130   module_start_up(get_module(BTIF_CONFIG_MODULE));
    131   bte_main_enable();
    132 
    133   if (future_await(hack_future) != FUTURE_SUCCESS) {
    134     stack_is_running = true; // So stack shutdown actually happens
    135     event_shut_down_stack(NULL);
    136     return;
    137   }
    138 
    139   stack_is_running = true;
    140   LOG_DEBUG("%s finished", __func__);
    141   btif_thread_post(event_signal_stack_up, NULL);
    142 }
    143 
    144 // Synchronous function to shut down the stack
    145 static void event_shut_down_stack(UNUSED_ATTR void *context) {
    146   if (!stack_is_running) {
    147     LOG_DEBUG("%s stack is already brought down.", __func__);
    148     return;
    149   }
    150 
    151   LOG_DEBUG("%s is bringing down the stack.", __func__);
    152   hack_future = future_new();
    153   stack_is_running = false;
    154 
    155   btif_disable_bluetooth();
    156   module_shut_down(get_module(BTIF_CONFIG_MODULE));
    157 
    158   future_await(hack_future);
    159   module_shut_down(get_module(CONTROLLER_MODULE)); // Doesn't do any work, just puts it in a restartable state
    160 
    161   LOG_DEBUG("%s finished.", __func__);
    162   btif_thread_post(event_signal_stack_down, NULL);
    163 }
    164 
    165 static void ensure_stack_is_not_running(void) {
    166   if (stack_is_running) {
    167     LOG_WARN("%s found the stack was still running. Bringing it down now.", __func__);
    168     event_shut_down_stack(NULL);
    169   }
    170 }
    171 
    172 // Synchronous function to clean up the stack
    173 static void event_clean_up_stack(UNUSED_ATTR void *context) {
    174   if (!stack_is_initialized) {
    175     LOG_DEBUG("%s found the stack already in a clean state.", __func__);
    176     return;
    177   }
    178 
    179   ensure_stack_is_not_running();
    180 
    181   LOG_DEBUG("%s is cleaning up the stack.", __func__);
    182   hack_future = future_new();
    183   stack_is_initialized = false;
    184 
    185   btif_shutdown_bluetooth();
    186   module_clean_up(get_module(BTIF_CONFIG_MODULE));
    187   module_clean_up(get_module(BT_UTILS_MODULE));
    188 
    189   future_await(hack_future);
    190   module_clean_up(get_module(OSI_MODULE));
    191   module_management_stop();
    192   LOG_DEBUG("%s finished.", __func__);
    193 }
    194 
    195 static void event_signal_stack_up(UNUSED_ATTR void *context) {
    196   // Notify BTIF connect queue that we've brought up the stack. It's
    197   // now time to dispatch all the pending profile connect requests.
    198   btif_queue_connect_next();
    199   HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON);
    200 }
    201 
    202 static void event_signal_stack_down(UNUSED_ATTR void *context) {
    203   HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF);
    204 }
    205 
    206 static void ensure_manager_initialized(void) {
    207   if (management_thread)
    208     return;
    209 
    210   management_thread = thread_new("stack_manager");
    211   if (!management_thread) {
    212     LOG_ERROR("%s unable to create stack management thread.", __func__);
    213     return;
    214   }
    215 }
    216 
    217 static const stack_manager_t interface = {
    218   init_stack,
    219   start_up_stack_async,
    220   shut_down_stack_async,
    221   clean_up_stack_async,
    222 
    223   get_stack_is_running
    224 };
    225 
    226 const stack_manager_t *stack_manager_get_interface() {
    227   ensure_manager_initialized();
    228   return &interface;
    229 }
    230 
    231 future_t *stack_manager_get_hack_future() {
    232   return hack_future;
    233 }
    234