diff options
author | Matthew Xie <mattx@google.com> | 2011-08-15 11:49:31 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-08-15 11:49:31 -0700 |
commit | 269cf1b2145d1f4d51615a98809522af65a8ec16 (patch) | |
tree | 6fc9b654717718ddb688124eaa0a85b4c1369bc7 | |
parent | 643c7dccbc86e470c8f81983b08029b750bf2b1c (diff) | |
parent | 14e48e91f6def5448db9994cb13ddcdc676cba53 (diff) | |
download | frameworks_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.java | 125 | ||||
-rw-r--r-- | core/java/android/server/BluetoothEventLoop.java | 21 | ||||
-rwxr-xr-x | core/java/android/server/BluetoothService.java | 68 |
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 |