Loading core/java/android/server/BluetoothEventLoop.java +17 −88 Original line number Diff line number Diff line Loading @@ -57,22 +57,14 @@ class BluetoothEventLoop { // from remote device when Android is in Suspend state. private PowerManager.WakeLock mWakeLock; private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1; private static final int EVENT_RESTART_BLUETOOTH = 2; private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 3; private static final int EVENT_AGENT_CANCEL = 4; private static final int EVENT_RESTART_BLUETOOTH = 1; private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 2; private static final int EVENT_AGENT_CANCEL = 3; private static final int CREATE_DEVICE_ALREADY_EXISTS = 1; private static final int CREATE_DEVICE_SUCCESS = 0; private static final int CREATE_DEVICE_FAILED = -1; // The time (in millisecs) to delay the pairing attempt after the first // auto pairing attempt fails. We use an exponential delay with // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value. private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000; private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; Loading @@ -81,13 +73,6 @@ class BluetoothEventLoop { public void handleMessage(Message msg) { String address = null; switch (msg.what) { case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: address = (String)msg.obj; if (address != null) { mBluetoothService.createBond(address); return; } break; case EVENT_RESTART_BLUETOOTH: mBluetoothService.restart(); break; Loading @@ -100,8 +85,7 @@ class BluetoothEventLoop { case EVENT_AGENT_CANCEL: // Set the Bond State to BOND_NONE. // We always have only 1 device in BONDING state. String[] devices = mBluetoothService.getBondState().listInState(BluetoothDevice.BOND_BONDING); String[] devices = mBluetoothService.listInState(BluetoothDevice.BOND_BONDING); if (devices.length == 0) { break; } else if (devices.length > 1) { Loading @@ -109,7 +93,7 @@ class BluetoothEventLoop { break; } address = devices[0]; mBluetoothService.getBondState().setBondState(address, mBluetoothService.setBondState(address, BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED); break; Loading @@ -120,7 +104,7 @@ class BluetoothEventLoop { static { classInitNative(); } private static native void classInitNative(); /* pacakge */ BluetoothEventLoop(Context context, BluetoothAdapter adapter, /* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter, BluetoothService bluetoothService) { mBluetoothService = bluetoothService; mContext = context; Loading Loading @@ -219,55 +203,7 @@ class BluetoothEventLoop { private void onCreatePairedDeviceResult(String address, int result) { address = address.toUpperCase(); if (result == BluetoothDevice.BOND_SUCCESS) { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED); if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) { mBluetoothService.getBondState().clearPinAttempts(address); } } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED && mBluetoothService.getBondState().getAttempt(address) == 1) { mBluetoothService.getBondState().addAutoPairingFailure(address); pairingAttempt(address, result); } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN && mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) { pairingAttempt(address, result); } else { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NONE, result); if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) { mBluetoothService.getBondState().clearPinAttempts(address); } } } private void pairingAttempt(String address, int result) { // This happens when our initial guess of "0000" as the pass key // fails. Try to create the bond again and display the pin dialog // to the user. Use back-off while posting the delayed // message. The initial value is // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is // reached, display an error to the user. int attempt = mBluetoothService.getBondState().getAttempt(address); if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY > MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) { mBluetoothService.getBondState().clearPinAttempts(address); mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NONE, result); return; } Message message = mHandler.obtainMessage(EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); message.obj = address; boolean postResult = mHandler.sendMessageDelayed(message, attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); if (!postResult) { mBluetoothService.getBondState().clearPinAttempts(address); mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NONE, result); return; } mBluetoothService.getBondState().attempt(address); mBluetoothService.onCreatePairedDeviceResult(address, result); } private void onDeviceCreated(String deviceObjectPath) { Loading @@ -285,8 +221,8 @@ class BluetoothEventLoop { private void onDeviceRemoved(String deviceObjectPath) { String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); if (address != null) { mBluetoothService.getBondState().setBondState(address.toUpperCase(), BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED); mBluetoothService.setBondState(address.toUpperCase(), BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED); mBluetoothService.setRemoteDeviceProperty(address, "UUIDs", null); } } Loading Loading @@ -417,13 +353,11 @@ class BluetoothEventLoop { // If locally initiated pairing, we will // not go to BOND_BONDED state until we have received a // successful return value in onCreatePairedDeviceResult if (null == mBluetoothService.getBondState().getPendingOutgoingBonding()) { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED); if (null == mBluetoothService.getPendingOutgoingBonding()) { mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDED); } } else { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NONE); mBluetoothService.setBondState(address, BluetoothDevice.BOND_NONE); mBluetoothService.setRemoteDeviceProperty(address, "Trusted", "false"); } } else if (name.equals("Trusted")) { Loading Loading @@ -453,8 +387,8 @@ class BluetoothEventLoop { // Also set it only when the state is not already Bonded, we can sometimes // get an authorization request from the remote end if it doesn't have the link key // while we still have it. if (mBluetoothService.getBondState().getBondState(address) != BluetoothDevice.BOND_BONDED) mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDING); if (mBluetoothService.getBondState(address) != BluetoothDevice.BOND_BONDED) mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDING); return address; } Loading @@ -468,7 +402,7 @@ class BluetoothEventLoop { * so we may get this request many times. Also if we respond immediately, * the other end is unable to handle it. Delay sending the message. */ if (mBluetoothService.getBondState().getBondState(address) == BluetoothDevice.BOND_BONDED) { if (mBluetoothService.getBondState(address) == BluetoothDevice.BOND_BONDED) { Message message = mHandler.obtainMessage(EVENT_PAIRING_CONSENT_DELAYED_ACCEPT); message.obj = address; mHandler.sendMessageDelayed(message, 1500); Loading Loading @@ -522,7 +456,7 @@ class BluetoothEventLoop { if (address == null) return; String pendingOutgoingAddress = mBluetoothService.getBondState().getPendingOutgoingBonding(); mBluetoothService.getPendingOutgoingBonding(); if (address.equals(pendingOutgoingAddress)) { // we initiated the bonding Loading @@ -543,12 +477,7 @@ class BluetoothEventLoop { case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO: case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO: if (!mBluetoothService.getBondState().hasAutoPairingFailed(address) && !mBluetoothService.getBondState().isAutoPairingBlacklisted(address)) { mBluetoothService.getBondState().attempt(address); mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000")); return; } if (mBluetoothService.attemptAutoPair(address)) return; } } // Acquire wakelock during PIN code request to bring up LCD display Loading core/java/android/server/BluetoothService.java +90 −2 Original line number Diff line number Diff line Loading @@ -104,6 +104,14 @@ public class BluetoothService extends IBluetooth.Stub { private static final int MESSAGE_FINISH_DISABLE = 2; private static final int MESSAGE_UUID_INTENT = 3; private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 5; // The time (in millisecs) to delay the pairing attempt after the first // auto pairing attempt fails. We use an exponential delay with // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value. private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000; private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000; // The timeout used to sent the UUIDs Intent // This timeout should be greater than the page timeout Loading Loading @@ -502,6 +510,13 @@ public class BluetoothService extends IBluetooth.Stub { setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, -1); } break; case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: address = (String)msg.obj; if (address != null) { createBond(address); return; } break; } } }; Loading Loading @@ -591,8 +606,68 @@ public class BluetoothService extends IBluetooth.Stub { Binder.restoreCallingIdentity(origCallerIdentityToken); } /* package */ BondState getBondState() { return mBondState; /*package*/ synchronized boolean attemptAutoPair(String address) { if (!mBondState.hasAutoPairingFailed(address) && !mBondState.isAutoPairingBlacklisted(address)) { mBondState.attempt(address); setPin(address, BluetoothDevice.convertPinToBytes("0000")); return true; } return false; } /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) { if (result == BluetoothDevice.BOND_SUCCESS) { setBondState(address, BluetoothDevice.BOND_BONDED); if (mBondState.isAutoPairingAttemptsInProgress(address)) { mBondState.clearPinAttempts(address); } } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED && mBondState.getAttempt(address) == 1) { mBondState.addAutoPairingFailure(address); pairingAttempt(address, result); } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN && mBondState.isAutoPairingAttemptsInProgress(address)) { pairingAttempt(address, result); } else { setBondState(address, BluetoothDevice.BOND_NONE, result); if (mBondState.isAutoPairingAttemptsInProgress(address)) { mBondState.clearPinAttempts(address); } } } /*package*/ synchronized String getPendingOutgoingBonding() { return mBondState.getPendingOutgoingBonding(); } private void pairingAttempt(String address, int result) { // This happens when our initial guess of "0000" as the pass key // fails. Try to create the bond again and display the pin dialog // to the user. Use back-off while posting the delayed // message. The initial value is // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is // reached, display an error to the user. int attempt = mBondState.getAttempt(address); if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY > MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) { mBondState.clearPinAttempts(address); setBondState(address, BluetoothDevice.BOND_NONE, result); return; } Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); message.obj = address; boolean postResult = mHandler.sendMessageDelayed(message, attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); if (!postResult) { mBondState.clearPinAttempts(address); setBondState(address, BluetoothDevice.BOND_NONE, result); return; } mBondState.attempt(address); } /** local cache of bonding state. Loading Loading @@ -1259,6 +1334,10 @@ public class BluetoothService extends IBluetooth.Stub { return mBondState.listInState(BluetoothDevice.BOND_BONDED); } /*package*/ synchronized String[] listInState(int state) { return mBondState.listInState(state); } public synchronized int getBondState(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (!BluetoothAdapter.checkBluetoothAddress(address)) { Loading @@ -1267,6 +1346,15 @@ public class BluetoothService extends IBluetooth.Stub { return mBondState.getBondState(address.toUpperCase()); } /*package*/ synchronized boolean setBondState(String address, int state) { return setBondState(address, state, 0); } /*package*/ synchronized boolean setBondState(String address, int state, int reason) { mBondState.setBondState(address.toUpperCase(), state); return true; } public synchronized boolean isBluetoothDock(String address) { SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, mContext.MODE_PRIVATE); Loading Loading
core/java/android/server/BluetoothEventLoop.java +17 −88 Original line number Diff line number Diff line Loading @@ -57,22 +57,14 @@ class BluetoothEventLoop { // from remote device when Android is in Suspend state. private PowerManager.WakeLock mWakeLock; private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1; private static final int EVENT_RESTART_BLUETOOTH = 2; private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 3; private static final int EVENT_AGENT_CANCEL = 4; private static final int EVENT_RESTART_BLUETOOTH = 1; private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 2; private static final int EVENT_AGENT_CANCEL = 3; private static final int CREATE_DEVICE_ALREADY_EXISTS = 1; private static final int CREATE_DEVICE_SUCCESS = 0; private static final int CREATE_DEVICE_FAILED = -1; // The time (in millisecs) to delay the pairing attempt after the first // auto pairing attempt fails. We use an exponential delay with // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value. private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000; private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; Loading @@ -81,13 +73,6 @@ class BluetoothEventLoop { public void handleMessage(Message msg) { String address = null; switch (msg.what) { case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: address = (String)msg.obj; if (address != null) { mBluetoothService.createBond(address); return; } break; case EVENT_RESTART_BLUETOOTH: mBluetoothService.restart(); break; Loading @@ -100,8 +85,7 @@ class BluetoothEventLoop { case EVENT_AGENT_CANCEL: // Set the Bond State to BOND_NONE. // We always have only 1 device in BONDING state. String[] devices = mBluetoothService.getBondState().listInState(BluetoothDevice.BOND_BONDING); String[] devices = mBluetoothService.listInState(BluetoothDevice.BOND_BONDING); if (devices.length == 0) { break; } else if (devices.length > 1) { Loading @@ -109,7 +93,7 @@ class BluetoothEventLoop { break; } address = devices[0]; mBluetoothService.getBondState().setBondState(address, mBluetoothService.setBondState(address, BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED); break; Loading @@ -120,7 +104,7 @@ class BluetoothEventLoop { static { classInitNative(); } private static native void classInitNative(); /* pacakge */ BluetoothEventLoop(Context context, BluetoothAdapter adapter, /* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter, BluetoothService bluetoothService) { mBluetoothService = bluetoothService; mContext = context; Loading Loading @@ -219,55 +203,7 @@ class BluetoothEventLoop { private void onCreatePairedDeviceResult(String address, int result) { address = address.toUpperCase(); if (result == BluetoothDevice.BOND_SUCCESS) { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED); if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) { mBluetoothService.getBondState().clearPinAttempts(address); } } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED && mBluetoothService.getBondState().getAttempt(address) == 1) { mBluetoothService.getBondState().addAutoPairingFailure(address); pairingAttempt(address, result); } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN && mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) { pairingAttempt(address, result); } else { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NONE, result); if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) { mBluetoothService.getBondState().clearPinAttempts(address); } } } private void pairingAttempt(String address, int result) { // This happens when our initial guess of "0000" as the pass key // fails. Try to create the bond again and display the pin dialog // to the user. Use back-off while posting the delayed // message. The initial value is // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is // reached, display an error to the user. int attempt = mBluetoothService.getBondState().getAttempt(address); if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY > MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) { mBluetoothService.getBondState().clearPinAttempts(address); mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NONE, result); return; } Message message = mHandler.obtainMessage(EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); message.obj = address; boolean postResult = mHandler.sendMessageDelayed(message, attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); if (!postResult) { mBluetoothService.getBondState().clearPinAttempts(address); mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NONE, result); return; } mBluetoothService.getBondState().attempt(address); mBluetoothService.onCreatePairedDeviceResult(address, result); } private void onDeviceCreated(String deviceObjectPath) { Loading @@ -285,8 +221,8 @@ class BluetoothEventLoop { private void onDeviceRemoved(String deviceObjectPath) { String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); if (address != null) { mBluetoothService.getBondState().setBondState(address.toUpperCase(), BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED); mBluetoothService.setBondState(address.toUpperCase(), BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED); mBluetoothService.setRemoteDeviceProperty(address, "UUIDs", null); } } Loading Loading @@ -417,13 +353,11 @@ class BluetoothEventLoop { // If locally initiated pairing, we will // not go to BOND_BONDED state until we have received a // successful return value in onCreatePairedDeviceResult if (null == mBluetoothService.getBondState().getPendingOutgoingBonding()) { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED); if (null == mBluetoothService.getPendingOutgoingBonding()) { mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDED); } } else { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NONE); mBluetoothService.setBondState(address, BluetoothDevice.BOND_NONE); mBluetoothService.setRemoteDeviceProperty(address, "Trusted", "false"); } } else if (name.equals("Trusted")) { Loading Loading @@ -453,8 +387,8 @@ class BluetoothEventLoop { // Also set it only when the state is not already Bonded, we can sometimes // get an authorization request from the remote end if it doesn't have the link key // while we still have it. if (mBluetoothService.getBondState().getBondState(address) != BluetoothDevice.BOND_BONDED) mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDING); if (mBluetoothService.getBondState(address) != BluetoothDevice.BOND_BONDED) mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDING); return address; } Loading @@ -468,7 +402,7 @@ class BluetoothEventLoop { * so we may get this request many times. Also if we respond immediately, * the other end is unable to handle it. Delay sending the message. */ if (mBluetoothService.getBondState().getBondState(address) == BluetoothDevice.BOND_BONDED) { if (mBluetoothService.getBondState(address) == BluetoothDevice.BOND_BONDED) { Message message = mHandler.obtainMessage(EVENT_PAIRING_CONSENT_DELAYED_ACCEPT); message.obj = address; mHandler.sendMessageDelayed(message, 1500); Loading Loading @@ -522,7 +456,7 @@ class BluetoothEventLoop { if (address == null) return; String pendingOutgoingAddress = mBluetoothService.getBondState().getPendingOutgoingBonding(); mBluetoothService.getPendingOutgoingBonding(); if (address.equals(pendingOutgoingAddress)) { // we initiated the bonding Loading @@ -543,12 +477,7 @@ class BluetoothEventLoop { case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO: case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO: if (!mBluetoothService.getBondState().hasAutoPairingFailed(address) && !mBluetoothService.getBondState().isAutoPairingBlacklisted(address)) { mBluetoothService.getBondState().attempt(address); mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000")); return; } if (mBluetoothService.attemptAutoPair(address)) return; } } // Acquire wakelock during PIN code request to bring up LCD display Loading
core/java/android/server/BluetoothService.java +90 −2 Original line number Diff line number Diff line Loading @@ -104,6 +104,14 @@ public class BluetoothService extends IBluetooth.Stub { private static final int MESSAGE_FINISH_DISABLE = 2; private static final int MESSAGE_UUID_INTENT = 3; private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 5; // The time (in millisecs) to delay the pairing attempt after the first // auto pairing attempt fails. We use an exponential delay with // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value. private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000; private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000; // The timeout used to sent the UUIDs Intent // This timeout should be greater than the page timeout Loading Loading @@ -502,6 +510,13 @@ public class BluetoothService extends IBluetooth.Stub { setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, -1); } break; case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: address = (String)msg.obj; if (address != null) { createBond(address); return; } break; } } }; Loading Loading @@ -591,8 +606,68 @@ public class BluetoothService extends IBluetooth.Stub { Binder.restoreCallingIdentity(origCallerIdentityToken); } /* package */ BondState getBondState() { return mBondState; /*package*/ synchronized boolean attemptAutoPair(String address) { if (!mBondState.hasAutoPairingFailed(address) && !mBondState.isAutoPairingBlacklisted(address)) { mBondState.attempt(address); setPin(address, BluetoothDevice.convertPinToBytes("0000")); return true; } return false; } /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) { if (result == BluetoothDevice.BOND_SUCCESS) { setBondState(address, BluetoothDevice.BOND_BONDED); if (mBondState.isAutoPairingAttemptsInProgress(address)) { mBondState.clearPinAttempts(address); } } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED && mBondState.getAttempt(address) == 1) { mBondState.addAutoPairingFailure(address); pairingAttempt(address, result); } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN && mBondState.isAutoPairingAttemptsInProgress(address)) { pairingAttempt(address, result); } else { setBondState(address, BluetoothDevice.BOND_NONE, result); if (mBondState.isAutoPairingAttemptsInProgress(address)) { mBondState.clearPinAttempts(address); } } } /*package*/ synchronized String getPendingOutgoingBonding() { return mBondState.getPendingOutgoingBonding(); } private void pairingAttempt(String address, int result) { // This happens when our initial guess of "0000" as the pass key // fails. Try to create the bond again and display the pin dialog // to the user. Use back-off while posting the delayed // message. The initial value is // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is // reached, display an error to the user. int attempt = mBondState.getAttempt(address); if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY > MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) { mBondState.clearPinAttempts(address); setBondState(address, BluetoothDevice.BOND_NONE, result); return; } Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); message.obj = address; boolean postResult = mHandler.sendMessageDelayed(message, attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); if (!postResult) { mBondState.clearPinAttempts(address); setBondState(address, BluetoothDevice.BOND_NONE, result); return; } mBondState.attempt(address); } /** local cache of bonding state. Loading Loading @@ -1259,6 +1334,10 @@ public class BluetoothService extends IBluetooth.Stub { return mBondState.listInState(BluetoothDevice.BOND_BONDED); } /*package*/ synchronized String[] listInState(int state) { return mBondState.listInState(state); } public synchronized int getBondState(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (!BluetoothAdapter.checkBluetoothAddress(address)) { Loading @@ -1267,6 +1346,15 @@ public class BluetoothService extends IBluetooth.Stub { return mBondState.getBondState(address.toUpperCase()); } /*package*/ synchronized boolean setBondState(String address, int state) { return setBondState(address, state, 0); } /*package*/ synchronized boolean setBondState(String address, int state, int reason) { mBondState.setBondState(address.toUpperCase(), state); return true; } public synchronized boolean isBluetoothDock(String address) { SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, mContext.MODE_PRIVATE); Loading