Files
packages_apps_Settings/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java
Jaikumar Ganesh fca3c1cf8b Check if a device is added to the cache before returning.
For incoming connections, we don't have the device in the Settings cache.
After we tried to readPairedDevices, check if we added to the cache.
If we successfully added it, continue with the connections, else bail out.

Bug id: 2160617

Change-Id: I25f2afba8ef6d2c32a7940f967cf12f1321ad9e0
2009-10-01 13:05:22 -07:00

274 lines
9.6 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();
readPairedDevices();
}
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);
if (bondState == BluetoothDevice.BOND_BONDED) {
// Auto-connect after pairing
cachedDevice.connect();
}
}
/**
* 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:
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();
}
}
}