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