18df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson/******************************************************************************
28df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *
38df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  Copyright (C) 2014 Google, Inc.
48df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *
58df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  Licensed under the Apache License, Version 2.0 (the "License");
68df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  you may not use this file except in compliance with the License.
78df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  You may obtain a copy of the License at:
88df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *
98df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  http://www.apache.org/licenses/LICENSE-2.0
108df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *
118df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  Unless required by applicable law or agreed to in writing, software
128df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  distributed under the License is distributed on an "AS IS" BASIS,
138df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  See the License for the specific language governing permissions and
158df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *  limitations under the License.
168df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson *
178df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson ******************************************************************************/
188df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1949120dc867c7818511b5afec461dfc97d17eef58Marie Janssen#define LOG_TAG "bt_stack_manager"
2049120dc867c7818511b5afec461dfc97d17eef58Marie Janssen
2149a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#include "stack_manager.h"
2249a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen
238df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson#include <hardware/bluetooth.h>
248df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
25db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "btcore/include/module.h"
26db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "btcore/include/osi_module.h"
278df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson#include "btif_api.h"
281924dac3811575d594c11b76874b24ee0ad24e71Zach Johnson#include "btif_common.h"
2979ecab5d0418fde77e9afcdd451bd713af73e180Chris Manton#include "device/include/controller.h"
3044802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h"
31db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "osi/include/osi.h"
320f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/semaphore.h"
330f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/thread.h"
348df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
359b0fbce37260e69cb116be1cdcbceb1f43bf9346Zach Johnson// Temp includes
366bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson#include "bt_utils.h"
379b0fbce37260e69cb116be1cdcbceb1f43bf9346Zach Johnson#include "btif_config.h"
38eacc69d09256ecaa7c01ea066cd70b0049edc23bSharvil Nanavati#include "btif_profile_queue.h"
399b0fbce37260e69cb116be1cdcbceb1f43bf9346Zach Johnson
406bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic thread_t* management_thread;
418df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
428df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// If initialized, any of the bluetooth API functions can be called.
438df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// (e.g. turning logging on and off, enabling/disabling the stack, etc)
448df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnsonstatic bool stack_is_initialized;
458df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// If running, the stack is fully up and able to bluetooth.
468df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnsonstatic bool stack_is_running;
478df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
486bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_init_stack(void* context);
496bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_start_up_stack(void* context);
506bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_shut_down_stack(void* context);
516bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_clean_up_stack(void* context);
528df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
536bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_signal_stack_up(void* context);
546bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_signal_stack_down(void* context);
55efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson
566bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson// Unvetted includes/imports, etc which should be removed or vetted in the
576bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson// future
586bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic future_t* hack_future;
596bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonvoid btif_thread_post(thread_fn func, void* context);
60f450ba53dfd7b36989c1ea6ed9c6508c7a1b895eZach Johnson// End unvetted section
618ea8188a481504641fc6a72087704eb808d0bd87Zach Johnson
628df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// Interface functions
638df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
648df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnsonstatic void init_stack(void) {
658df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  // This is a synchronous process. Post it to the thread though, so
66c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker  // state modification only happens there. Using the thread to perform
67c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker  // all stack operations ensures that the operations are done serially
68c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker  // and do not overlap.
696bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  semaphore_t* semaphore = semaphore_new(0);
708df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  thread_post(management_thread, event_init_stack, semaphore);
718df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  semaphore_wait(semaphore);
72f5153bf62b6cee3f3c740504e94360130c3a9186Sharvil Nanavati  semaphore_free(semaphore);
738df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
748df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
758df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnsonstatic void start_up_stack_async(void) {
768df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  thread_post(management_thread, event_start_up_stack, NULL);
778df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
788df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
798df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnsonstatic void shut_down_stack_async(void) {
808df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  thread_post(management_thread, event_shut_down_stack, NULL);
818df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
828df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
83c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panickerstatic void clean_up_stack(void) {
84c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker  // This is a synchronous process. Post it to the thread though, so
85c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker  // state modification only happens there.
866bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  semaphore_t* semaphore = semaphore_new(0);
87c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker  thread_post(management_thread, event_clean_up_stack, semaphore);
88c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker  semaphore_wait(semaphore);
89c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker  semaphore_free(semaphore);
908df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
918df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
926bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic bool get_stack_is_running(void) { return stack_is_running; }
93f450ba53dfd7b36989c1ea6ed9c6508c7a1b895eZach Johnson
948df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// Internal functions
958df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
968df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// Synchronous function to initialize the stack
976bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_init_stack(void* context) {
986bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  semaphore_t* semaphore = (semaphore_t*)context;
998df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1008e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov  LOG_INFO(LOG_TAG, "%s is initializing the stack", __func__);
1018e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov
1026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (stack_is_initialized) {
1036bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    LOG_INFO(LOG_TAG, "%s found the stack already in initialized state",
1046bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson             __func__);
1056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  } else {
10672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    module_management_start();
10772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
108592afafb911cccc8aaa7d74c54f638e6bfb0a62dPavlin Radoslavov    module_init(get_module(OSI_MODULE));
10996363ff2b78c10e2b2e106464f337b58ec1a616aZach Johnson    module_init(get_module(BT_UTILS_MODULE));
1109b0fbce37260e69cb116be1cdcbceb1f43bf9346Zach Johnson    module_init(get_module(BTIF_CONFIG_MODULE));
1118df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    btif_init_bluetooth();
1128df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1138df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    // stack init is synchronous, so no waiting necessary here
1148df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    stack_is_initialized = true;
1158df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  }
1168df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1178e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov  LOG_INFO(LOG_TAG, "%s finished", __func__);
1188e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov
1196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (semaphore) semaphore_post(semaphore);
1208df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
1218df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1228df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnsonstatic void ensure_stack_is_initialized(void) {
1238df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  if (!stack_is_initialized) {
1246bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    LOG_WARN(LOG_TAG, "%s found the stack was uninitialized. Initializing now.",
1256bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson             __func__);
1268df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    // No semaphore needed since we are calling it directly
1278df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    event_init_stack(NULL);
1288df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  }
1298df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
1308df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1318df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// Synchronous function to start up the stack
1326bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_start_up_stack(UNUSED_ATTR void* context) {
1338df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  if (stack_is_running) {
1348e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov    LOG_INFO(LOG_TAG, "%s stack already brought up", __func__);
1358df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    return;
1368df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  }
1378df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1388df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  ensure_stack_is_initialized();
1398df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1408e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov  LOG_INFO(LOG_TAG, "%s is bringing up the stack", __func__);
1416bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  future_t* local_hack_future = future_new();
142c3e8824f8d5266ee5d33be18c690b8de8f0562aaPavlin Radoslavov  hack_future = local_hack_future;
1438ea8188a481504641fc6a72087704eb808d0bd87Zach Johnson
1449b0fbce37260e69cb116be1cdcbceb1f43bf9346Zach Johnson  // Include this for now to put btif config into a shutdown-able state
1459b0fbce37260e69cb116be1cdcbceb1f43bf9346Zach Johnson  module_start_up(get_module(BTIF_CONFIG_MODULE));
146f450ba53dfd7b36989c1ea6ed9c6508c7a1b895eZach Johnson  bte_main_enable();
1478ea8188a481504641fc6a72087704eb808d0bd87Zach Johnson
148c3e8824f8d5266ee5d33be18c690b8de8f0562aaPavlin Radoslavov  if (future_await(local_hack_future) != FUTURE_SUCCESS) {
1498e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov    LOG_ERROR(LOG_TAG, "%s failed to start up the stack", __func__);
1506bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    stack_is_running = true;  // So stack shutdown actually happens
1511924dac3811575d594c11b76874b24ee0ad24e71Zach Johnson    event_shut_down_stack(NULL);
1521924dac3811575d594c11b76874b24ee0ad24e71Zach Johnson    return;
1531924dac3811575d594c11b76874b24ee0ad24e71Zach Johnson  }
1541924dac3811575d594c11b76874b24ee0ad24e71Zach Johnson
1551924dac3811575d594c11b76874b24ee0ad24e71Zach Johnson  stack_is_running = true;
1568e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov  LOG_INFO(LOG_TAG, "%s finished", __func__);
157efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson  btif_thread_post(event_signal_stack_up, NULL);
1588df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
1598df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1608df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// Synchronous function to shut down the stack
1616bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_shut_down_stack(UNUSED_ATTR void* context) {
1628df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  if (!stack_is_running) {
1638e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov    LOG_INFO(LOG_TAG, "%s stack is already brought down", __func__);
1648df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    return;
1658df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  }
1668df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1678e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov  LOG_INFO(LOG_TAG, "%s is bringing down the stack", __func__);
1686bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  future_t* local_hack_future = future_new();
169c3e8824f8d5266ee5d33be18c690b8de8f0562aaPavlin Radoslavov  hack_future = local_hack_future;
1708df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  stack_is_running = false;
1718ea8188a481504641fc6a72087704eb808d0bd87Zach Johnson
1728ea8188a481504641fc6a72087704eb808d0bd87Zach Johnson  btif_disable_bluetooth();
1739b0fbce37260e69cb116be1cdcbceb1f43bf9346Zach Johnson  module_shut_down(get_module(BTIF_CONFIG_MODULE));
1748ea8188a481504641fc6a72087704eb808d0bd87Zach Johnson
175c3e8824f8d5266ee5d33be18c690b8de8f0562aaPavlin Radoslavov  future_await(local_hack_future);
1766bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  module_shut_down(get_module(CONTROLLER_MODULE));  // Doesn't do any work, just
1776bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                                    // puts it in a restartable
1786bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                                    // state
179cae219fe70124f1fc39cd7a78c239c4870422d5dAndre Eisenbach
18016e112b1861d8f1147325372608c905627e00e88Gurpreet Ghai  hack_future = future_new();
181efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson  btif_thread_post(event_signal_stack_down, NULL);
18216e112b1861d8f1147325372608c905627e00e88Gurpreet Ghai  future_await(hack_future);
183137aa547f3d163929120d250a87e55dbf6c748abPavlin Radoslavov  LOG_INFO(LOG_TAG, "%s finished", __func__);
1848df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
1858df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1868df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnsonstatic void ensure_stack_is_not_running(void) {
1878df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  if (stack_is_running) {
1886bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    LOG_WARN(LOG_TAG,
1896bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson             "%s found the stack was still running. Bringing it down now.",
1906bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson             __func__);
1918df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    event_shut_down_stack(NULL);
1928df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  }
1938df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
1948df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
1958df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson// Synchronous function to clean up the stack
1966bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_clean_up_stack(void* context) {
1976bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  future_t* local_hack_future;
198713993d1784ab7c23aee1fa3cf1ab8676cc0aa69Jakub Pawlowski
1998df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  if (!stack_is_initialized) {
2008e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov    LOG_INFO(LOG_TAG, "%s found the stack already in a clean state", __func__);
201c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker    goto cleanup;
2028df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  }
2038df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
2048df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  ensure_stack_is_not_running();
2058df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
2068e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov  LOG_INFO(LOG_TAG, "%s is cleaning up the stack", __func__);
207713993d1784ab7c23aee1fa3cf1ab8676cc0aa69Jakub Pawlowski  local_hack_future = future_new();
208c3e8824f8d5266ee5d33be18c690b8de8f0562aaPavlin Radoslavov  hack_future = local_hack_future;
2098df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  stack_is_initialized = false;
2108ea8188a481504641fc6a72087704eb808d0bd87Zach Johnson
2111bd691cb8ae3c23ffe25b5ca1fcfd11b82a9fbdaPavlin Radoslavov  btif_cleanup_bluetooth();
2129b0fbce37260e69cb116be1cdcbceb1f43bf9346Zach Johnson  module_clean_up(get_module(BTIF_CONFIG_MODULE));
21396363ff2b78c10e2b2e106464f337b58ec1a616aZach Johnson  module_clean_up(get_module(BT_UTILS_MODULE));
2140933b4075e16589a073e85d8230677238b29b780Pavlin Radoslavov  module_clean_up(get_module(OSI_MODULE));
2158675d884479deca722ef5d7776a165241457dd75Zach Johnson  module_management_stop();
2168e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov  LOG_INFO(LOG_TAG, "%s finished", __func__);
217c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panicker
218c28849aa58c10a4e57d6cb7e5f6d876cba4f8d99Ajay Panickercleanup:;
2196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  semaphore_t* semaphore = (semaphore_t*)context;
2206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (semaphore) semaphore_post(semaphore);
2218df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
2228df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
2236bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_signal_stack_up(UNUSED_ATTR void* context) {
224eacc69d09256ecaa7c01ea066cd70b0049edc23bSharvil Nanavati  // Notify BTIF connect queue that we've brought up the stack. It's
225eacc69d09256ecaa7c01ea066cd70b0049edc23bSharvil Nanavati  // now time to dispatch all the pending profile connect requests.
226eacc69d09256ecaa7c01ea066cd70b0049edc23bSharvil Nanavati  btif_queue_connect_next();
227efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson  HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON);
228efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson}
229efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson
2306bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic void event_signal_stack_down(UNUSED_ATTR void* context) {
231efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson  HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF);
23216e112b1861d8f1147325372608c905627e00e88Gurpreet Ghai  future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS);
233efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson}
234efea7821780cdea2b30e944b08e418d1f2781878Zach Johnson
2358df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnsonstatic void ensure_manager_initialized(void) {
2366bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (management_thread) return;
2378df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
2388df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  management_thread = thread_new("stack_manager");
2398df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  if (!management_thread) {
2408e7721573557c4ccb7918810349f8a80c2e49803Pavlin Radoslavov    LOG_ERROR(LOG_TAG, "%s unable to create stack management thread", __func__);
2418df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson    return;
2428df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  }
2438df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
2448df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
2456bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic const stack_manager_t interface = {init_stack, start_up_stack_async,
2466bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                          shut_down_stack_async, clean_up_stack,
247f450ba53dfd7b36989c1ea6ed9c6508c7a1b895eZach Johnson
2486bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                          get_stack_is_running};
2498df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson
2506bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonconst stack_manager_t* stack_manager_get_interface() {
2518df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  ensure_manager_initialized();
2528df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson  return &interface;
2538df0d80f0227554d95ed51a443439ee9e7fe7e42Zach Johnson}
2548ea8188a481504641fc6a72087704eb808d0bd87Zach Johnson
2556bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonfuture_t* stack_manager_get_hack_future() { return hack_future; }
256