CachedBluetoothDevice.java revision 2036ebd8896bbabbbe04db34c9e7d8a1be6fe32a
1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/* 2afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License. 6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at 7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and 14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License. 15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings.bluetooth; 18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 192aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chanimport android.bluetooth.BluetoothClass; 20e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 21436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothProfile; 22e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chanimport android.os.ParcelUuid; 232aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chanimport android.os.SystemClock; 24afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.text.TextUtils; 25afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.util.Log; 26afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 27afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.ArrayList; 28436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collection; 29436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collections; 3050e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganeshimport java.util.HashMap; 31afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.List; 32afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 33afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/** 34d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * CachedBluetoothDevice represents a remote Bluetooth device. It contains 35afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * attributes of the device (such as the address, name, RSSI, etc.) and 36afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * functionality that can be performed on the device (connect, pair, disconnect, 37afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * etc.). 38afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 39436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { 40d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly private static final String TAG = "CachedBluetoothDevice"; 41436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static final boolean DEBUG = Utils.V; 42afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final LocalBluetoothAdapter mLocalAdapter; 44436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final LocalBluetoothProfileManager mProfileManager; 45d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly private final BluetoothDevice mDevice; 46afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private String mName; 47afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private short mRssi; 4816cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly private BluetoothClass mBtClass; 4950e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh private HashMap<LocalBluetoothProfile, Integer> mProfileConnectionState; 50afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 51436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final List<LocalBluetoothProfile> mProfiles = 52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<LocalBluetoothProfile>(); 53afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 54c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // List of profiles that were previously in mProfiles, but have been removed 55c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby private final List<LocalBluetoothProfile> mRemovedProfiles = 56c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby new ArrayList<LocalBluetoothProfile>(); 57c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 58c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // Device supports PANU but not NAP: remove PanProfile after device disconnects from NAP 59c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby private boolean mLocalNapRoleConnected; 60c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 61afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean mVisible; 62afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 63436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Collection<Callback> mCallbacks = new ArrayList<Callback>(); 64afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 65afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 66afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * When we connect to multiple profiles, we only want to display a single 67afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * error even if they all fail. This tracks that state. 68afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 69afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean mIsConnectingErrorPossible; 70afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 712aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /** 72eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan * Last time a bt profile auto-connect was attempted. 73eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan * If an ACTION_UUID intent comes in within 742aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * MAX_UUID_DELAY_FOR_AUTO_CONNECT milliseconds, we will try auto-connect 752aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * again with the new UUIDs 762aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 77eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan private long mConnectAttempted; 782aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 79eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan // See mConnectAttempted 802aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000; 812aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 82dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby /** Auto-connect after pairing only if locally initiated. */ 83dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby private boolean mConnectAfterPairing; 8484905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh 85e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project /** 86f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * Describes the current device and profile for logging. 8784905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh * 88f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * @param profile Profile to describe 89f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * @return Description of the device and profile 90e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project */ 91436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private String describe(LocalBluetoothProfile profile) { 92f907e0bb891eca4d498871a1cc862117a462a076Adam Powell StringBuilder sb = new StringBuilder(); 93e79f990490de49b39097433707c2bae6d8238330Jake Hamby sb.append("Address:").append(mDevice); 94f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (profile != null) { 95436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby sb.append(" Profile:").append(profile); 96097ed6c671ed733c0967acc32e017020ede4575bMichael Chan } 97e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 98f907e0bb891eca4d498871a1cc862117a462a076Adam Powell return sb.toString(); 99f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 10084905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh 101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) { 102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "onProfileStateChanged: profile " + profile + 104f907e0bb891eca4d498871a1cc862117a462a076Adam Powell " newProfileState " + newProfileState); 1056c97742c88303c65e68fe08257a7ccf841f03866Michael Chan } 106e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 10750e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.put(profile, newProfileState); 108436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (newProfileState == BluetoothProfile.STATE_CONNECTED) { 109f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (!mProfiles.contains(profile)) { 110c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mRemovedProfiles.remove(profile); 111f907e0bb891eca4d498871a1cc862117a462a076Adam Powell mProfiles.add(profile); 112c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby if (profile instanceof PanProfile && 113c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby ((PanProfile) profile).isLocalRoleNap(mDevice)) { 114c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // Device doesn't support NAP, so remove PanProfile on disconnect 115c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mLocalNapRoleConnected = true; 116c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 117e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 118c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (mLocalNapRoleConnected && profile instanceof PanProfile && 119c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby ((PanProfile) profile).isLocalRoleNap(mDevice) && 120c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby newProfileState == BluetoothProfile.STATE_DISCONNECTED) { 121c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby Log.d(TAG, "Removing PanProfile from device after NAP disconnect"); 122c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mProfiles.remove(profile); 123c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mRemovedProfiles.add(profile); 124c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mLocalNapRoleConnected = false; 125e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 126e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 127e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 128436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice(LocalBluetoothAdapter adapter, 129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothProfileManager profileManager, 130436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = adapter; 132436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager = profileManager; 133d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mDevice = device; 13450e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState = new HashMap<LocalBluetoothProfile, Integer>(); 135afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fillData(); 136afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 137afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void disconnect() { 139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 140afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project disconnect(profile); 141afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 142afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 143afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 144436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void disconnect(LocalBluetoothProfile profile) { 145436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.disconnect(mDevice)) { 146436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 147d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh Log.d(TAG, "Command sent successfully:DISCONNECT " + describe(profile)); 148f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 149afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 150afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 151afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 152436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void connect(boolean connectAllProfiles) { 153436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 154afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return; 155afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 156afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 157eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mConnectAttempted = SystemClock.elapsedRealtime(); 1584bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connectWithoutResettingTimer(connectAllProfiles); 159eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 160eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan 161436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onBondingDockConnect() { 162582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby // Attempt to connect if UUIDs are available. Otherwise, 163582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby // we will connect when the ACTION_UUID intent arrives. 1644bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connect(false); 165b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh } 166b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh 16739ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby private void connectWithoutResettingTimer(boolean connectAllProfiles) { 168a0d39a39c2f53ebe858685c75c756b51dfac49daJake Hamby // Try to initialize the profiles if they were not. 169436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mProfiles.isEmpty()) { 1702aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (!updateProfiles()) { 1712aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan // If UUIDs are not available yet, connect will be happen 1722aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan // upon arrival of the ACTION_UUID intent. 173eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) Log.d(TAG, "No profiles. Maybe we will connect later"); 1742aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan return; 1752aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 1762aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 1772aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 178afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 179afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 180afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 181eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan int preferredProfiles = 0; 182436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 18339ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) { 184436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.isPreferred(mDevice)) { 185b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan ++preferredProfiles; 186436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 187b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan } 188afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 189afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 190eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles); 191afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 192eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (preferredProfiles == 0) { 193436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectAutoConnectableProfiles(); 194afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 195afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 196afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 197436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void connectAutoConnectableProfiles() { 198436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 199436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 200436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 201afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 202afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 203afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 204436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 20539ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (profile.isAutoConnectable()) { 206436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profile.setPreferred(mDevice, true); 207436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 208b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan } 209afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 210afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 211afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 212436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 213436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Connect this device to the specified profile. 214436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 215436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param profile the profile to use with the remote device 216436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 217436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void connectProfile(LocalBluetoothProfile profile) { 218eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mConnectAttempted = SystemClock.elapsedRealtime(); 219afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 220afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 221436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 222afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 223afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 224436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void connectInt(LocalBluetoothProfile profile) { 225436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 226436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 227436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 228436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.connect(mDevice)) { 229436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 230d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile)); 231afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 232436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 233afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 234436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName); 235afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 236afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 237afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean ensurePaired() { 23816cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly if (getBondState() == BluetoothDevice.BOND_NONE) { 239436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby startPairing(); 240afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return false; 241afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } else { 242afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 243afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 244afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 245afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 246436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean startPairing() { 247afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Pairing is unreliable while scanning, so cancel discovery 248436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mLocalAdapter.isDiscovering()) { 249436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter.cancelDiscovery(); 250afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 251afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 252d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if (!mDevice.createBond()) { 253436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 254afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 255dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby 256dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = true; // auto-connect after pairing 257436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 258afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 259afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 260ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby /** 261ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby * Return true if user initiated pairing on this device. The message text is 262ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby * slightly different for local vs. remote initiated pairing dialogs. 263ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby */ 264ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby boolean isUserInitiatedPairing() { 265ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby return mConnectAfterPairing; 266ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby } 267ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby 268436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unpair() { 26996b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan disconnect(); 270e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 27196b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan int state = getBondState(); 272afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 27396b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan if (state == BluetoothDevice.BOND_BONDING) { 274d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mDevice.cancelBondProcess(); 27596b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan } 27696b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan 27796b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan if (state != BluetoothDevice.BOND_NONE) { 278436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby final BluetoothDevice dev = mDevice; 279f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (dev != null) { 280f907e0bb891eca4d498871a1cc862117a462a076Adam Powell final boolean successful = dev.removeBond(); 281f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (successful) { 282436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 283f907e0bb891eca4d498871a1cc862117a462a076Adam Powell Log.d(TAG, "Command sent successfully:REMOVE_BOND " + describe(null)); 284f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 285436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if (Utils.V) { 286f907e0bb891eca4d498871a1cc862117a462a076Adam Powell Log.v(TAG, "Framework rejected command immediately:REMOVE_BOND " + 287f907e0bb891eca4d498871a1cc862117a462a076Adam Powell describe(null)); 288f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 289f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 290afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 291afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 292afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 29350e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int getProfileConnectionState(LocalBluetoothProfile profile) { 29450e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh if (mProfileConnectionState == null || 29550e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.get(profile) == null) { 29650e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh // If cache is empty make the binder call to get the state 29750e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int state = profile.getConnectionStatus(mDevice); 29850e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.put(profile, state); 29950e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh } 30050e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh return mProfileConnectionState.get(profile); 30150e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh } 30250e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh 303436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // TODO: do any of these need to run async on a background thread? 304afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fillData() { 305afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchName(); 306afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchBtClass(); 3072aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan updateProfiles(); 308afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 309afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mVisible = false; 310afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 311afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 312afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 313afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 314436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice getDevice() { 315d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice; 316afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 317afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 318436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby String getName() { 319afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return mName; 320afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 321afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 322436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setName(String name) { 323d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh if (!mName.equals(name)) { 324d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh if (TextUtils.isEmpty(name)) { 325c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby // TODO: use friendly name for unknown device (bug 1181856) 326d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mName = mDevice.getAddress(); 327d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } else { 328d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh mName = name; 3292036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie mDevice.setAlias(name); 330d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 331d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh dispatchAttributesChanged(); 332d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 333d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 334d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh 335436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refreshName() { 336afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchName(); 337afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 338afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 339afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 340afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fetchName() { 3412036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie mName = mDevice.getAliasName(); 342afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 343afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (TextUtils.isEmpty(mName)) { 344d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mName = mDevice.getAddress(); 345436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) Log.d(TAG, "Device has no name (yet), use address: " + mName); 346afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 347afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 348afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 349436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refresh() { 350afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 351afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 352afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 353436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isVisible() { 354afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return mVisible; 355afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 356afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 357afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project void setVisible(boolean visible) { 358afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (mVisible != visible) { 359afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mVisible = visible; 360afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 361afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 362afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 363afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 364436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int getBondState() { 365d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.getBondState(); 366afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 367afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 368afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project void setRssi(short rssi) { 369afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (mRssi != rssi) { 370afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mRssi = rssi; 371afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 372afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 373afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 374afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 375afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 376afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Checks whether we are connected to this device (any profile counts). 377afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 378afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * @return Whether it is connected. 379afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 380436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isConnected() { 381436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 38250e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 383436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTED) { 384afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 385afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 386afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 387afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 388afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return false; 389afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 390afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 391436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isConnectedProfile(LocalBluetoothProfile profile) { 39250e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 393436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return status == BluetoothProfile.STATE_CONNECTED; 394c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby 395c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby } 396c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby 397436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isBusy() { 398436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 39950e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 400436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTING 401436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby || status == BluetoothProfile.STATE_DISCONNECTING) { 402afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 403afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 404afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 405436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return getBondState() == BluetoothDevice.BOND_BONDING; 406cde015b3d424b0d83030f11432ad0a0589014bd5Jake Hamby } 407cde015b3d424b0d83030f11432ad0a0589014bd5Jake Hamby 408afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 409afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Fetches a new value for the cached BT class. 410afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 411afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fetchBtClass() { 412d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mBtClass = mDevice.getBluetoothClass(); 4132aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 4142aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4152aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private boolean updateProfiles() { 4162aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan ParcelUuid[] uuids = mDevice.getUuids(); 4172aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (uuids == null) return false; 4182aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 419436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ParcelUuid[] localUuids = mLocalAdapter.getUuids(); 420498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh if (localUuids == null) return false; 421498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh 422c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mProfileManager.updateProfiles(uuids, localUuids, mProfiles, mRemovedProfiles); 4232aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4242aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (DEBUG) { 4252036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie Log.e(TAG, "updating profiles for " + mDevice.getAliasName()); 4262aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan BluetoothClass bluetoothClass = mDevice.getBluetoothClass(); 4272aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4288c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString()); 4298c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh Log.v(TAG, "UUID:"); 430436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (ParcelUuid uuid : uuids) { 431436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.v(TAG, " " + uuid); 4322aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 433b20dd917e2d29045225985baa980a2a8e22e10fcNick Pelly } 4342aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan return true; 435afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 436afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 437afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 438afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Refreshes the UI for the BT class, including fetching the latest value 439afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * for the class. 440afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 441436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refreshBtClass() { 442afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchBtClass(); 443afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 444afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 445afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 4462aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /** 4472aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * Refreshes the UI when framework alerts us of a UUID change. 4482aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 449436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onUuidChanged() { 4502aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan updateProfiles(); 4512aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 452eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) { 453eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan Log.e(TAG, "onUuidChanged: Time since last connect" 454eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan + (SystemClock.elapsedRealtime() - mConnectAttempted)); 455eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 4562aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4572aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /* 4582aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * If a connect was attempted earlier without any UUID, we will do the 4592aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * connect now. 4602aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 461436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!mProfiles.isEmpty() 462eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan && (mConnectAttempted + MAX_UUID_DELAY_FOR_AUTO_CONNECT) > SystemClock 4632aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan .elapsedRealtime()) { 46439ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby connectWithoutResettingTimer(false); 4652aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 4662aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan dispatchAttributesChanged(); 4672aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 4682aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 469436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onBondingStateChanged(int bondState) { 470eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (bondState == BluetoothDevice.BOND_NONE) { 471eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mProfiles.clear(); 472dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = false; // cancel auto-connect 473eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 4741308453b16c2ca85a456bd4bb7f3c71c916bd83eMichael Chan 475eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan refresh(); 476dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby 477dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby if (bondState == BluetoothDevice.BOND_BONDED) { 478dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby if (mDevice.isBluetoothDock()) { 479dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby onBondingDockConnect(); 480dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } else if (mConnectAfterPairing) { 4814bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connect(false); 482dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } 483dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = false; 484dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } 485eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 486eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan 487436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setBtClass(BluetoothClass btClass) { 48816cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly if (btClass != null && mBtClass != btClass) { 489d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh mBtClass = btClass; 490d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh dispatchAttributesChanged(); 491d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 492d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 493d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh 494436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothClass getBtClass() { 495436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mBtClass; 496afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 497afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 498436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> getProfiles() { 499436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return Collections.unmodifiableList(mProfiles); 50048e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani } 501afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 502436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> getConnectableProfiles() { 503436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> connectableProfiles = 504436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<LocalBluetoothProfile>(); 505436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 50639ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (profile.isConnectable()) { 507e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan connectableProfiles.add(profile); 508e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 509e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 510e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan return connectableProfiles; 511e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 512e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan 513c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby List<LocalBluetoothProfile> getRemovedProfiles() { 514c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby return mRemovedProfiles; 515c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 516c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 517436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void registerCallback(Callback callback) { 518afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 519afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mCallbacks.add(callback); 520afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 521afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 522afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 523436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unregisterCallback(Callback callback) { 524afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 525afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mCallbacks.remove(callback); 526afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 527afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 528afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 529afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void dispatchAttributesChanged() { 530afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 531afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project for (Callback callback : mCallbacks) { 532c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby callback.onDeviceAttributesChanged(); 533afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 534afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 535afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 536afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 537afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 538afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public String toString() { 539d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.toString(); 540afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 541afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 542afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 543afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public boolean equals(Object o) { 544d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if ((o == null) || !(o instanceof CachedBluetoothDevice)) { 545436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 546afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 547d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.equals(((CachedBluetoothDevice) o).mDevice); 548afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 549afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 550afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 551afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public int hashCode() { 552d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.getAddress().hashCode(); 553afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 554afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 555436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // This comparison uses non-final fields so the sort order may change 556436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // when device attributes change (such as bonding state). Settings 557436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // will completely refresh the device list when this happens. 558d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly public int compareTo(CachedBluetoothDevice another) { 559afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Connected above not connected 560436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int comparison = (another.isConnected() ? 1 : 0) - (isConnected() ? 1 : 0); 561afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 562afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 563afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Paired above not paired 564afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = (another.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0) - 565afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0); 566afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 567afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 568afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Visible above not visible 569afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0); 570afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 571afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 572afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Stronger signal above weaker signal 573afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = another.mRssi - mRssi; 574afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 575afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 576afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Fallback on name 577436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mName.compareTo(another.mName); 578afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 579afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 580afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public interface Callback { 581c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby void onDeviceAttributesChanged(); 582afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 583afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project} 584