AdapterState.java revision eb7b90f5b93db1230a5b64caa3d8d05a642e33a6
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 17package com.android.bluetooth.btservice; 18 19import android.bluetooth.BluetoothAdapter; 20import android.os.Message; 21import android.os.UserManager; 22import android.util.Log; 23 24import com.android.internal.util.State; 25import com.android.internal.util.StateMachine; 26 27/** 28 * This state machine handles Bluetooth Adapter State. 29 * States: 30 * {@link OnState} : Bluetooth is on at this state 31 * {@link OffState}: Bluetooth is off at this state. This is the initial 32 * state. 33 * {@link PendingCommandState} : An enable / disable operation is pending. 34 * TODO(BT): Add per process on state. 35 */ 36 37final class AdapterState extends StateMachine { 38 private static final boolean DBG = true; 39 private static final boolean VDBG = true; 40 private static final String TAG = "BluetoothAdapterState"; 41 42 static final int BLE_TURN_ON = 0; 43 static final int USER_TURN_ON = 1; 44 static final int BREDR_STARTED=2; 45 static final int ENABLED_READY = 3; 46 static final int BLE_STARTED=4; 47 48 static final int USER_TURN_OFF = 20; 49 static final int BEGIN_DISABLE = 21; 50 static final int ALL_DEVICES_DISCONNECTED = 22; 51 static final int BLE_TURN_OFF = 23; 52 53 static final int DISABLED = 24; 54 static final int BLE_STOPPED=25; 55 static final int BREDR_STOPPED = 26; 56 57 static final int BREDR_START_TIMEOUT = 100; 58 static final int ENABLE_TIMEOUT = 101; 59 static final int DISABLE_TIMEOUT = 103; 60 static final int BLE_STOP_TIMEOUT = 104; 61 static final int SET_SCAN_MODE_TIMEOUT = 105; 62 static final int BLE_START_TIMEOUT = 106; 63 static final int BREDR_STOP_TIMEOUT = 107; 64 65 static final int USER_TURN_OFF_DELAY_MS=500; 66 67 //TODO: tune me 68 private static final int ENABLE_TIMEOUT_DELAY = 12000; 69 private static final int DISABLE_TIMEOUT_DELAY = 8000; 70 private static final int BREDR_START_TIMEOUT_DELAY = 4000; 71 //BLE_START_TIMEOUT can happen quickly as it just a start gattservice 72 private static final int BLE_START_TIMEOUT_DELAY = 2000; //To start GattService 73 private static final int BLE_STOP_TIMEOUT_DELAY = 2000; 74 //BREDR_STOP_TIMEOUT can < STOP_TIMEOUT 75 private static final int BREDR_STOP_TIMEOUT_DELAY = 4000; 76 private static final int PROPERTY_OP_DELAY =2000; 77 private AdapterService mAdapterService; 78 private AdapterProperties mAdapterProperties; 79 private PendingCommandState mPendingCommandState = new PendingCommandState(); 80 private OnState mOnState = new OnState(); 81 private OffState mOffState = new OffState(); 82 private BleOnState mBleOnState = new BleOnState(); 83 84 public boolean isTurningOn() { 85 boolean isTurningOn= mPendingCommandState.isTurningOn(); 86 verboseLog("isTurningOn()=" + isTurningOn); 87 return isTurningOn; 88 } 89 90 public boolean isBleTurningOn() { 91 boolean isBleTurningOn= mPendingCommandState.isBleTurningOn(); 92 verboseLog("isBleTurningOn()=" + isBleTurningOn); 93 return isBleTurningOn; 94 } 95 96 public boolean isBleTurningOff() { 97 boolean isBleTurningOff = mPendingCommandState.isBleTurningOff(); 98 verboseLog("isBleTurningOff()=" + isBleTurningOff); 99 return isBleTurningOff; 100 } 101 102 public boolean isTurningOff() { 103 boolean isTurningOff= mPendingCommandState.isTurningOff(); 104 verboseLog("isTurningOff()=" + isTurningOff); 105 return isTurningOff; 106 } 107 108 private AdapterState(AdapterService service, AdapterProperties adapterProperties) { 109 super("BluetoothAdapterState:"); 110 addState(mOnState); 111 addState(mBleOnState); 112 addState(mOffState); 113 addState(mPendingCommandState); 114 mAdapterService = service; 115 mAdapterProperties = adapterProperties; 116 setInitialState(mOffState); 117 } 118 119 public static AdapterState make(AdapterService service, AdapterProperties adapterProperties) { 120 Log.d(TAG, "make() - Creating AdapterState"); 121 AdapterState as = new AdapterState(service, adapterProperties); 122 as.start(); 123 return as; 124 } 125 126 public void doQuit() { 127 quitNow(); 128 } 129 130 public void cleanup() { 131 if(mAdapterProperties != null) 132 mAdapterProperties = null; 133 if(mAdapterService != null) 134 mAdapterService = null; 135 } 136 137 private class OffState extends State { 138 @Override 139 public void enter() { 140 infoLog("Entering OffState"); 141 } 142 143 @Override 144 public boolean processMessage(Message msg) { 145 AdapterService adapterService = mAdapterService; 146 if (adapterService == null) { 147 errorLog("Received message in OffState after cleanup: " + msg.what); 148 return false; 149 } 150 151 debugLog("Current state: OFF, message: " + msg.what); 152 153 switch(msg.what) { 154 case BLE_TURN_ON: 155 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON); 156 mPendingCommandState.setBleTurningOn(true); 157 transitionTo(mPendingCommandState); 158 sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY); 159 adapterService.BleOnProcessStart(); 160 break; 161 162 case USER_TURN_OFF: 163 //TODO: Handle case of service started and stopped without enable 164 break; 165 166 default: 167 return false; 168 } 169 return true; 170 } 171 } 172 173 private class BleOnState extends State { 174 @Override 175 public void enter() { 176 infoLog("Entering BleOnState"); 177 } 178 179 @Override 180 public boolean processMessage(Message msg) { 181 182 AdapterService adapterService = mAdapterService; 183 AdapterProperties adapterProperties = mAdapterProperties; 184 if ((adapterService == null) || (adapterProperties == null)) { 185 errorLog("Received message in BleOnState after cleanup: " + msg.what); 186 return false; 187 } 188 189 debugLog("Current state: BLE ON, message: " + msg.what); 190 191 switch(msg.what) { 192 case USER_TURN_ON: 193 notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON); 194 mPendingCommandState.setTurningOn(true); 195 transitionTo(mPendingCommandState); 196 sendMessageDelayed(BREDR_START_TIMEOUT, BREDR_START_TIMEOUT_DELAY); 197 adapterService.startCoreServices(); 198 break; 199 200 case USER_TURN_OFF: 201 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF); 202 mPendingCommandState.setBleTurningOff(true); 203 adapterProperties.onBleDisable(); 204 transitionTo(mPendingCommandState); 205 sendMessageDelayed(DISABLE_TIMEOUT, DISABLE_TIMEOUT_DELAY); 206 boolean ret = adapterService.disableNative(); 207 if (!ret) { 208 removeMessages(DISABLE_TIMEOUT); 209 errorLog("Error while calling disableNative"); 210 //FIXME: what about post enable services 211 mPendingCommandState.setBleTurningOff(false); 212 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON); 213 } 214 break; 215 216 default: 217 return false; 218 } 219 return true; 220 } 221 } 222 223 private class OnState extends State { 224 @Override 225 public void enter() { 226 infoLog("Entering OnState"); 227 228 AdapterService adapterService = mAdapterService; 229 if (adapterService == null) { 230 errorLog("Entered OnState after cleanup"); 231 return; 232 } 233 adapterService.updateUuids(); 234 adapterService.autoConnect(); 235 } 236 237 @Override 238 public boolean processMessage(Message msg) { 239 AdapterProperties adapterProperties = mAdapterProperties; 240 if (adapterProperties == null) { 241 errorLog("Received message in OnState after cleanup: " + msg.what); 242 return false; 243 } 244 245 debugLog("Current state: ON, message: " + msg.what); 246 247 switch(msg.what) { 248 case BLE_TURN_OFF: 249 notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_OFF); 250 mPendingCommandState.setTurningOff(true); 251 transitionTo(mPendingCommandState); 252 253 // Invoke onBluetoothDisable which shall trigger a 254 // setScanMode to SCAN_MODE_NONE 255 Message m = obtainMessage(SET_SCAN_MODE_TIMEOUT); 256 sendMessageDelayed(m, PROPERTY_OP_DELAY); 257 adapterProperties.onBluetoothDisable(); 258 break; 259 260 case USER_TURN_ON: 261 break; 262 263 default: 264 return false; 265 } 266 return true; 267 } 268 } 269 270 private class PendingCommandState extends State { 271 private boolean mIsTurningOn; 272 private boolean mIsTurningOff; 273 private boolean mIsBleTurningOn; 274 private boolean mIsBleTurningOff; 275 276 public void enter() { 277 infoLog("Entering PendingCommandState"); 278 } 279 280 public void setTurningOn(boolean isTurningOn) { 281 mIsTurningOn = isTurningOn; 282 } 283 284 public boolean isTurningOn() { 285 return mIsTurningOn; 286 } 287 288 public void setTurningOff(boolean isTurningOff) { 289 mIsTurningOff = isTurningOff; 290 } 291 292 public boolean isTurningOff() { 293 return mIsTurningOff; 294 } 295 296 public void setBleTurningOn(boolean isBleTurningOn) { 297 mIsBleTurningOn = isBleTurningOn; 298 } 299 300 public boolean isBleTurningOn() { 301 return mIsBleTurningOn; 302 } 303 304 public void setBleTurningOff(boolean isBleTurningOff) { 305 mIsBleTurningOff = isBleTurningOff; 306 } 307 308 public boolean isBleTurningOff() { 309 return mIsBleTurningOff; 310 } 311 312 @Override 313 public boolean processMessage(Message msg) { 314 315 boolean isTurningOn= isTurningOn(); 316 boolean isTurningOff = isTurningOff(); 317 boolean isBleTurningOn = isBleTurningOn(); 318 boolean isBleTurningOff = isBleTurningOff(); 319 320 AdapterService adapterService = mAdapterService; 321 AdapterProperties adapterProperties = mAdapterProperties; 322 if ((adapterService == null) || (adapterProperties == null)) { 323 errorLog("Received message in PendingCommandState after cleanup: " + msg.what); 324 return false; 325 } 326 327 debugLog("Current state: PENDING_COMMAND, message: " + msg.what); 328 329 switch (msg.what) { 330 case USER_TURN_ON: 331 if (isBleTurningOff || isTurningOff) { //TODO:do we need to send it after ble turn off also?? 332 infoLog("Deferring USER_TURN_ON request..."); 333 deferMessage(msg); 334 } 335 break; 336 337 case USER_TURN_OFF: 338 if (isTurningOn || isBleTurningOn) { 339 infoLog("Deferring USER_TURN_OFF request..."); 340 deferMessage(msg); 341 } 342 break; 343 344 case BLE_TURN_ON: 345 if (isTurningOff || isBleTurningOff) { 346 infoLog("Deferring BLE_TURN_ON request..."); 347 deferMessage(msg); 348 } 349 break; 350 351 case BLE_TURN_OFF: 352 if (isTurningOn || isBleTurningOn) { 353 infoLog("Deferring BLE_TURN_OFF request..."); 354 deferMessage(msg); 355 } 356 break; 357 358 case BLE_STARTED: 359 //Remove start timeout 360 removeMessages(BLE_START_TIMEOUT); 361 362 //Enable 363 boolean isGuest = UserManager.get(mAdapterService).isGuestUser(); 364 if (!adapterService.enableNative(isGuest)) { 365 errorLog("Error while turning Bluetooth on"); 366 notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); 367 transitionTo(mOffState); 368 } else { 369 sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY); 370 } 371 break; 372 373 case BREDR_STARTED: 374 //Remove start timeout 375 removeMessages(BREDR_START_TIMEOUT); 376 adapterProperties.onBluetoothReady(); 377 mPendingCommandState.setTurningOn(false); 378 transitionTo(mOnState); 379 notifyAdapterStateChange(BluetoothAdapter.STATE_ON); 380 break; 381 382 case ENABLED_READY: 383 removeMessages(ENABLE_TIMEOUT); 384 mPendingCommandState.setBleTurningOn(false); 385 transitionTo(mBleOnState); 386 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON); 387 break; 388 389 case SET_SCAN_MODE_TIMEOUT: 390 warningLog("Timeout while setting scan mode. Continuing with disable..."); 391 //Fall through 392 case BEGIN_DISABLE: 393 removeMessages(SET_SCAN_MODE_TIMEOUT); 394 sendMessageDelayed(BREDR_STOP_TIMEOUT, BREDR_STOP_TIMEOUT_DELAY); 395 adapterService.stopProfileServices(); 396 break; 397 398 case DISABLED: 399 if (isTurningOn) { 400 removeMessages(ENABLE_TIMEOUT); 401 errorLog("Error enabling Bluetooth - hardware init failed?"); 402 mPendingCommandState.setTurningOn(false); 403 transitionTo(mOffState); 404 adapterService.stopProfileServices(); 405 notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); 406 break; 407 } 408 removeMessages(DISABLE_TIMEOUT); 409 sendMessageDelayed(BLE_STOP_TIMEOUT, BLE_STOP_TIMEOUT_DELAY); 410 if (adapterService.stopGattProfileService()) { 411 debugLog("Stopping Gatt profile services that were post enabled"); 412 break; 413 } 414 //Fall through if no services or services already stopped 415 case BLE_STOPPED: 416 removeMessages(BLE_STOP_TIMEOUT); 417 setBleTurningOff(false); 418 transitionTo(mOffState); 419 notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); 420 break; 421 422 case BREDR_STOPPED: 423 removeMessages(BREDR_STOP_TIMEOUT); 424 setTurningOff(false); 425 transitionTo(mBleOnState); 426 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON); 427 break; 428 429 case BLE_START_TIMEOUT: 430 errorLog("Error enabling Bluetooth (BLE start timeout)"); 431 mPendingCommandState.setBleTurningOn(false); 432 transitionTo(mOffState); 433 notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); 434 break; 435 436 case BREDR_START_TIMEOUT: 437 errorLog("Error enabling Bluetooth (start timeout)"); 438 mPendingCommandState.setTurningOn(false); 439 adapterService.stopProfileServices(); 440 transitionTo(mBleOnState); 441 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON); 442 break; 443 444 case ENABLE_TIMEOUT: 445 errorLog("Error enabling Bluetooth (enable timeout)"); 446 mPendingCommandState.setBleTurningOn(false); 447 transitionTo(mOffState); 448 adapterService.stopProfileServices(); 449 adapterService.stopGattProfileService(); 450 notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); 451 break; 452 453 case BREDR_STOP_TIMEOUT: 454 errorLog("Error stopping Bluetooth profiles (stop timeout)"); 455 mPendingCommandState.setTurningOff(false); 456 transitionTo(mBleOnState); 457 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON); 458 break; 459 460 case BLE_STOP_TIMEOUT: 461 errorLog("Error stopping Bluetooth profiles (BLE stop timeout)"); 462 mPendingCommandState.setTurningOff(false); 463 transitionTo(mOffState); 464 notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); 465 break; 466 467 case DISABLE_TIMEOUT: 468 errorLog("Error disabling Bluetooth (disable timeout)"); 469 if (isTurningOn) 470 mPendingCommandState.setTurningOn(false); 471 adapterService.stopProfileServices(); 472 adapterService.stopGattProfileService(); 473 mPendingCommandState.setTurningOff(false); 474 setBleTurningOff(false); 475 transitionTo(mOffState); 476 notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); 477 break; 478 479 default: 480 return false; 481 } 482 return true; 483 } 484 } 485 486 private void notifyAdapterStateChange(int newState) { 487 AdapterService adapterService = mAdapterService; 488 AdapterProperties adapterProperties = mAdapterProperties; 489 if ((adapterService == null) || (adapterProperties == null)) { 490 errorLog("notifyAdapterStateChange after cleanup:" + newState); 491 return; 492 } 493 494 int oldState = adapterProperties.getState(); 495 adapterProperties.setState(newState); 496 infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState); 497 adapterService.updateAdapterState(oldState, newState); 498 } 499 500 void stateChangeCallback(int status) { 501 if (status == AbstractionLayer.BT_STATE_OFF) { 502 sendMessage(DISABLED); 503 504 } else if (status == AbstractionLayer.BT_STATE_ON) { 505 // We should have got the property change for adapter and remote devices. 506 sendMessage(ENABLED_READY); 507 508 } else { 509 errorLog("Incorrect status in stateChangeCallback"); 510 } 511 } 512 513 private void infoLog(String msg) { 514 if (DBG) Log.i(TAG, msg); 515 } 516 517 private void debugLog(String msg) { 518 if (DBG) Log.d(TAG, msg); 519 } 520 521 private void warningLog(String msg) { 522 if (DBG) Log.d(TAG, msg); 523 } 524 525 private void verboseLog(String msg) { 526 if (VDBG) Log.v(TAG, msg); 527 } 528 529 private void errorLog(String msg) { 530 Log.e(TAG, msg); 531 } 532 533} 534