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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user