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