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
40 static 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)
44 static bool stack_is_initialized;
45 // If running, the stack is fully up and able to bluetooth.
46 static bool stack_is_running;
47
48 static void event_init_stack(void *context);
49 static void event_start_up_stack(void *context);
50 static void event_shut_down_stack(void *context);
51 static void event_clean_up_stack(void *context);
52
53 static void event_signal_stack_up(void *context);
54 static void event_signal_stack_down(void *context);
55
56 // Unvetted includes/imports, etc which should be removed or vetted in the future
57 static future_t *hack_future;
58 void bte_main_enable();
59 void btif_thread_post(thread_fn func, void *context);
60 // End unvetted section
61
62 // Interface functions
63
init_stack(void)64 static 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
start_up_stack_async(void)75 static void start_up_stack_async(void) {
76 thread_post(management_thread, event_start_up_stack, NULL);
77 }
78
shut_down_stack_async(void)79 static void shut_down_stack_async(void) {
80 thread_post(management_thread, event_shut_down_stack, NULL);
81 }
82
clean_up_stack(void)83 static 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
get_stack_is_running(void)92 static bool get_stack_is_running(void) {
93 return stack_is_running;
94 }
95
96 // Internal functions
97
98 // Synchronous function to initialize the stack
event_init_stack(void * context)99 static 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
ensure_stack_is_initialized(void)125 static 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
event_start_up_stack(UNUSED_ATTR void * context)134 static 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
event_shut_down_stack(UNUSED_ATTR void * context)163 static 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 hack_future = future_new();
182 btif_thread_post(event_signal_stack_down, NULL);
183 future_await(hack_future);
184 }
185
ensure_stack_is_not_running(void)186 static void ensure_stack_is_not_running(void) {
187 if (stack_is_running) {
188 LOG_WARN(LOG_TAG, "%s found the stack was still running. Bringing it down now.", __func__);
189 event_shut_down_stack(NULL);
190 }
191 }
192
193 // Synchronous function to clean up the stack
event_clean_up_stack(void * context)194 static void event_clean_up_stack(void *context) {
195 if (!stack_is_initialized) {
196 LOG_INFO(LOG_TAG, "%s found the stack already in a clean state", __func__);
197 goto cleanup;
198 }
199
200 ensure_stack_is_not_running();
201
202 LOG_INFO(LOG_TAG, "%s is cleaning up the stack", __func__);
203 future_t *local_hack_future = future_new();
204 hack_future = local_hack_future;
205 stack_is_initialized = false;
206
207 btif_cleanup_bluetooth();
208 module_clean_up(get_module(BTIF_CONFIG_MODULE));
209 module_clean_up(get_module(BT_UTILS_MODULE));
210 module_clean_up(get_module(OSI_MODULE));
211 module_management_stop();
212 LOG_INFO(LOG_TAG, "%s finished", __func__);
213
214 cleanup:;
215 semaphore_t *semaphore = (semaphore_t *)context;
216 if (semaphore)
217 semaphore_post(semaphore);
218 }
219
event_signal_stack_up(UNUSED_ATTR void * context)220 static void event_signal_stack_up(UNUSED_ATTR void *context) {
221 // Notify BTIF connect queue that we've brought up the stack. It's
222 // now time to dispatch all the pending profile connect requests.
223 btif_queue_connect_next();
224 HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON);
225 }
226
event_signal_stack_down(UNUSED_ATTR void * context)227 static void event_signal_stack_down(UNUSED_ATTR void *context) {
228 HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF);
229 future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS);
230 }
231
ensure_manager_initialized(void)232 static 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
243 static 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
stack_manager_get_interface()252 const stack_manager_t *stack_manager_get_interface() {
253 ensure_manager_initialized();
254 return &interface;
255 }
256
stack_manager_get_hack_future()257 future_t *stack_manager_get_hack_future() {
258 return hack_future;
259 }
260