am a224f70b: Fix interaction between BluetoothEventLoop and BluetoothService.

Merge commit 'a224f70b1efc29d9698da5b5c143251a43838f2b' into gingerbread-plus-aosp

* commit 'a224f70b1efc29d9698da5b5c143251a43838f2b':
  Fix interaction between BluetoothEventLoop and BluetoothService.
This commit is contained in:
Jaikumar Ganesh
2010-09-14 09:43:31 -07:00
committed by Android Git Automerger
2 changed files with 107 additions and 90 deletions

View File

@@ -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;
@@ -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;
@@ -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) {
@@ -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;
@@ -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;
@@ -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) {
@@ -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);
}
}
@@ -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")) {
@@ -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;
}
@@ -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);
@@ -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
@@ -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

View File

@@ -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
@@ -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;
}
}
};
@@ -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.
@@ -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)) {
@@ -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);