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 final TurningOnState mTurningOnState = new TurningOnState(); 71 private final TurningBleOnState mTurningBleOnState = new TurningBleOnState(); 72 private final TurningOffState mTurningOffState = new TurningOffState(); 73 private final TurningBleOffState mTurningBleOffState = new TurningBleOffState(); 74 private final OnState mOnState = new OnState(); 75 private final OffState mOffState = new OffState(); 76 private final 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 static 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 int prevState = mPrevState; 176 super.enter(); 177 if (prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) { 178 mAdapterService.cleanup(); 179 } 180 } 181 182 @Override processMessage(Message msg)183 public boolean processMessage(Message msg) { 184 switch (msg.what) { 185 case BLE_TURN_ON: 186 transitionTo(mTurningBleOnState); 187 break; 188 189 default: 190 infoLog("Unhandled message - " + messageString(msg.what)); 191 return false; 192 } 193 return true; 194 } 195 } 196 197 private class BleOnState extends BaseAdapterState { 198 199 @Override getStateValue()200 int getStateValue() { 201 return BluetoothAdapter.STATE_BLE_ON; 202 } 203 204 @Override processMessage(Message msg)205 public boolean processMessage(Message msg) { 206 switch (msg.what) { 207 case USER_TURN_ON: 208 transitionTo(mTurningOnState); 209 break; 210 211 case BLE_TURN_OFF: 212 transitionTo(mTurningBleOffState); 213 break; 214 215 default: 216 infoLog("Unhandled message - " + messageString(msg.what)); 217 return false; 218 } 219 return true; 220 } 221 } 222 223 private class OnState extends BaseAdapterState { 224 225 @Override getStateValue()226 int getStateValue() { 227 return BluetoothAdapter.STATE_ON; 228 } 229 230 @Override processMessage(Message msg)231 public boolean processMessage(Message msg) { 232 switch (msg.what) { 233 case USER_TURN_OFF: 234 transitionTo(mTurningOffState); 235 break; 236 237 default: 238 infoLog("Unhandled message - " + messageString(msg.what)); 239 return false; 240 } 241 return true; 242 } 243 } 244 245 private class TurningBleOnState extends BaseAdapterState { 246 247 @Override getStateValue()248 int getStateValue() { 249 return BluetoothAdapter.STATE_BLE_TURNING_ON; 250 } 251 252 @Override enter()253 public void enter() { 254 super.enter(); 255 final int timeoutDelay = 256 SystemProperties.getInt( 257 BLE_START_TIMEOUT_DELAY_PROPERTY, BLE_START_TIMEOUT_DELAY); 258 Log.d(TAG, "Start Timeout Delay: " + timeoutDelay); 259 sendMessageDelayed(BLE_START_TIMEOUT, timeoutDelay); 260 mAdapterService.bringUpBle(); 261 } 262 263 @Override exit()264 public void exit() { 265 removeMessages(BLE_START_TIMEOUT); 266 super.exit(); 267 } 268 269 @Override processMessage(Message msg)270 public boolean processMessage(Message msg) { 271 switch (msg.what) { 272 case BLE_STARTED: 273 transitionTo(mBleOnState); 274 break; 275 276 case BLE_START_TIMEOUT: 277 errorLog(messageString(msg.what)); 278 transitionTo(mTurningBleOffState); 279 break; 280 281 default: 282 infoLog("Unhandled message - " + messageString(msg.what)); 283 return false; 284 } 285 return true; 286 } 287 } 288 289 private class TurningOnState extends BaseAdapterState { 290 291 @Override getStateValue()292 int getStateValue() { 293 return BluetoothAdapter.STATE_TURNING_ON; 294 } 295 296 @Override enter()297 public void enter() { 298 super.enter(); 299 sendMessageDelayed(BREDR_START_TIMEOUT, BREDR_START_TIMEOUT_DELAY); 300 mAdapterService.startProfileServices(); 301 } 302 303 @Override exit()304 public void exit() { 305 removeMessages(BREDR_START_TIMEOUT); 306 super.exit(); 307 } 308 309 @Override processMessage(Message msg)310 public boolean processMessage(Message msg) { 311 switch (msg.what) { 312 case BREDR_STARTED: 313 transitionTo(mOnState); 314 break; 315 316 case BREDR_START_TIMEOUT: 317 errorLog(messageString(msg.what)); 318 transitionTo(mTurningOffState); 319 break; 320 321 default: 322 infoLog("Unhandled message - " + messageString(msg.what)); 323 return false; 324 } 325 return true; 326 } 327 } 328 329 private class TurningOffState extends BaseAdapterState { 330 331 @Override getStateValue()332 int getStateValue() { 333 return BluetoothAdapter.STATE_TURNING_OFF; 334 } 335 336 @Override enter()337 public void enter() { 338 super.enter(); 339 sendMessageDelayed(BREDR_STOP_TIMEOUT, BREDR_STOP_TIMEOUT_DELAY); 340 mAdapterService.stopProfileServices(); 341 } 342 343 @Override exit()344 public void exit() { 345 removeMessages(BREDR_STOP_TIMEOUT); 346 if (Flags.disconnectAclsByBredrDisabled()) { 347 if (mAdapterService != null) { 348 Log.i(TAG, "Disconnecting all ACLs with BREDR Stopped"); 349 mAdapterService.disconnectAllAcls(); 350 } 351 } 352 353 super.exit(); 354 } 355 356 @Override processMessage(Message msg)357 public boolean processMessage(Message msg) { 358 switch (msg.what) { 359 case BREDR_STOPPED: 360 transitionTo(mBleOnState); 361 break; 362 363 case BREDR_STOP_TIMEOUT: 364 errorLog(messageString(msg.what)); 365 transitionTo(mTurningBleOffState); 366 break; 367 368 default: 369 infoLog("Unhandled message - " + messageString(msg.what)); 370 return false; 371 } 372 return true; 373 } 374 } 375 376 private class TurningBleOffState extends BaseAdapterState { 377 378 @Override getStateValue()379 int getStateValue() { 380 return BluetoothAdapter.STATE_BLE_TURNING_OFF; 381 } 382 383 @Override enter()384 public void enter() { 385 super.enter(); 386 final int timeoutDelay = 387 SystemProperties.getInt( 388 BLE_STOP_TIMEOUT_DELAY_PROPERTY, BLE_STOP_TIMEOUT_DELAY); 389 Log.d(TAG, "Stop Timeout Delay: " + timeoutDelay); 390 sendMessageDelayed(BLE_STOP_TIMEOUT, timeoutDelay); 391 mAdapterService.bringDownBle(); 392 } 393 394 @Override exit()395 public void exit() { 396 removeMessages(BLE_STOP_TIMEOUT); 397 super.exit(); 398 } 399 400 @Override processMessage(Message msg)401 public boolean processMessage(Message msg) { 402 switch (msg.what) { 403 case BLE_STOPPED: 404 transitionTo(mOffState); 405 break; 406 407 case BLE_STOP_TIMEOUT: 408 errorLog(messageString(msg.what)); 409 transitionTo(mOffState); 410 break; 411 412 default: 413 infoLog("Unhandled message - " + messageString(msg.what)); 414 return false; 415 } 416 return true; 417 } 418 } 419 } 420