summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Xie <mattx@google.com>2011-08-15 11:49:31 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-08-15 11:49:31 -0700
commit269cf1b2145d1f4d51615a98809522af65a8ec16 (patch)
tree6fc9b654717718ddb688124eaa0a85b4c1369bc7
parent643c7dccbc86e470c8f81983b08029b750bf2b1c (diff)
parent14e48e91f6def5448db9994cb13ddcdc676cba53 (diff)
downloadframeworks_base-269cf1b2145d1f4d51615a98809522af65a8ec16.zip
frameworks_base-269cf1b2145d1f4d51615a98809522af65a8ec16.tar.gz
frameworks_base-269cf1b2145d1f4d51615a98809522af65a8ec16.tar.bz2
Merge "Implement switchConnectable with Powered property setting instead of scan modes"
-rw-r--r--core/java/android/server/BluetoothAdapterStateMachine.java125
-rw-r--r--core/java/android/server/BluetoothEventLoop.java21
-rwxr-xr-xcore/java/android/server/BluetoothService.java68
3 files changed, 128 insertions, 86 deletions
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
index 031375e..e15e61f 100644
--- a/core/java/android/server/BluetoothAdapterStateMachine.java
+++ b/core/java/android/server/BluetoothAdapterStateMachine.java
@@ -39,14 +39,14 @@ import java.io.PrintWriter;
* (BluetootOn)<----------------------<-
* | ^ -------------------->- |
* | | | |
- * TURN_OFF | | BECAME_PAIRABLE m1 | | USER_TURN_ON
+ * TURN_OFF | | SCAN_MODE_CHANGED m1 | | USER_TURN_ON
* AIRPLANE_MODE_ON | | | |
* V | | |
* (Switching) (PerProcessState)
* | ^ | |
- * BECAME_NON_PAIRABLE& | | TURN_ON(_CONTINUE) | |
+ * POWER_STATE_CHANGED & | | TURN_ON(_CONTINUE) | |
* ALL_DEVICES_DISCONNECTED | | m2 | |
- * V |------------------------< | BECAME_PAIRABLE
+ * V |------------------------< | SCAN_MODE_CHANGED
* (HotOff)-------------------------->- PER_PROCESS_TURN_ON
* / ^
* / | SERVICE_RECORD_LOADED
@@ -61,7 +61,7 @@ import java.io.PrintWriter;
* Legend:
* m1 = TURN_HOT
* m2 = Transition to HotOff when number of process wanting BT on is 0.
- * BECAME_NON_PAIRABLE will make the transition.
+ * POWER_STATE_CHANGED will make the transition.
*/
final class BluetoothAdapterStateMachine extends StateMachine {
private static final String TAG = "BluetoothAdapterStateMachine";
@@ -83,10 +83,10 @@ final class BluetoothAdapterStateMachine extends StateMachine {
static final int SERVICE_RECORD_LOADED = 51;
// Event indicates all the remote Bluetooth devices has been disconnected
static final int ALL_DEVICES_DISCONNECTED = 52;
- // Event indicates the Bluetooth is connectable
- static final int BECAME_PAIRABLE = 53;
- // Event indicates the Bluetooth is non-connectable.
- static final int BECAME_NON_PAIRABLE = 54;
+ // Event indicates the Bluetooth scan mode has changed
+ static final int SCAN_MODE_CHANGED = 53;
+ // Event indicates the powered state has changed
+ static final int POWER_STATE_CHANGED = 54;
// Event indicates airplane mode is turned on
static final int AIRPLANE_MODE_ON = 55;
// Event indicates airplane mode is turned off
@@ -107,6 +107,8 @@ final class BluetoothAdapterStateMachine extends StateMachine {
private static final int TURN_COLD = 103;
// Device disconnecting timeout happens
private static final int DEVICES_DISCONNECT_TIMEOUT = 104;
+ // Prepare Bluetooth timeout happens
+ private static final int PREPARE_BLUETOOTH_TIMEOUT = 105;
private Context mContext;
private BluetoothService mBluetoothService;
@@ -125,6 +127,8 @@ final class BluetoothAdapterStateMachine extends StateMachine {
// 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 = 7000;
+
BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
BluetoothAdapter bluetoothAdapter) {
super(TAG);
@@ -165,7 +169,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log("PowerOff process message: " + message.what);
+ log("PowerOff process message: " + message.what);
boolean retValue = HANDLED;
switch(message.what) {
@@ -257,6 +261,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
+ log("prepareBluetooth sleep interrupted: " + pollCount);
break;
}
}
@@ -274,6 +279,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
return false;
}
+ sendMessageDelayed(PREPARE_BLUETOOTH_TIMEOUT, PREPARE_BLUETOOTH_TIMEOUT_TIME);
return true;
}
}
@@ -291,13 +297,20 @@ final class BluetoothAdapterStateMachine extends StateMachine {
@Override
public boolean processMessage(Message message) {
- if (DBG) log("WarmUp process message: " + message.what);
+ log("WarmUp process message: " + message.what);
boolean retValue = HANDLED;
switch(message.what) {
case SERVICE_RECORD_LOADED:
+ removeMessages(PREPARE_BLUETOOTH_TIMEOUT);
transitionTo(mHotOff);
break;
+ case PREPARE_BLUETOOTH_TIMEOUT:
+ Log.e(TAG, "Bluetooth adapter SDP failed to load");
+ shutoffBluetooth();
+ transitionTo(mPowerOff);
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ break;
case USER_TURN_ON: // handle this at HotOff state
case TURN_ON_CONTINUE: // Once in HotOff state, continue turn bluetooth
// on to the BluetoothOn state
@@ -331,7 +344,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
@Override
public boolean processMessage(Message message) {
- if (DBG) log("HotOff process message: " + message.what);
+ log("HotOff process message: " + message.what);
boolean retValue = HANDLED;
switch(message.what) {
@@ -348,8 +361,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
break;
case AIRPLANE_MODE_ON:
case TURN_COLD:
- mBluetoothService.shutoffBluetooth();
- mEventLoop.stop();
+ shutoffBluetooth();
transitionTo(mPowerOff);
broadcastState(BluetoothAdapter.STATE_OFF);
break;
@@ -390,32 +402,32 @@ final class BluetoothAdapterStateMachine extends StateMachine {
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log("Switching process message: " + message.what);
+ log("Switching process message: " + message.what);
boolean retValue = HANDLED;
switch(message.what) {
- case BECAME_PAIRABLE:
- mBluetoothService.initBluetoothAfterTurningOn();
- transitionTo(mBluetoothOn);
- broadcastState(BluetoothAdapter.STATE_ON);
- // run bluetooth now that it's turned on
- // Note runBluetooth should be called only in adapter STATE_ON
- mBluetoothService.runBluetooth();
+ case SCAN_MODE_CHANGED:
+ // This event matches mBluetoothService.switchConnectable action
+ if (mPublicState == BluetoothAdapter.STATE_TURNING_ON) {
+ // set pairable if it's not
+ mBluetoothService.setPairable();
+ mBluetoothService.initBluetoothAfterTurningOn();
+ transitionTo(mBluetoothOn);
+ broadcastState(BluetoothAdapter.STATE_ON);
+ // run bluetooth now that it's turned on
+ // Note runBluetooth should be called only in adapter STATE_ON
+ mBluetoothService.runBluetooth();
+ }
break;
- case BECAME_NON_PAIRABLE:
- if (mBluetoothService.getAdapterConnectionState() ==
- BluetoothAdapter.STATE_DISCONNECTED) {
- removeMessages(DEVICES_DISCONNECT_TIMEOUT);
+ case POWER_STATE_CHANGED:
+ if (!((Boolean) message.obj)) {
transitionTo(mHotOff);
finishSwitchingOff();
}
break;
case ALL_DEVICES_DISCONNECTED:
removeMessages(DEVICES_DISCONNECT_TIMEOUT);
- if (mBluetoothService.getScanMode() == BluetoothAdapter.SCAN_MODE_NONE) {
- transitionTo(mHotOff);
- finishSwitchingOff();
- }
+ mBluetoothService.switchConnectable(false);
break;
case DEVICES_DISCONNECT_TIMEOUT:
sendMessage(ALL_DEVICES_DISCONNECTED);
@@ -461,7 +473,7 @@ final class BluetoothAdapterStateMachine extends StateMachine {
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log("BluetoothOn process message: " + message.what);
+ log("BluetoothOn process message: " + message.what);
boolean retValue = HANDLED;
switch(message.what) {
@@ -482,9 +494,14 @@ final class BluetoothAdapterStateMachine extends StateMachine {
case AIRPLANE_MODE_ON:
transitionTo(mSwitching);
broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
- mBluetoothService.switchConnectable(false);
- mBluetoothService.disconnectDevices();
- sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT, DEVICES_DISCONNECT_TIMEOUT_TIME);
+ if (mBluetoothService.getAdapterConnectionState() !=
+ BluetoothAdapter.STATE_DISCONNECTED) {
+ mBluetoothService.disconnectDevices();
+ sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT,
+ DEVICES_DISCONNECT_TIMEOUT_TIME);
+ } else {
+ mBluetoothService.switchConnectable(false);
+ }
// we turn all the way to PowerOff with AIRPLANE_MODE_ON
if (message.what == AIRPLANE_MODE_ON) {
@@ -514,15 +531,25 @@ final class BluetoothAdapterStateMachine extends StateMachine {
private class PerProcessState extends State {
IBluetoothStateChangeCallback mCallback = null;
+ boolean isTurningOn = false;
@Override
public void enter() {
- if (DBG) log("Enter PerProcessState: " + getCurrentMessage().what);
+ int what = getCurrentMessage().what;
+ if (DBG) log("Enter PerProcessState: " + what);
+
+ if (what == PER_PROCESS_TURN_ON) {
+ isTurningOn = true;
+ } else if (what == PER_PROCESS_TURN_OFF) {
+ isTurningOn = false;
+ } else {
+ Log.e(TAG, "enter PerProcessState: wrong msg: " + what);
+ }
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log("PerProcessState process message: " + message.what);
+ log("PerProcessState process message: " + message.what);
boolean retValue = HANDLED;
switch (message.what) {
@@ -534,8 +561,20 @@ final class BluetoothAdapterStateMachine extends StateMachine {
perProcessCallback(true, mCallback);
}
break;
- case BECAME_PAIRABLE:
- perProcessCallback(true, mCallback);
+ case SCAN_MODE_CHANGED:
+ if (isTurningOn) {
+ perProcessCallback(true, mCallback);
+ isTurningOn = false;
+ }
+ break;
+ case POWER_STATE_CHANGED:
+ if (!((Boolean) message.obj)) {
+ transitionTo(mHotOff);
+ if (!mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ deferMessage(obtainMessage(TURN_COLD));
+ }
+ }
break;
case USER_TURN_ON:
broadcastState(BluetoothAdapter.STATE_TURNING_ON);
@@ -579,13 +618,6 @@ final class BluetoothAdapterStateMachine extends StateMachine {
mBluetoothService.switchConnectable(false);
}
break;
- case BECAME_NON_PAIRABLE:
- transitionTo(mHotOff);
- if (!mContext.getResources().getBoolean
- (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
- deferMessage(obtainMessage(TURN_COLD));
- }
- break;
case AIRPLANE_MODE_ON:
mBluetoothService.switchConnectable(false);
allProcessesCallback(false);
@@ -602,6 +634,11 @@ final class BluetoothAdapterStateMachine extends StateMachine {
}
}
+ private void shutoffBluetooth() {
+ mBluetoothService.shutoffBluetooth();
+ mEventLoop.stop();
+ mBluetoothService.cleanNativeAfterShutoffBluetooth();
+ }
private void perProcessCallback(boolean on, IBluetoothStateChangeCallback c) {
if (c == null) return;
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index d73f8c9..6eff796 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -322,6 +322,12 @@ class BluetoothEventLoop {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
} else if (name.equals("Pairable") || name.equals("Discoverable")) {
+ adapterProperties.setProperty(name, propValues[1]);
+
+ if (name.equals("Discoverable")) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED);
+ }
+
String pairable = name.equals("Pairable") ? propValues[1] :
adapterProperties.getProperty("Pairable");
String discoverable = name.equals("Discoverable") ? propValues[1] :
@@ -331,16 +337,6 @@ class BluetoothEventLoop {
if (pairable == null || discoverable == null)
return;
- adapterProperties.setProperty(name, propValues[1]);
-
- if (name.equals("Pairable")) {
- if (pairable.equals("true")) {
- mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECAME_PAIRABLE);
- } else {
- mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECAME_NON_PAIRABLE);
- }
- }
-
int mode = BluetoothService.bluezStringToScanMode(
pairable.equals("true"),
discoverable.equals("true"));
@@ -377,10 +373,11 @@ class BluetoothEventLoop {
mBluetoothService.updateBluetoothState(value);
}
} else if (name.equals("Powered")) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.POWER_STATE_CHANGED,
+ propValues[1].equals("true") ? new Boolean(true) : new Boolean(false));
// bluetoothd has restarted, re-read all our properties.
// Note: bluez only sends this property change when it restarts.
- if (propValues[1].equals("true"))
- onRestartRequired();
+ onRestartRequired();
} else if (name.equals("DiscoverableTimeout")) {
adapterProperties.setProperty(name, propValues[1]);
}
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 0357958..ee14673 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -437,7 +437,21 @@ public class BluetoothService extends IBluetooth.Stub {
* power off Bluetooth
*/
synchronized void shutoffBluetooth() {
+ if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles);
+ setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE,
+ BluetoothPanProfileHandler.NAP_BRIDGE);
tearDownNativeDataNative();
+ }
+
+ /**
+ * Data clean up after Bluetooth shutoff
+ */
+ synchronized void cleanNativeAfterShutoffBluetooth() {
+ // Ths method is called after shutdown of event loop in the Bluetooth shut down
+ // procedure
+
+ // the adapter property could be changed before event loop is stoped, clear it again
+ mAdapterProperties.clear();
disableNative();
if (mRestart) {
mRestart = false;
@@ -743,26 +757,6 @@ public class BluetoothService extends IBluetooth.Stub {
public synchronized boolean setScanMode(int mode, int duration) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
"Need WRITE_SECURE_SETTINGS permission");
- return setScanMode(mode, duration, true);
- }
-
- /**
- * @param on true set the local Bluetooth module to be connectable
- * but not dicoverable
- * false set the local Bluetooth module to be not connectable
- * and not dicoverable
- */
- /*package*/ synchronized void switchConnectable(boolean on) {
- if (on) {
- // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE
- setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false);
- } else {
- // 0 is a dummy value, does not apply for SCAN_MODE_NONE
- setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false);
- }
- }
-
- private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) {
boolean pairable;
boolean discoverable;
@@ -785,19 +779,33 @@ public class BluetoothService extends IBluetooth.Stub {
return false;
}
- if (allowOnlyInOnState) {
- setPropertyBoolean("Discoverable", discoverable);
- setPropertyBoolean("Pairable", pairable);
- } else {
- // allowed to set the property through native layer directly
- setAdapterPropertyBooleanNative("Discoverable", discoverable ? 1 : 0);
- // do setting pairable after setting discoverable since the adapter
- // state machine uses pairable event for state change
- setAdapterPropertyBooleanNative("Pairable", pairable ? 1 : 0);
- }
+ setPropertyBoolean("Discoverable", discoverable);
+ setPropertyBoolean("Pairable", pairable);
return true;
}
+ /**
+ * @param on true set the local Bluetooth module to be connectable
+ * The dicoverability is recovered to what it was before
+ * switchConnectable(false) call
+ * false set the local Bluetooth module to be not connectable
+ * and not dicoverable
+ */
+ /*package*/ synchronized void switchConnectable(boolean on) {
+ setAdapterPropertyBooleanNative("Powered", on ? 1 : 0);
+ }
+
+ /*package*/ synchronized void setPairable() {
+ String pairableString = getProperty("Pairable", false);
+ if (pairableString == null) {
+ Log.e(TAG, "null pairableString");
+ return;
+ }
+ if (pairableString.equals("false")) {
+ setAdapterPropertyBooleanNative("Pairable", 1);
+ }
+ }
+
/*package*/ synchronized String getProperty(String name, boolean checkState) {
// If checkState is false, check if the event loop is running.
// before making the call to Bluez