17f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie/* 27f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Copyright (C) 2011 The Android Open Source Project 37f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * 47f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Licensed under the Apache License, Version 2.0 (the "License"); 57f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * you may not use this file except in compliance with the License. 67f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * You may obtain a copy of the License at 77f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * 87f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * http://www.apache.org/licenses/LICENSE-2.0 97f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * 107f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Unless required by applicable law or agreed to in writing, software 117f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * distributed under the License is distributed on an "AS IS" BASIS, 127f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * See the License for the specific language governing permissions and 147f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * limitations under the License. 157f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 167f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xiepackage android.server; 187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 197f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport android.bluetooth.BluetoothAdapter; 20ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport android.bluetooth.IBluetoothStateChangeCallback; 217f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport android.content.ContentResolver; 227f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport android.content.Context; 237f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport android.content.Intent; 247f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport android.os.Binder; 257f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport android.os.Message; 26ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport android.os.RemoteException; 277f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport android.provider.Settings; 287f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport android.util.Log; 297f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 307f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport com.android.internal.util.IState; 317f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport com.android.internal.util.State; 327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport com.android.internal.util.StateMachine; 337f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xieimport java.io.PrintWriter; 357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie/** 377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Bluetooth Adapter StateMachine 387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * All the states are at the same level, ie, no hierarchy. 39ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * (BluetootOn)<----------------------<- 40ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * | ^ -------------------->- | 41ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * | | | | 4214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * TURN_OFF | | SCAN_MODE_CHANGED m1 | | USER_TURN_ON 43ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * AIRPLANE_MODE_ON | | | | 44ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * V | | | 45ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * (Switching) (PerProcessState) 46ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * | ^ | | 4714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * POWER_STATE_CHANGED & | | TURN_ON(_CONTINUE) | | 48ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * ALL_DEVICES_DISCONNECTED | | m2 | | 4914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * V |------------------------< | SCAN_MODE_CHANGED 509a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie * (HotOff)-------------------------->- PER_PROCESS_TURN_ON 517f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * / ^ 527f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * / | SERVICE_RECORD_LOADED 537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * | | 547f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * TURN_COLD | (Warmup) 557f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * \ ^ 567f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * \ | TURN_HOT/TURN_ON 577f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * | | AIRPLANE_MODE_OFF(when Bluetooth was on before) 587f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * V | 597f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * (PowerOff) <----- initial state 607f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * 61ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * Legend: 629a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie * m1 = TURN_HOT 63ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh * m2 = Transition to HotOff when number of process wanting BT on is 0. 6414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * POWER_STATE_CHANGED will make the transition. 657f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xiefinal class BluetoothAdapterStateMachine extends StateMachine { 677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static final String TAG = "BluetoothAdapterStateMachine"; 687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static final boolean DBG = false; 697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Message(what) to take an action 717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // 727f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // We get this message when user tries to turn on BT 73ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh static final int USER_TURN_ON = 1; 747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // We get this message when user tries to turn off BT 75ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh static final int USER_TURN_OFF = 2; 769a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie // Per process enable / disable messages 779a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie static final int PER_PROCESS_TURN_ON = 3; 789a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie static final int PER_PROCESS_TURN_OFF = 4; 797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 809de1feb673499519cb380a142ba1e453109480bdMatthew Xie // Turn on Bluetooth Module, Load firmware, and do all the preparation 819de1feb673499519cb380a142ba1e453109480bdMatthew Xie // needed to get the Bluetooth Module ready but keep it not discoverable 829de1feb673499519cb380a142ba1e453109480bdMatthew Xie // and not connectable. This way the Bluetooth Module can be quickly 839de1feb673499519cb380a142ba1e453109480bdMatthew Xie // switched on if needed 849de1feb673499519cb380a142ba1e453109480bdMatthew Xie static final int TURN_HOT = 5; 859de1feb673499519cb380a142ba1e453109480bdMatthew Xie 867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Message(what) to report a event that the state machine need to respond to 877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // 887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Event indicates sevice records have been loaded 89ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh static final int SERVICE_RECORD_LOADED = 51; 907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Event indicates all the remote Bluetooth devices has been disconnected 91ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh static final int ALL_DEVICES_DISCONNECTED = 52; 9214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // Event indicates the Bluetooth scan mode has changed 9314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie static final int SCAN_MODE_CHANGED = 53; 9414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // Event indicates the powered state has changed 9514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie static final int POWER_STATE_CHANGED = 54; 967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Event indicates airplane mode is turned on 97ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh static final int AIRPLANE_MODE_ON = 55; 987f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Event indicates airplane mode is turned off 99ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh static final int AIRPLANE_MODE_OFF = 56; 1007f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // private internal messages 1027f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // 1037f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // USER_TURN_ON is changed to TURN_ON_CONTINUE after we broadcast the 1047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // state change intent so that we will not broadcast the intent again in 1057f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // other state 1069de1feb673499519cb380a142ba1e453109480bdMatthew Xie private static final int TURN_ON_CONTINUE = 101; 1077f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Unload firmware, turning off Bluetooth module power 1089de1feb673499519cb380a142ba1e453109480bdMatthew Xie private static final int TURN_COLD = 102; 1099a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie // Device disconnecting timeout happens 1109de1feb673499519cb380a142ba1e453109480bdMatthew Xie private static final int DEVICES_DISCONNECT_TIMEOUT = 103; 11114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // Prepare Bluetooth timeout happens 1129de1feb673499519cb380a142ba1e453109480bdMatthew Xie private static final int PREPARE_BLUETOOTH_TIMEOUT = 104; 113694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie // Bluetooth Powerdown timeout happens 1149de1feb673499519cb380a142ba1e453109480bdMatthew Xie private static final int POWER_DOWN_TIMEOUT = 105; 1157f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1167f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private Context mContext; 1177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private BluetoothService mBluetoothService; 1187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private BluetoothEventLoop mEventLoop; 1197f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1207f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private BluetoothOn mBluetoothOn; 1217f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private Switching mSwitching; 1227f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private HotOff mHotOff; 1237f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private WarmUp mWarmUp; 1247f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private PowerOff mPowerOff; 125ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private PerProcessState mPerProcessState; 1267f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1277f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // this is the BluetoothAdapter state that reported externally 1287f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private int mPublicState; 1297f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1309a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie // timeout value waiting for all the devices to be disconnected 1319a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie private static final int DEVICES_DISCONNECT_TIMEOUT_TIME = 3000; 1329a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie 13325c4e2a8032c38f6336f7f49e464c95c7b8798f2Matthew Xie private static final int PREPARE_BLUETOOTH_TIMEOUT_TIME = 10000; 13414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie 135694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie private static final int POWER_DOWN_TIMEOUT_TIME = 5000; 136694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie 1377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService, 1387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie BluetoothAdapter bluetoothAdapter) { 1397f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie super(TAG); 1407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mContext = context; 1417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothService = bluetoothService; 1427f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mEventLoop = new BluetoothEventLoop(context, bluetoothAdapter, bluetoothService, this); 1437f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1447f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothOn = new BluetoothOn(); 1457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mSwitching = new Switching(); 1467f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mHotOff = new HotOff(); 1477f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mWarmUp = new WarmUp(); 1487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mPowerOff = new PowerOff(); 149ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mPerProcessState = new PerProcessState(); 1507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1517f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie addState(mBluetoothOn); 1527f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie addState(mSwitching); 1537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie addState(mHotOff); 1547f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie addState(mWarmUp); 1557f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie addState(mPowerOff); 156ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh addState(mPerProcessState); 157ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1587f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setInitialState(mPowerOff); 1597f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mPublicState = BluetoothAdapter.STATE_OFF; 1607f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 1617f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1627f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 1637f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Bluetooth module's power is off, firmware is not loaded. 1647f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 1657f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private class PowerOff extends State { 1667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 1677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public void enter() { 1688594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie if (DBG) log("Enter PowerOff: " + getCurrentMessage().what); 1697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 1707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 1717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public boolean processMessage(Message message) { 17214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie log("PowerOff process message: " + message.what); 1737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 1747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie boolean retValue = HANDLED; 1757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switch(message.what) { 1767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case USER_TURN_ON: 1777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // starts turning on BT module, broadcast this out 1787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie broadcastState(BluetoothAdapter.STATE_TURNING_ON); 179a6ba6fd4bb931ba7c1cbda6adc8452609ea80dacMatthew Xie transitionTo(mWarmUp); 1807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (prepareBluetooth()) { 1817f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // this is user request, save the setting 1827f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if ((Boolean) message.obj) { 183ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh persistSwitchSetting(true); 1847f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 1857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // We will continue turn the BT on all the way to the BluetoothOn state 1867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie deferMessage(obtainMessage(TURN_ON_CONTINUE)); 1877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 1887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Log.e(TAG, "failed to prepare bluetooth, abort turning on"); 1897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie transitionTo(mPowerOff); 1907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie broadcastState(BluetoothAdapter.STATE_OFF); 1917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 1927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 1937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case TURN_HOT: 1947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (prepareBluetooth()) { 1957f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie transitionTo(mWarmUp); 1967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 1977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 1987f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case AIRPLANE_MODE_OFF: 1997f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothPersistedSetting()) { 2007f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // starts turning on BT module, broadcast this out 2017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie broadcastState(BluetoothAdapter.STATE_TURNING_ON); 202a6ba6fd4bb931ba7c1cbda6adc8452609ea80dacMatthew Xie transitionTo(mWarmUp); 2037f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (prepareBluetooth()) { 2047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // We will continue turn the BT on all the way to the BluetoothOn state 2057f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie deferMessage(obtainMessage(TURN_ON_CONTINUE)); 2067f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie transitionTo(mWarmUp); 2077f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 2087f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Log.e(TAG, "failed to prepare bluetooth, abort turning on"); 2097f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie transitionTo(mPowerOff); 2107f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie broadcastState(BluetoothAdapter.STATE_OFF); 2117f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 212ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else if (mContext.getResources().getBoolean 213ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 214ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh sendMessage(TURN_HOT); 2157f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2167f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 217ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_ON: 218ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (prepareBluetooth()) { 219ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh transitionTo(mWarmUp); 220ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 221ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh deferMessage(obtainMessage(PER_PROCESS_TURN_ON)); 222ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 223ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_OFF: 224ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh perProcessCallback(false, (IBluetoothStateChangeCallback) message.obj); 225ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 2269a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case USER_TURN_OFF: 2279a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie Log.w(TAG, "PowerOff received: " + message.what); 2289a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case AIRPLANE_MODE_ON: // ignore 2297f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 2307f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie default: 2317f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return NOT_HANDLED; 2327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2337f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return retValue; 2347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 2377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Turn on Bluetooth Module, Load firmware, and do all the preparation 2387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * needed to get the Bluetooth Module ready but keep it not discoverable 2397f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * and not connectable. 2407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * The last step of this method sets up the local service record DB. 2417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * There will be a event reporting the status of the SDP setup. 2427f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 2437f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private boolean prepareBluetooth() { 2447f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (mBluetoothService.enableNative() != 0) { 2457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return false; 2467f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2477f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // try to start event loop, give 2 attempts 2497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie int retryCount = 2; 2507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie boolean eventLoopStarted = false; 2517f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie while ((retryCount-- > 0) && !eventLoopStarted) { 2527f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mEventLoop.start(); 2537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // it may take a moment for the other thread to do its 2547f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // thing. Check periodically for a while. 2557f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie int pollCount = 5; 2567f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie while ((pollCount-- > 0) && !eventLoopStarted) { 2577f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (mEventLoop.isEventLoopRunning()) { 2587f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie eventLoopStarted = true; 2597f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 2607f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2617f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie try { 2627f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Thread.sleep(100); 2637f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } catch (InterruptedException e) { 26414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie log("prepareBluetooth sleep interrupted: " + pollCount); 2657f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 2667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (!eventLoopStarted) { 2717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothService.disableNative(); 2727f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return false; 2737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // get BluetoothService ready 2767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (!mBluetoothService.prepareBluetooth()) { 2777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mEventLoop.stop(); 2787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothService.disableNative(); 2797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return false; 2807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2817f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 28214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie sendMessageDelayed(PREPARE_BLUETOOTH_TIMEOUT, PREPARE_BLUETOOTH_TIMEOUT_TIME); 2837f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return true; 2847f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 2887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Turning on Bluetooth module's power, loading firmware, starting 2897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * event loop thread to listen on Bluetooth module event changes. 2907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 2917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private class WarmUp extends State { 2927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 2947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public void enter() { 2958594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie if (DBG) log("Enter WarmUp: " + getCurrentMessage().what); 2967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 2977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2987f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 2997f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public boolean processMessage(Message message) { 30014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie log("WarmUp process message: " + message.what); 3017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 3027f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie boolean retValue = HANDLED; 3037f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switch(message.what) { 3047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case SERVICE_RECORD_LOADED: 30514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie removeMessages(PREPARE_BLUETOOTH_TIMEOUT); 3067f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie transitionTo(mHotOff); 3077f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 30814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie case PREPARE_BLUETOOTH_TIMEOUT: 30914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie Log.e(TAG, "Bluetooth adapter SDP failed to load"); 31014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie shutoffBluetooth(); 31114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie transitionTo(mPowerOff); 31214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie broadcastState(BluetoothAdapter.STATE_OFF); 31314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie break; 3147f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case USER_TURN_ON: // handle this at HotOff state 3157f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case TURN_ON_CONTINUE: // Once in HotOff state, continue turn bluetooth 3167f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // on to the BluetoothOn state 3177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case AIRPLANE_MODE_ON: 3187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case AIRPLANE_MODE_OFF: 319ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_ON: 320ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_OFF: 3217f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie deferMessage(message); 3227f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 3239a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case USER_TURN_OFF: 3249a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie Log.w(TAG, "WarmUp received: " + message.what); 3257f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 3267f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie default: 3277f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return NOT_HANDLED; 3287f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 3297f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return retValue; 3307f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 3317f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 3327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 3337f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 3347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 3357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Bluetooth Module has powered, firmware loaded, event loop started, 3367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * SDP loaded, but the modules stays non-discoverable and 3377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * non-connectable. 3387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 3397f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private class HotOff extends State { 3407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 3417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public void enter() { 3428594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie if (DBG) log("Enter HotOff: " + getCurrentMessage().what); 3437f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 3447f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 3457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 3467f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public boolean processMessage(Message message) { 34714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie log("HotOff process message: " + message.what); 3487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 3497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie boolean retValue = HANDLED; 3507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switch(message.what) { 3517f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case USER_TURN_ON: 3522d789e58a8d2665b980fa952ba233cdde40f0157Matthew Xie broadcastState(BluetoothAdapter.STATE_TURNING_ON); 3537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if ((Boolean) message.obj) { 354ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh persistSwitchSetting(true); 3557f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 3567f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // let it fall to TURN_ON_CONTINUE: 357ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh //$FALL-THROUGH$ 3587f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case TURN_ON_CONTINUE: 3597f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothService.switchConnectable(true); 3607f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie transitionTo(mSwitching); 3617f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 3627f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case AIRPLANE_MODE_ON: 3637f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case TURN_COLD: 36414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie shutoffBluetooth(); 3657f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie transitionTo(mPowerOff); 3667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie broadcastState(BluetoothAdapter.STATE_OFF); 3677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 3687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case AIRPLANE_MODE_OFF: 3697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothPersistedSetting()) { 370a6ba6fd4bb931ba7c1cbda6adc8452609ea80dacMatthew Xie broadcastState(BluetoothAdapter.STATE_TURNING_ON); 3717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie transitionTo(mSwitching); 372ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothService.switchConnectable(true); 3737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 3747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 375ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_ON: 376ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh transitionTo(mPerProcessState); 377ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 378ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh // Resend the PER_PROCESS_TURN_ON message so that the callback 379ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh // can be sent through. 380ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh deferMessage(message); 381ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 382ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothService.switchConnectable(true); 383ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 384ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_OFF: 385ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj); 386ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 3879a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case USER_TURN_OFF: // ignore 3889a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie break; 389694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie case POWER_STATE_CHANGED: 390694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie if ((Boolean) message.obj) { 391694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie recoverStateMachine(TURN_HOT, null); 392694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 393694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie break; 3947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie default: 3957f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return NOT_HANDLED; 3967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 3977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return retValue; 3987f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 3997f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4007f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4027f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private class Switching extends State { 4037f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 4057f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public void enter() { 4068594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie if (DBG) log("Enter Switching: " + getCurrentMessage().what); 4077f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4087f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 4097f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public boolean processMessage(Message message) { 41014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie log("Switching process message: " + message.what); 4117f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4127f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie boolean retValue = HANDLED; 4137f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switch(message.what) { 41414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie case SCAN_MODE_CHANGED: 41514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // This event matches mBluetoothService.switchConnectable action 41614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (mPublicState == BluetoothAdapter.STATE_TURNING_ON) { 41714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // set pairable if it's not 41814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothService.setPairable(); 41914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothService.initBluetoothAfterTurningOn(); 42014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie transitionTo(mBluetoothOn); 42114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie broadcastState(BluetoothAdapter.STATE_ON); 42214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // run bluetooth now that it's turned on 42314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // Note runBluetooth should be called only in adapter STATE_ON 42414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothService.runBluetooth(); 42514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 4267f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 42714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie case POWER_STATE_CHANGED: 428694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie removeMessages(POWER_DOWN_TIMEOUT); 42914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (!((Boolean) message.obj)) { 430694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie if (mPublicState == BluetoothAdapter.STATE_TURNING_OFF) { 431694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie transitionTo(mHotOff); 432694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie finishSwitchingOff(); 433dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie if (!mContext.getResources().getBoolean 434dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 435dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie deferMessage(obtainMessage(TURN_COLD)); 436dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie } 437694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 438694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } else { 439694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie if (mPublicState != BluetoothAdapter.STATE_TURNING_ON) { 440694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie if (mContext.getResources().getBoolean 441694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 442694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie recoverStateMachine(TURN_HOT, null); 443694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } else { 444694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie recoverStateMachine(TURN_COLD, null); 445694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 446694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 4477f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 4497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case ALL_DEVICES_DISCONNECTED: 4509a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie removeMessages(DEVICES_DISCONNECT_TIMEOUT); 45114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothService.switchConnectable(false); 452694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME); 4537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 4549a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case DEVICES_DISCONNECT_TIMEOUT: 4559a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie sendMessage(ALL_DEVICES_DISCONNECTED); 4569a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie // reset the hardware for error recovery 4579a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie Log.e(TAG, "Devices failed to disconnect, reseting..."); 4589a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie deferMessage(obtainMessage(TURN_COLD)); 4599a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie if (mContext.getResources().getBoolean 4609a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 4619a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie deferMessage(obtainMessage(TURN_HOT)); 4629a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie } 4639a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie break; 464694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie case POWER_DOWN_TIMEOUT: 465694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie transitionTo(mHotOff); 466694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie finishSwitchingOff(); 467694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie // reset the hardware for error recovery 468694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie Log.e(TAG, "Devices failed to power down, reseting..."); 469694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie deferMessage(obtainMessage(TURN_COLD)); 470694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie if (mContext.getResources().getBoolean 471694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 472694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie deferMessage(obtainMessage(TURN_HOT)); 473694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 474694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie break; 4757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case USER_TURN_ON: 4767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case AIRPLANE_MODE_OFF: 4777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case AIRPLANE_MODE_ON: 478ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_ON: 479ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_OFF: 4807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case USER_TURN_OFF: 4817f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie deferMessage(message); 4827f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 483ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 4847f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie default: 4857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return NOT_HANDLED; 4867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return retValue; 4887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private class BluetoothOn extends State { 4927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 4947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public void enter() { 4958594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie if (DBG) log("Enter BluetoothOn: " + getCurrentMessage().what); 4967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie @Override 4987f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie public boolean processMessage(Message message) { 49914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie log("BluetoothOn process message: " + message.what); 5007f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 5017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie boolean retValue = HANDLED; 5027f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switch(message.what) { 5037f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case USER_TURN_OFF: 5047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if ((Boolean) message.obj) { 505ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh persistSwitchSetting(false); 506ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 507ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 508ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (mBluetoothService.isDiscovering()) { 509ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothService.cancelDiscovery(); 510ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 511ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (!mBluetoothService.isApplicationStateChangeTrackerEmpty()) { 512ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh transitionTo(mPerProcessState); 5139a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie deferMessage(obtainMessage(TURN_HOT)); 514ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 5157f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 516ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh //$FALL-THROUGH$ to AIRPLANE_MODE_ON 5177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie case AIRPLANE_MODE_ON: 5187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie broadcastState(BluetoothAdapter.STATE_TURNING_OFF); 519a6ba6fd4bb931ba7c1cbda6adc8452609ea80dacMatthew Xie transitionTo(mSwitching); 52014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (mBluetoothService.getAdapterConnectionState() != 52114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie BluetoothAdapter.STATE_DISCONNECTED) { 52214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothService.disconnectDevices(); 52314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT, 52414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie DEVICES_DISCONNECT_TIMEOUT_TIME); 52514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } else { 52614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothService.switchConnectable(false); 527694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME); 52814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 529ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 5307f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // we turn all the way to PowerOff with AIRPLANE_MODE_ON 531f3171fb60c840a9bc0220fad651338346dddfff7Matthew Xie if (message.what == AIRPLANE_MODE_ON || mBluetoothService.isAirplaneModeOn()) { 532ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh // We inform all the per process callbacks 533ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh allProcessesCallback(false); 5347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie deferMessage(obtainMessage(AIRPLANE_MODE_ON)); 5357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 5367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 5379a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case AIRPLANE_MODE_OFF: 5389a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case USER_TURN_ON: 5399a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie Log.w(TAG, "BluetoothOn received: " + message.what); 5407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie break; 541ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_ON: 542ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh perProcessCallback(true, (IBluetoothStateChangeCallback)message.obj); 543ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 544ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_OFF: 545ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj); 546ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 547694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie case POWER_STATE_CHANGED: 548694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie if ((Boolean) message.obj) { 549694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie // reset the state machine and send it TURN_ON_CONTINUE message 550694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie recoverStateMachine(USER_TURN_ON, false); 551694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 552694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie break; 5537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie default: 5547f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return NOT_HANDLED; 5557f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 5567f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return retValue; 5577f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 5587f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 5597f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 5607f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 561ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 562ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private class PerProcessState extends State { 563ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh IBluetoothStateChangeCallback mCallback = null; 56414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie boolean isTurningOn = false; 565ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 566ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh @Override 567ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh public void enter() { 56814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie int what = getCurrentMessage().what; 56914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (DBG) log("Enter PerProcessState: " + what); 57014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie 57114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (what == PER_PROCESS_TURN_ON) { 57214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie isTurningOn = true; 573694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } else if (what == USER_TURN_OFF) { 57414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie isTurningOn = false; 57514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } else { 57614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie Log.e(TAG, "enter PerProcessState: wrong msg: " + what); 57714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 578ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 579ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 580ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh @Override 581ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh public boolean processMessage(Message message) { 58214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie log("PerProcessState process message: " + message.what); 583ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 584ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh boolean retValue = HANDLED; 585ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh switch (message.what) { 586ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case PER_PROCESS_TURN_ON: 587ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mCallback = (IBluetoothStateChangeCallback)getCurrentMessage().obj; 588ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 589ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh // If this is not the first application call the callback. 590ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (mBluetoothService.getNumberOfApplicationStateChangeTrackers() > 1) { 591ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh perProcessCallback(true, mCallback); 592ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 593ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 59414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie case SCAN_MODE_CHANGED: 59514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (isTurningOn) { 59614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie perProcessCallback(true, mCallback); 59714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie isTurningOn = false; 59814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 59914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie break; 60014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie case POWER_STATE_CHANGED: 601694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie removeMessages(POWER_DOWN_TIMEOUT); 60214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (!((Boolean) message.obj)) { 60314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie transitionTo(mHotOff); 60414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (!mContext.getResources().getBoolean 60514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 60614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie deferMessage(obtainMessage(TURN_COLD)); 60714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 608694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } else { 609694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie if (!isTurningOn) { 610694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie recoverStateMachine(TURN_COLD, null); 611694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie for (IBluetoothStateChangeCallback c: 612694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie mBluetoothService.getApplicationStateChangeCallbacks()) { 613694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie perProcessCallback(false, c); 614694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie deferMessage(obtainMessage(PER_PROCESS_TURN_ON, c)); 615694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 616694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 617694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 618694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie break; 619694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie case POWER_DOWN_TIMEOUT: 620694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie transitionTo(mHotOff); 621694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie Log.e(TAG, "Power-down timed out, resetting..."); 622694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie deferMessage(obtainMessage(TURN_COLD)); 623694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie if (mContext.getResources().getBoolean 624694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 625694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie deferMessage(obtainMessage(TURN_HOT)); 62614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 627ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 628ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case USER_TURN_ON: 629ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh broadcastState(BluetoothAdapter.STATE_TURNING_ON); 630ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh persistSwitchSetting(true); 6318594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie mBluetoothService.initBluetoothAfterTurningOn(); 632ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh transitionTo(mBluetoothOn); 633ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh broadcastState(BluetoothAdapter.STATE_ON); 6348594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie // run bluetooth now that it's turned on 6358594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie mBluetoothService.runBluetooth(); 636ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 6379a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case TURN_HOT: 638ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh broadcastState(BluetoothAdapter.STATE_TURNING_OFF); 639ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (mBluetoothService.getAdapterConnectionState() != 640ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh BluetoothAdapter.STATE_DISCONNECTED) { 641ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothService.disconnectDevices(); 6429a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT, 6439a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie DEVICES_DISCONNECT_TIMEOUT_TIME); 644ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 645ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 646ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh //$FALL-THROUGH$ all devices are already disconnected 647ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case ALL_DEVICES_DISCONNECTED: 6489a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie removeMessages(DEVICES_DISCONNECT_TIMEOUT); 649dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie finishSwitchingOff(); 650ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 6519a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case DEVICES_DISCONNECT_TIMEOUT: 652dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie finishSwitchingOff(); 6539a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie Log.e(TAG, "Devices fail to disconnect, reseting..."); 6549a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie transitionTo(mHotOff); 6559a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie deferMessage(obtainMessage(TURN_COLD)); 6569a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie for (IBluetoothStateChangeCallback c: 6579a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie mBluetoothService.getApplicationStateChangeCallbacks()) { 6589a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie perProcessCallback(false, c); 6599a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie deferMessage(obtainMessage(PER_PROCESS_TURN_ON, c)); 6609a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie } 6619a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie break; 6629a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case PER_PROCESS_TURN_OFF: 663ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj); 664ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (mBluetoothService.isApplicationStateChangeTrackerEmpty()) { 665ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothService.switchConnectable(false); 666694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME); 667ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 668ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 669ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh case AIRPLANE_MODE_ON: 670ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothService.switchConnectable(false); 671694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME); 672ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh allProcessesCallback(false); 673ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh // we turn all the way to PowerOff with AIRPLANE_MODE_ON 674ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh deferMessage(obtainMessage(AIRPLANE_MODE_ON)); 675ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh break; 6769a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie case USER_TURN_OFF: 6779a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie Log.w(TAG, "PerProcessState received: " + message.what); 6789a943a64202aba8f885b2c736183bf53276a23dfMatthew Xie break; 679ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh default: 680ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return NOT_HANDLED; 681ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 682ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return retValue; 683ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 684ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 685ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 686dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie private void finishSwitchingOff() { 687dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie mBluetoothService.finishDisable(); 688dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie broadcastState(BluetoothAdapter.STATE_OFF); 689dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie mBluetoothService.cleanupAfterFinishDisable(); 690dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie } 691dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie 69214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie private void shutoffBluetooth() { 69314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothService.shutoffBluetooth(); 69414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mEventLoop.stop(); 69514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothService.cleanNativeAfterShutoffBluetooth(); 69614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 697ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 698ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private void perProcessCallback(boolean on, IBluetoothStateChangeCallback c) { 699ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (c == null) return; 700ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 701ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh try { 702ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh c.onBluetoothStateChange(on); 703ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } catch (RemoteException e) {} 704ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 705ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 706ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private void allProcessesCallback(boolean on) { 707ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh for (IBluetoothStateChangeCallback c: 708ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothService.getApplicationStateChangeCallbacks()) { 709ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh perProcessCallback(on, c); 710ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 711ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (!on) { 712ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothService.clearApplicationStateChangeTracker(); 713ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 714ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 715ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 7167f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 7177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Return the public BluetoothAdapter state 7187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 7197f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie int getBluetoothAdapterState() { 7207f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return mPublicState; 7217f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7227f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7237f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie BluetoothEventLoop getBluetoothEventLoop() { 7247f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return mEventLoop; 7257f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7267f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7277f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private void persistSwitchSetting(boolean setOn) { 7287f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie long origCallerIdentityToken = Binder.clearCallingIdentity(); 7297f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Settings.Secure.putInt(mContext.getContentResolver(), 7307f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Settings.Secure.BLUETOOTH_ON, 7317f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie setOn ? 1 : 0); 7327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Binder.restoreCallingIdentity(origCallerIdentityToken); 7337f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private boolean getBluetoothPersistedSetting() { 7367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie ContentResolver contentResolver = mContext.getContentResolver(); 7377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return (Settings.Secure.getInt(contentResolver, 7387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Settings.Secure.BLUETOOTH_ON, 0) > 0); 7397f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private void broadcastState(int newState) { 7427f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 743ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh log("Bluetooth state " + mPublicState + " -> " + newState); 7447f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (mPublicState == newState) { 7457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return; 7467f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7477f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 7497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mPublicState); 7507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 7517f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 7527f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mPublicState = newState; 7537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7547f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM); 7557f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7567f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 757694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie /** 758694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie * bluetoothd has crashed and recovered, the adapter state machine has to 759694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie * reset itself and try to return to previous state 760694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie */ 761694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie private void recoverStateMachine(int what, Object obj) { 762694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie Log.e(TAG, "Get unexpected power on event, reset with: " + what); 763694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie transitionTo(mHotOff); 764694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie deferMessage(obtainMessage(TURN_COLD)); 765694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie deferMessage(obtainMessage(what, obj)); 766694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie } 767694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie 7687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private void dump(PrintWriter pw) { 7697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie IState currentState = getCurrentState(); 7707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (currentState == mPowerOff) { 7717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie pw.println("Bluetooth OFF - power down\n"); 7727f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else if (currentState == mWarmUp) { 7737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie pw.println("Bluetooth OFF - warm up\n"); 7747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else if (currentState == mHotOff) { 7757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie pw.println("Bluetooth OFF - hot but off\n"); 7767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else if (currentState == mSwitching) { 7777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie pw.println("Bluetooth Switching\n"); 7787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else if (currentState == mBluetoothOn) { 7797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie pw.println("Bluetooth ON\n"); 7807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 7817f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie pw.println("ERROR: Bluetooth UNKNOWN STATE "); 7827f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7837f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7847f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 7857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static void log(String msg) { 7867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Log.d(TAG, msg); 7877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 7887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie} 789