Loading core/java/android/server/BluetoothAdapterStateMachine.java +81 −44 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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"; Loading @@ -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 Loading @@ -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; Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -257,6 +261,7 @@ final class BluetoothAdapterStateMachine extends StateMachine { try { Thread.sleep(100); } catch (InterruptedException e) { log("prepareBluetooth sleep interrupted: " + pollCount); break; } } Loading @@ -274,6 +279,7 @@ final class BluetoothAdapterStateMachine extends StateMachine { return false; } sendMessageDelayed(PREPARE_BLUETOOTH_TIMEOUT, PREPARE_BLUETOOTH_TIMEOUT_TIME); return true; } } Loading @@ -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 Loading Loading @@ -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) { Loading @@ -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; Loading Loading @@ -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: 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); Loading Loading @@ -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) { Loading @@ -482,9 +494,14 @@ final class BluetoothAdapterStateMachine extends StateMachine { case AIRPLANE_MODE_ON: transitionTo(mSwitching); broadcastState(BluetoothAdapter.STATE_TURNING_OFF); mBluetoothService.switchConnectable(false); if (mBluetoothService.getAdapterConnectionState() != BluetoothAdapter.STATE_DISCONNECTED) { mBluetoothService.disconnectDevices(); sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT, DEVICES_DISCONNECT_TIMEOUT_TIME); 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) { Loading Loading @@ -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) { Loading @@ -534,8 +561,20 @@ final class BluetoothAdapterStateMachine extends StateMachine { perProcessCallback(true, mCallback); } break; case BECAME_PAIRABLE: 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); Loading Loading @@ -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); Loading @@ -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; Loading core/java/android/server/BluetoothEventLoop.java +9 −12 Original line number Diff line number Diff line Loading @@ -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] : Loading @@ -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")); Loading Loading @@ -377,9 +373,10 @@ 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(); } else if (name.equals("DiscoverableTimeout")) { adapterProperties.setProperty(name, propValues[1]); Loading core/java/android/server/BluetoothService.java +38 −30 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); } 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 Loading Loading
core/java/android/server/BluetoothAdapterStateMachine.java +81 −44 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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"; Loading @@ -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 Loading @@ -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; Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -257,6 +261,7 @@ final class BluetoothAdapterStateMachine extends StateMachine { try { Thread.sleep(100); } catch (InterruptedException e) { log("prepareBluetooth sleep interrupted: " + pollCount); break; } } Loading @@ -274,6 +279,7 @@ final class BluetoothAdapterStateMachine extends StateMachine { return false; } sendMessageDelayed(PREPARE_BLUETOOTH_TIMEOUT, PREPARE_BLUETOOTH_TIMEOUT_TIME); return true; } } Loading @@ -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 Loading Loading @@ -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) { Loading @@ -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; Loading Loading @@ -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: 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); Loading Loading @@ -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) { Loading @@ -482,9 +494,14 @@ final class BluetoothAdapterStateMachine extends StateMachine { case AIRPLANE_MODE_ON: transitionTo(mSwitching); broadcastState(BluetoothAdapter.STATE_TURNING_OFF); mBluetoothService.switchConnectable(false); if (mBluetoothService.getAdapterConnectionState() != BluetoothAdapter.STATE_DISCONNECTED) { mBluetoothService.disconnectDevices(); sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT, DEVICES_DISCONNECT_TIMEOUT_TIME); 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) { Loading Loading @@ -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) { Loading @@ -534,8 +561,20 @@ final class BluetoothAdapterStateMachine extends StateMachine { perProcessCallback(true, mCallback); } break; case BECAME_PAIRABLE: 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); Loading Loading @@ -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); Loading @@ -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; Loading
core/java/android/server/BluetoothEventLoop.java +9 −12 Original line number Diff line number Diff line Loading @@ -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] : Loading @@ -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")); Loading Loading @@ -377,9 +373,10 @@ 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(); } else if (name.equals("DiscoverableTimeout")) { adapterProperties.setProperty(name, propValues[1]); Loading
core/java/android/server/BluetoothService.java +38 −30 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); } 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 Loading