• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
init_stack(void)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 
start_up_stack_async(void)72 static void start_up_stack_async(void) {
73   thread_post(management_thread, event_start_up_stack, NULL);
74 }
75 
shut_down_stack_async(void)76 static void shut_down_stack_async(void) {
77   thread_post(management_thread, event_shut_down_stack, NULL);
78 }
79 
clean_up_stack_async(void)80 static void clean_up_stack_async(void) {
81   thread_post(management_thread, event_clean_up_stack, NULL);
82 }
83 
get_stack_is_running(void)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
event_init_stack(void * context)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 
ensure_stack_is_initialized(void)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
event_start_up_stack(UNUSED_ATTR void * context)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
event_shut_down_stack(UNUSED_ATTR void * context)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 
ensure_stack_is_not_running(void)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
event_clean_up_stack(UNUSED_ATTR void * context)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 
event_signal_stack_up(UNUSED_ATTR void * context)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 
event_signal_stack_down(UNUSED_ATTR void * context)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 
ensure_manager_initialized(void)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 
stack_manager_get_interface()226 const stack_manager_t *stack_manager_get_interface() {
227   ensure_manager_initialized();
228   return &interface;
229 }
230 
stack_manager_get_hack_future()231 future_t *stack_manager_get_hack_future() {
232   return hack_future;
233 }
234