1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.bluetooth; 18 19 import android.bluetooth.BluetoothAdapter; 20 import android.bluetooth.BluetoothDevice; 21 import android.content.Context; 22 import android.util.Log; 23 24 import java.util.ArrayList; 25 import java.util.Collection; 26 import java.util.List; 27 28 /** 29 * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices. 30 */ 31 final class CachedBluetoothDeviceManager { 32 private static final String TAG = "CachedBluetoothDeviceManager"; 33 private static final boolean DEBUG = Utils.D; 34 35 private Context mContext; 36 private final List<CachedBluetoothDevice> mCachedDevices = 37 new ArrayList<CachedBluetoothDevice>(); 38 39 CachedBluetoothDeviceManager(Context context) { 40 mContext = context; 41 } 42 43 public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() { 44 return new ArrayList<CachedBluetoothDevice>(mCachedDevices); 45 } 46 47 public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) { 48 cachedDevice.setVisible(false); 49 return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE; 50 } 51 52 public void onDeviceNameUpdated(BluetoothDevice device) { 53 CachedBluetoothDevice cachedDevice = findDevice(device); 54 if (cachedDevice != null) { 55 cachedDevice.refreshName(); 56 } 57 } 58 59 /** 60 * Search for existing {@link CachedBluetoothDevice} or return null 61 * if this device isn't in the cache. Use {@link #addDevice} 62 * to create and return a new {@link CachedBluetoothDevice} for 63 * a newly discovered {@link BluetoothDevice}. 64 * 65 * @param device the address of the Bluetooth device 66 * @return the cached device object for this device, or null if it has 67 * not been previously seen 68 */ 69 CachedBluetoothDevice findDevice(BluetoothDevice device) { 70 for (CachedBluetoothDevice cachedDevice : mCachedDevices) { 71 if (cachedDevice.getDevice().equals(device)) { 72 return cachedDevice; 73 } 74 } 75 return null; 76 } 77 78 /** 79 * Create and return a new {@link CachedBluetoothDevice}. This assumes 80 * that {@link #findDevice} has already been called and returned null. 81 * @param device the address of the new Bluetooth device 82 * @return the newly created CachedBluetoothDevice object 83 */ 84 CachedBluetoothDevice addDevice(LocalBluetoothAdapter adapter, 85 LocalBluetoothProfileManager profileManager, 86 BluetoothDevice device) { 87 CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter, 88 profileManager, device); 89 synchronized (mCachedDevices) { 90 mCachedDevices.add(newDevice); 91 } 92 return newDevice; 93 } 94 95 /** 96 * Attempts to get the name of a remote device, otherwise returns the address. 97 * 98 * @param device The remote device. 99 * @return The name, or if unavailable, the address. 100 */ 101 public String getName(BluetoothDevice device) { 102 CachedBluetoothDevice cachedDevice = findDevice(device); 103 if (cachedDevice != null) { 104 return cachedDevice.getName(); 105 } 106 107 String name = device.getAliasName(); 108 if (name != null) { 109 return name; 110 } 111 112 return device.getAddress(); 113 } 114 115 public synchronized void clearNonBondedDevices() { 116 for (int i = mCachedDevices.size() - 1; i >= 0; i--) { 117 CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); 118 if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) { 119 mCachedDevices.remove(i); 120 } 121 } 122 } 123 124 public synchronized void onScanningStateChanged(boolean started) { 125 if (!started) return; 126 127 // If starting a new scan, clear old visibility 128 // Iterate in reverse order since devices may be removed. 129 for (int i = mCachedDevices.size() - 1; i >= 0; i--) { 130 CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); 131 cachedDevice.setVisible(false); 132 } 133 } 134 135 public synchronized void onBtClassChanged(BluetoothDevice device) { 136 CachedBluetoothDevice cachedDevice = findDevice(device); 137 if (cachedDevice != null) { 138 cachedDevice.refreshBtClass(); 139 } 140 } 141 142 public synchronized void onUuidChanged(BluetoothDevice device) { 143 CachedBluetoothDevice cachedDevice = findDevice(device); 144 if (cachedDevice != null) { 145 cachedDevice.onUuidChanged(); 146 } 147 } 148 149 public synchronized void onBluetoothStateChanged(int bluetoothState) { 150 // When Bluetooth is turning off, we need to clear the non-bonded devices 151 // Otherwise, they end up showing up on the next BT enable 152 if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) { 153 for (int i = mCachedDevices.size() - 1; i >= 0; i--) { 154 CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); 155 if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) { 156 cachedDevice.setVisible(false); 157 mCachedDevices.remove(i); 158 } else { 159 // For bonded devices, we need to clear the connection status so that 160 // when BT is enabled next time, device connection status shall be retrieved 161 // by making a binder call. 162 cachedDevice.clearProfileConnectionState(); 163 } 164 } 165 } 166 } 167 private void log(String msg) { 168 if (DEBUG) { 169 Log.d(TAG, msg); 170 } 171 } 172 } 173