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