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