1d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly/* 2d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * Copyright (C) 2008 The Android Open Source Project 3d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * 4d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 5d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * you may not use this file except in compliance with the License. 6d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * You may obtain a copy of the License at 7d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * 8d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 9d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * 10d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * Unless required by applicable law or agreed to in writing, software 11d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 12d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * See the License for the specific language governing permissions and 14d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * limitations under the License. 15d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly */ 16d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 17d63c0112251ab4e4e977545368dd703d875012a4Nick Pellypackage com.android.settings.bluetooth; 18d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 19737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamyimport android.bluetooth.BluetoothAdapter; 20d63c0112251ab4e4e977545368dd703d875012a4Nick Pellyimport android.bluetooth.BluetoothDevice; 21b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xieimport android.content.Context; 22b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xieimport android.util.Log; 23d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 24d63c0112251ab4e4e977545368dd703d875012a4Nick Pellyimport java.util.ArrayList; 25436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collection; 26d63c0112251ab4e4e977545368dd703d875012a4Nick Pellyimport java.util.List; 27d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 28d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly/** 29d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices. 30d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly */ 31436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class CachedBluetoothDeviceManager { 32b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private static final String TAG = "CachedBluetoothDeviceManager"; 33b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private static final boolean DEBUG = Utils.D; 34d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 35b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private Context mContext; 36436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final List<CachedBluetoothDevice> mCachedDevices = 37436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<CachedBluetoothDevice>(); 38d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 39b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie CachedBluetoothDeviceManager(Context context) { 40b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mContext = context; 41b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 42b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() { 44d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return new ArrayList<CachedBluetoothDevice>(mCachedDevices); 45d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 46d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 4779be0b3e6b5639c4cbe2bbcd9adb0ec4c28716edJake Hamby public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) { 48d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly cachedDevice.setVisible(false); 4979be0b3e6b5639c4cbe2bbcd9adb0ec4c28716edJake Hamby return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE; 50d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 51d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onDeviceNameUpdated(BluetoothDevice device) { 53d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly CachedBluetoothDevice cachedDevice = findDevice(device); 54d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if (cachedDevice != null) { 55d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly cachedDevice.refreshName(); 56d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 57d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 58d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 60436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Search for existing {@link CachedBluetoothDevice} or return null 61436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * if this device isn't in the cache. Use {@link #addDevice} 62436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * to create and return a new {@link CachedBluetoothDevice} for 63436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * a newly discovered {@link BluetoothDevice}. 64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param device the address of the Bluetooth device 66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @return the cached device object for this device, or null if it has 67436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * not been previously seen 68436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 69436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice findDevice(BluetoothDevice device) { 70436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (CachedBluetoothDevice cachedDevice : mCachedDevices) { 71d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if (cachedDevice.getDevice().equals(device)) { 72d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return cachedDevice; 73d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 74d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 75d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return null; 76d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 77d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 78d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly /** 79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Create and return a new {@link CachedBluetoothDevice}. This assumes 80436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * that {@link #findDevice} has already been called and returned null. 81436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param device the address of the new Bluetooth device 82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @return the newly created CachedBluetoothDevice object 83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice addDevice(LocalBluetoothAdapter adapter, 85436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothProfileManager profileManager, 86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 87b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter, 88b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie profileManager, device); 89436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mCachedDevices.add(newDevice); 90436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return newDevice; 91436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 92436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 93436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 94d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * Attempts to get the name of a remote device, otherwise returns the address. 95d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * 96d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * @param device The remote device. 97d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * @return The name, or if unavailable, the address. 98d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly */ 99d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly public String getName(BluetoothDevice device) { 100d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly CachedBluetoothDevice cachedDevice = findDevice(device); 101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice != null) { 102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return cachedDevice.getName(); 103d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 104d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 1052036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie String name = device.getAliasName(); 106436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (name != null) { 107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return name; 108d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 109d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 110436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return device.getAddress(); 111d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 112d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 113d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly public synchronized void onScanningStateChanged(boolean started) { 114d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if (!started) return; 115d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 116d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly // If starting a new scan, clear old visibility 117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Iterate in reverse order since devices may be removed. 118d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly for (int i = mCachedDevices.size() - 1; i >= 0; i--) { 119d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); 120d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly cachedDevice.setVisible(false); 121d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 122d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 123d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly 124d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly public synchronized void onBtClassChanged(BluetoothDevice device) { 125d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly CachedBluetoothDevice cachedDevice = findDevice(device); 126d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if (cachedDevice != null) { 127d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly cachedDevice.refreshBtClass(); 128d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 129d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly } 1302aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 1312aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan public synchronized void onUuidChanged(BluetoothDevice device) { 1322aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan CachedBluetoothDevice cachedDevice = findDevice(device); 1332aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (cachedDevice != null) { 1342aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan cachedDevice.onUuidChanged(); 1352aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 1362aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 137b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 138737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy public synchronized void onBluetoothStateChanged(int bluetoothState) { 139737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy // When Bluetooth is turning off, we need to clear the non-bonded devices 140737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy // Otherwise, they end up showing up on the next BT enable 141737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) { 142737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy for (int i = mCachedDevices.size() - 1; i >= 0; i--) { 143737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); 1442582e6ca94e6cbb80a8bf2b3abcb83da5f7d3a09Ravi Nagarajan if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) { 145737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy cachedDevice.setVisible(false); 146737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy mCachedDevices.remove(i); 1477951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } else { 1487951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta // For bonded devices, we need to clear the connection status so that 1497951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta // when BT is enabled next time, device connection status shall be retrieved 1507951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta // by making a binder call. 1517951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta cachedDevice.clearProfileConnectionState(); 152737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy } 153737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy } 154737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy } 155737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy } 156b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private void log(String msg) { 157b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie if (DEBUG) { 158b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie Log.d(TAG, msg); 159b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 160b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 161d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly} 162