• 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 "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 "bt_utils.h"
37 #include "btif_config.h"
38 #include "btif_profile_queue.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
57 // future
58 static future_t* hack_future;
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) { return stack_is_running; }
93 
94 // Internal functions
95 
96 // Synchronous function to initialize the stack
event_init_stack(void * context)97 static void event_init_stack(void* context) {
98   semaphore_t* semaphore = (semaphore_t*)context;
99 
100   LOG_INFO(LOG_TAG, "%s is initializing the stack", __func__);
101 
102   if (stack_is_initialized) {
103     LOG_INFO(LOG_TAG, "%s found the stack already in initialized state",
104              __func__);
105   } else {
106     module_management_start();
107 
108     module_init(get_module(OSI_MODULE));
109     module_init(get_module(BT_UTILS_MODULE));
110     module_init(get_module(BTIF_CONFIG_MODULE));
111     btif_init_bluetooth();
112 
113     // stack init is synchronous, so no waiting necessary here
114     stack_is_initialized = true;
115   }
116 
117   LOG_INFO(LOG_TAG, "%s finished", __func__);
118 
119   if (semaphore) semaphore_post(semaphore);
120 }
121 
ensure_stack_is_initialized(void)122 static void ensure_stack_is_initialized(void) {
123   if (!stack_is_initialized) {
124     LOG_WARN(LOG_TAG, "%s found the stack was uninitialized. Initializing now.",
125              __func__);
126     // No semaphore needed since we are calling it directly
127     event_init_stack(NULL);
128   }
129 }
130 
131 // Synchronous function to start up the stack
event_start_up_stack(UNUSED_ATTR void * context)132 static void event_start_up_stack(UNUSED_ATTR void* context) {
133   if (stack_is_running) {
134     LOG_INFO(LOG_TAG, "%s stack already brought up", __func__);
135     return;
136   }
137 
138   ensure_stack_is_initialized();
139 
140   LOG_INFO(LOG_TAG, "%s is bringing up the stack", __func__);
141   future_t* local_hack_future = future_new();
142   hack_future = local_hack_future;
143 
144   // Include this for now to put btif config into a shutdown-able state
145   module_start_up(get_module(BTIF_CONFIG_MODULE));
146   bte_main_enable();
147 
148   if (future_await(local_hack_future) != FUTURE_SUCCESS) {
149     LOG_ERROR(LOG_TAG, "%s failed to start up the stack", __func__);
150     stack_is_running = true;  // So stack shutdown actually happens
151     event_shut_down_stack(NULL);
152     return;
153   }
154 
155   stack_is_running = true;
156   LOG_INFO(LOG_TAG, "%s finished", __func__);
157   btif_thread_post(event_signal_stack_up, NULL);
158 }
159 
160 // Synchronous function to shut down the stack
event_shut_down_stack(UNUSED_ATTR void * context)161 static void event_shut_down_stack(UNUSED_ATTR void* context) {
162   if (!stack_is_running) {
163     LOG_INFO(LOG_TAG, "%s stack is already brought down", __func__);
164     return;
165   }
166 
167   LOG_INFO(LOG_TAG, "%s is bringing down the stack", __func__);
168   future_t* local_hack_future = future_new();
169   hack_future = local_hack_future;
170   stack_is_running = false;
171 
172   btif_disable_bluetooth();
173   module_shut_down(get_module(BTIF_CONFIG_MODULE));
174 
175   future_await(local_hack_future);
176   module_shut_down(get_module(CONTROLLER_MODULE));  // Doesn't do any work, just
177                                                     // puts it in a restartable
178                                                     // 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,
189              "%s found the stack was still running. Bringing it down now.",
190              __func__);
191     event_shut_down_stack(NULL);
192   }
193 }
194 
195 // Synchronous function to clean up the stack
event_clean_up_stack(void * context)196 static void event_clean_up_stack(void* context) {
197   future_t* local_hack_future;
198 
199   if (!stack_is_initialized) {
200     LOG_INFO(LOG_TAG, "%s found the stack already in a clean state", __func__);
201     goto cleanup;
202   }
203 
204   ensure_stack_is_not_running();
205 
206   LOG_INFO(LOG_TAG, "%s is cleaning up the stack", __func__);
207   local_hack_future = future_new();
208   hack_future = local_hack_future;
209   stack_is_initialized = false;
210 
211   btif_cleanup_bluetooth();
212   module_clean_up(get_module(BTIF_CONFIG_MODULE));
213   module_clean_up(get_module(BT_UTILS_MODULE));
214   module_clean_up(get_module(OSI_MODULE));
215   module_management_stop();
216   LOG_INFO(LOG_TAG, "%s finished", __func__);
217 
218 cleanup:;
219   semaphore_t* semaphore = (semaphore_t*)context;
220   if (semaphore) semaphore_post(semaphore);
221 }
222 
event_signal_stack_up(UNUSED_ATTR void * context)223 static void event_signal_stack_up(UNUSED_ATTR void* context) {
224   // Notify BTIF connect queue that we've brought up the stack. It's
225   // now time to dispatch all the pending profile connect requests.
226   btif_queue_connect_next();
227   HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON);
228 }
229 
event_signal_stack_down(UNUSED_ATTR void * context)230 static void event_signal_stack_down(UNUSED_ATTR void* context) {
231   HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF);
232   future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS);
233 }
234 
ensure_manager_initialized(void)235 static void ensure_manager_initialized(void) {
236   if (management_thread) return;
237 
238   management_thread = thread_new("stack_manager");
239   if (!management_thread) {
240     LOG_ERROR(LOG_TAG, "%s unable to create stack management thread", __func__);
241     return;
242   }
243 }
244 
245 static const stack_manager_t interface = {init_stack, start_up_stack_async,
246                                           shut_down_stack_async, clean_up_stack,
247 
248                                           get_stack_is_running};
249 
stack_manager_get_interface()250 const stack_manager_t* stack_manager_get_interface() {
251   ensure_manager_initialized();
252   return &interface;
253 }
254 
stack_manager_get_hack_future()255 future_t* stack_manager_get_hack_future() { return hack_future; }
256