Files
app_Settings/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java
Jake Hamby dd79a33ba5 Auto-connect Bluetooth device only when user initiates pairing.
Fix bug 2271901: do not auto-connect to services on a BT device
when pairing was initiated by the device (e.g. for OPP file transfer).

Also corrected some typos and removed an unneeded lock object in
LocalBluetoothManager (synchronize on .class object instead, like
android.bluetooth.BluetoothDevice.getService() does).

Change-Id: I121105c6eee2658129f6094786754bbc7932d324
2010-09-24 14:23:26 -07:00

269 lines
9.5 KiB
Java

/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.bluetooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.bluetooth.LocalBluetoothManager.Callback;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
*/
public class CachedBluetoothDeviceManager {
private static final String TAG = "CachedBluetoothDeviceManager";
final LocalBluetoothManager mLocalManager;
final List<Callback> mCallbacks;
final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
public CachedBluetoothDeviceManager(LocalBluetoothManager localManager) {
mLocalManager = localManager;
mCallbacks = localManager.getCallbacks();
}
private synchronized boolean readPairedDevices() {
BluetoothAdapter adapter = mLocalManager.getBluetoothAdapter();
Set<BluetoothDevice> bondedDevices = adapter.getBondedDevices();
if (bondedDevices == null) return false;
boolean deviceAdded = false;
for (BluetoothDevice device : bondedDevices) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice == null) {
cachedDevice = new CachedBluetoothDevice(mLocalManager.getContext(), device);
mCachedDevices.add(cachedDevice);
dispatchDeviceAdded(cachedDevice);
deviceAdded = true;
}
}
return deviceAdded;
}
public synchronized List<CachedBluetoothDevice> getCachedDevicesCopy() {
return new ArrayList<CachedBluetoothDevice>(mCachedDevices);
}
void onBluetoothStateChanged(boolean enabled) {
if (enabled) {
readPairedDevices();
}
}
public synchronized void onDeviceAppeared(BluetoothDevice device, short rssi,
BluetoothClass btClass, String name) {
boolean deviceAdded = false;
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice == null) {
cachedDevice = new CachedBluetoothDevice(mLocalManager.getContext(), device);
mCachedDevices.add(cachedDevice);
deviceAdded = true;
}
cachedDevice.setRssi(rssi);
cachedDevice.setBtClass(btClass);
cachedDevice.setName(name);
cachedDevice.setVisible(true);
if (deviceAdded) {
dispatchDeviceAdded(cachedDevice);
}
}
public synchronized void onDeviceDisappeared(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice == null) return;
cachedDevice.setVisible(false);
checkForDeviceRemoval(cachedDevice);
}
private void checkForDeviceRemoval(CachedBluetoothDevice cachedDevice) {
if (cachedDevice.getBondState() == BluetoothDevice.BOND_NONE &&
!cachedDevice.isVisible()) {
// If device isn't paired, remove it altogether
mCachedDevices.remove(cachedDevice);
dispatchDeviceDeleted(cachedDevice);
}
}
public synchronized void onDeviceNameUpdated(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice != null) {
cachedDevice.refreshName();
}
}
public synchronized CachedBluetoothDevice findDevice(BluetoothDevice device) {
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
if (cachedDevice.getDevice().equals(device)) {
return cachedDevice;
}
}
return null;
}
/**
* Attempts to get the name of a remote device, otherwise returns the address.
*
* @param device The remote device.
* @return The name, or if unavailable, the address.
*/
public String getName(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice != null) return cachedDevice.getName();
String name = device.getName();
if (name != null) return name;
return device.getAddress();
}
private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
synchronized (mCallbacks) {
for (Callback callback : mCallbacks) {
callback.onDeviceAdded(cachedDevice);
}
}
// TODO: divider between prev paired/connected and scanned
}
private void dispatchDeviceDeleted(CachedBluetoothDevice cachedDevice) {
synchronized (mCallbacks) {
for (Callback callback : mCallbacks) {
callback.onDeviceDeleted(cachedDevice);
}
}
}
public synchronized void onBondingStateChanged(BluetoothDevice device, int bondState) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice == null) {
if (!readPairedDevices()) {
Log.e(TAG, "Got bonding state changed for " + device +
", but we have no record of that device.");
return;
}
cachedDevice = findDevice(device);
if (cachedDevice == null) {
Log.e(TAG, "Got bonding state changed for " + device +
"but device not added in cache");
return;
}
}
cachedDevice.onBondingStateChanged(bondState);
}
/**
* Called when we have reached the un-bond state.
*
* @param device The remote device.
* @param reason The reason, one of the error reasons from
* BluetoothDevice.UNBOND_REASON_*
*/
public synchronized void showUnbondMessage(BluetoothDevice device, int reason) {
int errorMsg;
switch(reason) {
case BluetoothDevice.UNBOND_REASON_AUTH_FAILED:
errorMsg = R.string.bluetooth_pairing_pin_error_message;
mLocalManager.showError(device, R.string.bluetooth_error_title, errorMsg);
break;
case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED:
errorMsg = R.string.bluetooth_pairing_rejected_error_message;
mLocalManager.showError(device, R.string.bluetooth_error_title, errorMsg);
break;
case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN:
errorMsg = R.string.bluetooth_pairing_device_down_error_message;
mLocalManager.showError(device, R.string.bluetooth_error_title, errorMsg);
break;
case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS:
case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT:
case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS:
case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED:
errorMsg = R.string.bluetooth_pairing_error_message;
mLocalManager.showError(device, R.string.bluetooth_error_title, errorMsg);
break;
default:
Log.w(TAG, "showUnbondMessage: Not displaying any message for reason:" + reason);
break;
}
}
public synchronized void onProfileStateChanged(BluetoothDevice device, Profile profile,
int newProfileState) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice == null) return;
cachedDevice.onProfileStateChanged(profile, newProfileState);
cachedDevice.refresh();
}
public synchronized void onConnectingError(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice == null) return;
/*
* Go through the device's delegate so we don't spam the user with
* errors connecting to different profiles, and instead make sure the
* user sees a single error for his single 'connect' action.
*/
cachedDevice.showConnectingError();
}
public synchronized void onScanningStateChanged(boolean started) {
if (!started) return;
// If starting a new scan, clear old visibility
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
cachedDevice.setVisible(false);
checkForDeviceRemoval(cachedDevice);
}
}
public synchronized void onBtClassChanged(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice != null) {
cachedDevice.refreshBtClass();
}
}
public synchronized void onUuidChanged(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice != null) {
cachedDevice.onUuidChanged();
}
}
}