OSDN Git Service

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