When turning off, broadcast STATE_OFF in the last HotOff state

This is because we do HotOff -> PowerOff -> HotOff for USER_TURN_OFF
Donot do poweroff for perprocess turn off.
Add small time delays for calls into stack to reset dbus timing.
bug 6438556

Change-Id: Iae8bdd24e41824ed4bc34aca96d082f9284f169c
This commit is contained in:
Matthew Xie
2012-05-07 11:01:23 -07:00
parent e06747c727
commit b12d6bc3a5
2 changed files with 53 additions and 17 deletions

View File

@ -39,7 +39,7 @@ import java.io.PrintWriter;
* (BluetootOn)<----------------------<-
* | ^ -------------------->- |
* | | | |
* TURN_OFF | | SCAN_MODE_CHANGED m1 | | USER_TURN_ON
* USER_TURN_OFF | | SCAN_MODE_CHANGED m1 | | USER_TURN_ON
* AIRPLANE_MODE_ON | | | |
* V | | |
* (Switching) (PerProcessState)
@ -121,8 +121,10 @@ final class BluetoothAdapterStateMachine extends StateMachine {
private static final int DEVICES_DISCONNECT_TIMEOUT = 103;
// Prepare Bluetooth timeout happens
private static final int PREPARE_BLUETOOTH_TIMEOUT = 104;
// Bluetooth Powerdown timeout happens
private static final int POWER_DOWN_TIMEOUT = 105;
// Bluetooth turn off wait timeout happens
private static final int TURN_OFF_TIMEOUT = 105;
// Bluetooth device power off wait timeout happens
private static final int POWER_DOWN_TIMEOUT = 106;
private Context mContext;
private BluetoothService mBluetoothService;
@ -137,13 +139,17 @@ final class BluetoothAdapterStateMachine extends StateMachine {
// this is the BluetoothAdapter state that reported externally
private int mPublicState;
// When turning off, broadcast STATE_OFF in the last HotOff state
// This is because we do HotOff -> PowerOff -> HotOff for USER_TURN_OFF
private boolean mDelayBroadcastStateOff;
// timeout value waiting for all the devices to be disconnected
private static final int DEVICES_DISCONNECT_TIMEOUT_TIME = 3000;
private static final int PREPARE_BLUETOOTH_TIMEOUT_TIME = 10000;
private static final int POWER_DOWN_TIMEOUT_TIME = 5000;
private static final int TURN_OFF_TIMEOUT_TIME = 5000;
private static final int POWER_DOWN_TIMEOUT_TIME = 20;
BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
BluetoothAdapter bluetoothAdapter) {
@ -168,6 +174,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
setInitialState(mPowerOff);
mPublicState = BluetoothAdapter.STATE_OFF;
mDelayBroadcastStateOff = false;
}
/**
@ -315,6 +322,10 @@ final class BluetoothAdapterStateMachine extends StateMachine {
case SERVICE_RECORD_LOADED:
removeMessages(PREPARE_BLUETOOTH_TIMEOUT);
transitionTo(mHotOff);
if (mDelayBroadcastStateOff) {
broadcastState(BluetoothAdapter.STATE_OFF);
mDelayBroadcastStateOff = false;
}
break;
case PREPARE_BLUETOOTH_TIMEOUT:
Log.e(TAG, "Bluetooth adapter SDP failed to load");
@ -373,8 +384,17 @@ final class BluetoothAdapterStateMachine extends StateMachine {
case AIRPLANE_MODE_ON:
case TURN_COLD:
shutoffBluetooth();
// we cannot go to power off state yet, we need wait for the Bluetooth
// device power off. Unfortunately the stack does not give a event back
// so we wait a little bit here
sendMessageDelayed(POWER_DOWN_TIMEOUT,
POWER_DOWN_TIMEOUT_TIME);
break;
case POWER_DOWN_TIMEOUT:
transitionTo(mPowerOff);
broadcastState(BluetoothAdapter.STATE_OFF);
if (!mDelayBroadcastStateOff) {
broadcastState(BluetoothAdapter.STATE_OFF);
}
break;
case AIRPLANE_MODE_OFF:
if (getBluetoothPersistedSetting()) {
@ -402,6 +422,9 @@ final class BluetoothAdapterStateMachine extends StateMachine {
recoverStateMachine(TURN_HOT, null);
}
break;
case TURN_HOT:
deferMessage(message);
break;
default:
return NOT_HANDLED;
}
@ -436,15 +459,17 @@ final class BluetoothAdapterStateMachine extends StateMachine {
}
break;
case POWER_STATE_CHANGED:
removeMessages(POWER_DOWN_TIMEOUT);
removeMessages(TURN_OFF_TIMEOUT);
if (!((Boolean) message.obj)) {
if (mPublicState == BluetoothAdapter.STATE_TURNING_OFF) {
transitionTo(mHotOff);
finishSwitchingOff();
mBluetoothService.finishDisable();
mBluetoothService.cleanupAfterFinishDisable();
deferMessage(obtainMessage(TURN_COLD));
if (mContext.getResources().getBoolean
(com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
deferMessage(obtainMessage(TURN_HOT));
mDelayBroadcastStateOff = true;
}
}
} else {
@ -461,7 +486,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
case ALL_DEVICES_DISCONNECTED:
removeMessages(DEVICES_DISCONNECT_TIMEOUT);
mBluetoothService.switchConnectable(false);
sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME);
sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
break;
case DEVICES_DISCONNECT_TIMEOUT:
sendMessage(ALL_DEVICES_DISCONNECTED);
@ -473,7 +498,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
deferMessage(obtainMessage(TURN_HOT));
}
break;
case POWER_DOWN_TIMEOUT:
case TURN_OFF_TIMEOUT:
transitionTo(mHotOff);
finishSwitchingOff();
// reset the hardware for error recovery
@ -536,7 +561,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
DEVICES_DISCONNECT_TIMEOUT_TIME);
} else {
mBluetoothService.switchConnectable(false);
sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME);
sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
}
// we turn all the way to PowerOff with AIRPLANE_MODE_ON
@ -610,13 +635,12 @@ final class BluetoothAdapterStateMachine extends StateMachine {
}
break;
case POWER_STATE_CHANGED:
removeMessages(POWER_DOWN_TIMEOUT);
removeMessages(TURN_OFF_TIMEOUT);
if (!((Boolean) message.obj)) {
transitionTo(mHotOff);
deferMessage(obtainMessage(TURN_COLD));
if (mContext.getResources().getBoolean
if (!mContext.getResources().getBoolean
(com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
deferMessage(obtainMessage(TURN_HOT));
deferMessage(obtainMessage(TURN_COLD));
}
} else {
if (!isTurningOn) {
@ -629,7 +653,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
}
}
break;
case POWER_DOWN_TIMEOUT:
case TURN_OFF_TIMEOUT:
transitionTo(mHotOff);
Log.e(TAG, "Power-down timed out, resetting...");
deferMessage(obtainMessage(TURN_COLD));
@ -676,12 +700,12 @@ final class BluetoothAdapterStateMachine extends StateMachine {
perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
if (mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
mBluetoothService.switchConnectable(false);
sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME);
sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
}
break;
case AIRPLANE_MODE_ON:
mBluetoothService.switchConnectable(false);
sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME);
sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
allProcessesCallback(false);
// we turn all the way to PowerOff with AIRPLANE_MODE_ON
deferMessage(obtainMessage(AIRPLANE_MODE_ON));

View File

@ -526,6 +526,12 @@ public class BluetoothService extends IBluetooth.Stub {
return false;
}
switchConnectable(false);
// Bluetooth stack needs a small delay here before adding
// SDP records, otherwise dbus stalls for over 30 seconds 1 out of 50 runs
try {
Thread.sleep(20);
} catch (InterruptedException e) {}
updateSdpRecords();
return true;
}
@ -593,6 +599,12 @@ public class BluetoothService extends IBluetooth.Stub {
// Add SDP records for profiles maintained by Android userspace
addReservedSdpRecords(uuids);
// Bluetooth stack need some a small delay here before adding more
// SDP records, otherwise dbus stalls for over 30 seconds 1 out of 50 runs
try {
Thread.sleep(20);
} catch (InterruptedException e) {}
if (R.getBoolean(com.android.internal.R.bool.config_bluetooth_default_profiles)) {
// Enable profiles maintained by Bluez userspace.
setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE,