1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.btservice;
18 
19 import android.bluetooth.BluetoothAdapter;
20 import android.os.Message;
21 import android.util.Log;
22 
23 import com.android.bluetooth.statemachine.State;
24 import com.android.bluetooth.statemachine.StateMachine;
25 
26 /**
27  * This state machine handles Bluetooth Adapter State.
28  * Stable States:
29  *      {@link OffState}: Initial State
30  *      {@link BleOnState} : Bluetooth Low Energy, Including GATT, is on
31  *      {@link OnState} : Bluetooth is on (All supported profiles)
32  *
33  * Transition States:
34  *      {@link TurningBleOnState} : OffState to BleOnState
35  *      {@link TurningBleOffState} : BleOnState to OffState
36  *      {@link TurningOnState} : BleOnState to OnState
37  *      {@link TurningOffState} : OnState to BleOnState
38  *
39  *        +------   Off  <-----+
40  *        |                    |
41  *        v                    |
42  * TurningBleOn   TO--->   TurningBleOff
43  *        |                  ^ ^
44  *        |                  | |
45  *        +----->        ----+ |
46  *                 BleOn       |
47  *        +------        <---+ O
48  *        v                  | T
49  *    TurningOn  TO---->  TurningOff
50  *        |                    ^
51  *        |                    |
52  *        +----->   On   ------+
53  *
54  */
55 
56 final class AdapterState extends StateMachine {
57     private static final boolean DBG = true;
58     private static final String TAG = AdapterState.class.getSimpleName();
59 
60     static final int USER_TURN_ON = 1;
61     static final int USER_TURN_OFF = 2;
62     static final int BLE_TURN_ON = 3;
63     static final int BLE_TURN_OFF = 4;
64     static final int BREDR_STARTED = 5;
65     static final int BREDR_STOPPED = 6;
66     static final int BLE_STARTED = 7;
67     static final int BLE_STOPPED = 8;
68     static final int BREDR_START_TIMEOUT = 9;
69     static final int BREDR_STOP_TIMEOUT = 10;
70     static final int BLE_STOP_TIMEOUT = 11;
71     static final int BLE_START_TIMEOUT = 12;
72 
73     static final int BLE_START_TIMEOUT_DELAY = 4000;
74     static final int BLE_STOP_TIMEOUT_DELAY = 1000;
75     static final int BREDR_START_TIMEOUT_DELAY = 4000;
76     static final int BREDR_STOP_TIMEOUT_DELAY = 4000;
77 
78     private AdapterService mAdapterService;
79     private TurningOnState mTurningOnState = new TurningOnState();
80     private TurningBleOnState mTurningBleOnState = new TurningBleOnState();
81     private TurningOffState mTurningOffState = new TurningOffState();
82     private TurningBleOffState mTurningBleOffState = new TurningBleOffState();
83     private OnState mOnState = new OnState();
84     private OffState mOffState = new OffState();
85     private BleOnState mBleOnState = new BleOnState();
86 
87     private int mPrevState = BluetoothAdapter.STATE_OFF;
88 
AdapterState(AdapterService service)89     private AdapterState(AdapterService service) {
90         super(TAG);
91         addState(mOnState);
92         addState(mBleOnState);
93         addState(mOffState);
94         addState(mTurningOnState);
95         addState(mTurningOffState);
96         addState(mTurningBleOnState);
97         addState(mTurningBleOffState);
98         mAdapterService = service;
99         setInitialState(mOffState);
100     }
101 
messageString(int message)102     private String messageString(int message) {
103         switch (message) {
104             case BLE_TURN_ON: return "BLE_TURN_ON";
105             case USER_TURN_ON: return "USER_TURN_ON";
106             case BREDR_STARTED: return "BREDR_STARTED";
107             case BLE_STARTED: return "BLE_STARTED";
108             case USER_TURN_OFF: return "USER_TURN_OFF";
109             case BLE_TURN_OFF: return "BLE_TURN_OFF";
110             case BLE_STOPPED: return "BLE_STOPPED";
111             case BREDR_STOPPED: return "BREDR_STOPPED";
112             case BLE_START_TIMEOUT: return "BLE_START_TIMEOUT";
113             case BLE_STOP_TIMEOUT: return "BLE_STOP_TIMEOUT";
114             case BREDR_START_TIMEOUT: return "BREDR_START_TIMEOUT";
115             case BREDR_STOP_TIMEOUT: return "BREDR_STOP_TIMEOUT";
116             default: return "Unknown message (" + message + ")";
117         }
118     }
119 
make(AdapterService service)120     public static AdapterState make(AdapterService service) {
121         Log.d(TAG, "make() - Creating AdapterState");
122         AdapterState as = new AdapterState(service);
123         as.start();
124         return as;
125     }
126 
doQuit()127     public void doQuit() {
128         quitNow();
129     }
130 
cleanup()131     private void cleanup() {
132         if (mAdapterService != null) {
133             mAdapterService = null;
134         }
135     }
136 
137     @Override
onQuitting()138     protected void onQuitting() {
139         cleanup();
140     }
141 
142     @Override
getLogRecString(Message msg)143     protected String getLogRecString(Message msg) {
144         return messageString(msg.what);
145     }
146 
147     private abstract class BaseAdapterState extends State {
148 
getStateValue()149         abstract int getStateValue();
150 
151         @Override
enter()152         public void enter() {
153             int currState = getStateValue();
154             infoLog("entered ");
155             mAdapterService.updateAdapterState(mPrevState, currState);
156             mPrevState = currState;
157         }
158 
infoLog(String msg)159         void infoLog(String msg) {
160             if (DBG) {
161                 Log.i(TAG, BluetoothAdapter.nameForState(getStateValue()) + " : " + msg);
162             }
163         }
164 
errorLog(String msg)165         void errorLog(String msg) {
166             Log.e(TAG, BluetoothAdapter.nameForState(getStateValue()) + " : " + msg);
167         }
168     }
169 
170     private class OffState extends BaseAdapterState {
171 
172         @Override
getStateValue()173         int getStateValue() {
174             return BluetoothAdapter.STATE_OFF;
175         }
176 
177         @Override
processMessage(Message msg)178         public boolean processMessage(Message msg) {
179             switch (msg.what) {
180                 case BLE_TURN_ON:
181                     transitionTo(mTurningBleOnState);
182                     break;
183 
184                 default:
185                     infoLog("Unhandled message - " + messageString(msg.what));
186                     return false;
187             }
188             return true;
189         }
190     }
191 
192     private class BleOnState extends BaseAdapterState {
193 
194         @Override
getStateValue()195         int getStateValue() {
196             return BluetoothAdapter.STATE_BLE_ON;
197         }
198 
199         @Override
processMessage(Message msg)200         public boolean processMessage(Message msg) {
201             switch (msg.what) {
202                 case USER_TURN_ON:
203                     transitionTo(mTurningOnState);
204                     break;
205 
206                 case BLE_TURN_OFF:
207                     transitionTo(mTurningBleOffState);
208                     break;
209 
210                 default:
211                     infoLog("Unhandled message - " + messageString(msg.what));
212                     return false;
213             }
214             return true;
215         }
216     }
217 
218     private class OnState extends BaseAdapterState {
219 
220         @Override
getStateValue()221         int getStateValue() {
222             return BluetoothAdapter.STATE_ON;
223         }
224 
225         @Override
processMessage(Message msg)226         public boolean processMessage(Message msg) {
227             switch (msg.what) {
228                 case USER_TURN_OFF:
229                     transitionTo(mTurningOffState);
230                     break;
231 
232                 default:
233                     infoLog("Unhandled message - " + messageString(msg.what));
234                     return false;
235             }
236             return true;
237         }
238     }
239 
240     private class TurningBleOnState extends BaseAdapterState {
241 
242         @Override
getStateValue()243         int getStateValue() {
244             return BluetoothAdapter.STATE_BLE_TURNING_ON;
245         }
246 
247         @Override
enter()248         public void enter() {
249             super.enter();
250             sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
251             mAdapterService.bringUpBle();
252         }
253 
254         @Override
exit()255         public void exit() {
256             removeMessages(BLE_START_TIMEOUT);
257             super.exit();
258         }
259 
260         @Override
processMessage(Message msg)261         public boolean processMessage(Message msg) {
262             switch (msg.what) {
263                 case BLE_STARTED:
264                     transitionTo(mBleOnState);
265                     break;
266 
267                 case BLE_START_TIMEOUT:
268                     errorLog(messageString(msg.what));
269                     transitionTo(mTurningBleOffState);
270                     break;
271 
272                 default:
273                     infoLog("Unhandled message - " + messageString(msg.what));
274                     return false;
275             }
276             return true;
277         }
278     }
279 
280     private class TurningOnState extends BaseAdapterState {
281 
282         @Override
getStateValue()283         int getStateValue() {
284             return BluetoothAdapter.STATE_TURNING_ON;
285         }
286 
287         @Override
enter()288         public void enter() {
289             super.enter();
290             sendMessageDelayed(BREDR_START_TIMEOUT, BREDR_START_TIMEOUT_DELAY);
291             mAdapterService.startProfileServices();
292         }
293 
294         @Override
exit()295         public void exit() {
296             removeMessages(BREDR_START_TIMEOUT);
297             super.exit();
298         }
299 
300         @Override
processMessage(Message msg)301         public boolean processMessage(Message msg) {
302             switch (msg.what) {
303                 case BREDR_STARTED:
304                     transitionTo(mOnState);
305                     break;
306 
307                 case BREDR_START_TIMEOUT:
308                     errorLog(messageString(msg.what));
309                     transitionTo(mTurningOffState);
310                     break;
311 
312                 default:
313                     infoLog("Unhandled message - " + messageString(msg.what));
314                     return false;
315             }
316             return true;
317         }
318     }
319 
320     private class TurningOffState extends BaseAdapterState {
321 
322         @Override
getStateValue()323         int getStateValue() {
324             return BluetoothAdapter.STATE_TURNING_OFF;
325         }
326 
327         @Override
enter()328         public void enter() {
329             super.enter();
330             sendMessageDelayed(BREDR_STOP_TIMEOUT, BREDR_STOP_TIMEOUT_DELAY);
331             mAdapterService.stopProfileServices();
332         }
333 
334         @Override
exit()335         public void exit() {
336             removeMessages(BREDR_STOP_TIMEOUT);
337             super.exit();
338         }
339 
340         @Override
processMessage(Message msg)341         public boolean processMessage(Message msg) {
342             switch (msg.what) {
343                 case BREDR_STOPPED:
344                     transitionTo(mBleOnState);
345                     break;
346 
347                 case BREDR_STOP_TIMEOUT:
348                     errorLog(messageString(msg.what));
349                     transitionTo(mTurningBleOffState);
350                     break;
351 
352                 default:
353                     infoLog("Unhandled message - " + messageString(msg.what));
354                     return false;
355             }
356             return true;
357         }
358     }
359 
360     private class TurningBleOffState extends BaseAdapterState {
361 
362         @Override
getStateValue()363         int getStateValue() {
364             return BluetoothAdapter.STATE_BLE_TURNING_OFF;
365         }
366 
367         @Override
enter()368         public void enter() {
369             super.enter();
370             sendMessageDelayed(BLE_STOP_TIMEOUT, BLE_STOP_TIMEOUT_DELAY);
371             mAdapterService.bringDownBle();
372         }
373 
374         @Override
exit()375         public void exit() {
376             removeMessages(BLE_STOP_TIMEOUT);
377             super.exit();
378         }
379 
380         @Override
processMessage(Message msg)381         public boolean processMessage(Message msg) {
382             switch (msg.what) {
383                 case BLE_STOPPED:
384                     transitionTo(mOffState);
385                     break;
386 
387                 case BLE_STOP_TIMEOUT:
388                     errorLog(messageString(msg.what));
389                     transitionTo(mOffState);
390                     break;
391 
392                 default:
393                     infoLog("Unhandled message - " + messageString(msg.what));
394                     return false;
395             }
396             return true;
397         }
398     }
399 }
400