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; 22b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xieimport android.content.Context; 23b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xieimport android.content.SharedPreferences; 24e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chanimport android.os.ParcelUuid; 252aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chanimport android.os.SystemClock; 26afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.text.TextUtils; 27afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.util.Log; 282ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balajiimport android.bluetooth.BluetoothAdapter; 29afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 30afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.ArrayList; 31436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collection; 32436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collections; 3350e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganeshimport java.util.HashMap; 34afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.List; 35afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 36afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/** 37d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * CachedBluetoothDevice represents a remote Bluetooth device. It contains 38afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * attributes of the device (such as the address, name, RSSI, etc.) and 39afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * functionality that can be performed on the device (connect, pair, disconnect, 40afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * etc.). 41afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 42436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { 43d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly private static final String TAG = "CachedBluetoothDevice"; 44436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static final boolean DEBUG = Utils.V; 45afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 46b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private final Context mContext; 47436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final LocalBluetoothAdapter mLocalAdapter; 48436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final LocalBluetoothProfileManager mProfileManager; 49d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly private final BluetoothDevice mDevice; 50afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private String mName; 51afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private short mRssi; 5216cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly private BluetoothClass mBtClass; 5350e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh private HashMap<LocalBluetoothProfile, Integer> mProfileConnectionState; 54afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 55436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final List<LocalBluetoothProfile> mProfiles = 56436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<LocalBluetoothProfile>(); 57afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 58c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // List of profiles that were previously in mProfiles, but have been removed 59c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby private final List<LocalBluetoothProfile> mRemovedProfiles = 60c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby new ArrayList<LocalBluetoothProfile>(); 61c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 62c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // Device supports PANU but not NAP: remove PanProfile after device disconnects from NAP 63c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby private boolean mLocalNapRoleConnected; 64c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 65afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean mVisible; 66afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 67b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private int mPhonebookPermissionChoice; 68b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 695b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie private int mMessagePermissionChoice; 705b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 71ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee private int mMessageRejectionCount; 725b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 73436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Collection<Callback> mCallbacks = new ArrayList<Callback>(); 74afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 755b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie // Following constants indicate the user's choices of Phone book/message access settings 76b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User hasn't made any choice or settings app has wiped out the memory 77361d870e5415f8642cb106b4329d194673b4dd02PauloftheWest public final static int ACCESS_UNKNOWN = 0; 78b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User has accepted the connection and let Settings app remember the decision 79361d870e5415f8642cb106b4329d194673b4dd02PauloftheWest public final static int ACCESS_ALLOWED = 1; 80b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User has rejected the connection and let Settings app remember the decision 81361d870e5415f8642cb106b4329d194673b4dd02PauloftheWest public final static int ACCESS_REJECTED = 2; 825b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 83ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee // How many times user should reject the connection to make the choice persist. 84ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee private final static int MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST = 2; 85b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 86ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee private final static String MESSAGE_REJECTION_COUNT_PREFS_NAME = "bluetooth_message_reject"; 87b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 88afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 89afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * When we connect to multiple profiles, we only want to display a single 90afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * error even if they all fail. This tracks that state. 91afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 92afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean mIsConnectingErrorPossible; 93afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 942aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /** 95eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan * Last time a bt profile auto-connect was attempted. 96eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan * If an ACTION_UUID intent comes in within 972aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * MAX_UUID_DELAY_FOR_AUTO_CONNECT milliseconds, we will try auto-connect 982aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * again with the new UUIDs 992aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 100eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan private long mConnectAttempted; 1012aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 102eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan // See mConnectAttempted 1032aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000; 1042aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 105dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby /** Auto-connect after pairing only if locally initiated. */ 106dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby private boolean mConnectAfterPairing; 10784905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh 108e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project /** 109f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * Describes the current device and profile for logging. 11084905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh * 111f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * @param profile Profile to describe 112f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * @return Description of the device and profile 113e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project */ 114436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private String describe(LocalBluetoothProfile profile) { 115f907e0bb891eca4d498871a1cc862117a462a076Adam Powell StringBuilder sb = new StringBuilder(); 116e79f990490de49b39097433707c2bae6d8238330Jake Hamby sb.append("Address:").append(mDevice); 117f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (profile != null) { 118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby sb.append(" Profile:").append(profile); 119097ed6c671ed733c0967acc32e017020ede4575bMichael Chan } 120e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 121f907e0bb891eca4d498871a1cc862117a462a076Adam Powell return sb.toString(); 122f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 12384905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh 124436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) { 125436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 126436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "onProfileStateChanged: profile " + profile + 127f907e0bb891eca4d498871a1cc862117a462a076Adam Powell " newProfileState " + newProfileState); 1286c97742c88303c65e68fe08257a7ccf841f03866Michael Chan } 1297951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF) 1307951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta { 1317951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta if (Utils.D) Log.d(TAG, " BT Turninig Off...Profile conn state change ignored..."); 1327951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta return; 1337951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } 13450e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.put(profile, newProfileState); 135436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (newProfileState == BluetoothProfile.STATE_CONNECTED) { 13600656b8e46e187e5fa63b8a80cd4f42367c1c924PauloftheWest if (profile instanceof MapProfile) { 13700656b8e46e187e5fa63b8a80cd4f42367c1c924PauloftheWest profile.setPreferred(mDevice, true); 13800656b8e46e187e5fa63b8a80cd4f42367c1c924PauloftheWest } else if (!mProfiles.contains(profile)) { 139c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mRemovedProfiles.remove(profile); 140f907e0bb891eca4d498871a1cc862117a462a076Adam Powell mProfiles.add(profile); 141c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby if (profile instanceof PanProfile && 142c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby ((PanProfile) profile).isLocalRoleNap(mDevice)) { 143c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // Device doesn't support NAP, so remove PanProfile on disconnect 144c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mLocalNapRoleConnected = true; 145c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 146e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 1475d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz } else if (profile instanceof MapProfile && 1485d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz newProfileState == BluetoothProfile.STATE_DISCONNECTED) { 1495d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz profile.setPreferred(mDevice, false); 150c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (mLocalNapRoleConnected && profile instanceof PanProfile && 151c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby ((PanProfile) profile).isLocalRoleNap(mDevice) && 152c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby newProfileState == BluetoothProfile.STATE_DISCONNECTED) { 153c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby Log.d(TAG, "Removing PanProfile from device after NAP disconnect"); 154c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mProfiles.remove(profile); 155c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mRemovedProfiles.add(profile); 156c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mLocalNapRoleConnected = false; 157e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 158e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 159e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 160b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie CachedBluetoothDevice(Context context, 161b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie LocalBluetoothAdapter adapter, 162b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie LocalBluetoothProfileManager profileManager, 163b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie BluetoothDevice device) { 164b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mContext = context; 165436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = adapter; 166436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager = profileManager; 167d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mDevice = device; 16850e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState = new HashMap<LocalBluetoothProfile, Integer>(); 169afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fillData(); 170afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 171afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 172436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void disconnect() { 173436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 174afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project disconnect(profile); 175afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 1760654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta // Disconnect PBAP server in case its connected 1770654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta // This is to ensure all the profiles are disconnected as some CK/Hs do not 1780654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta // disconnect PBAP connection when HF connection is brought down 1790654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta PbapServerProfile PbapProfile = mProfileManager.getPbapProfile(); 1800654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta if (PbapProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED) 1810654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta { 1820654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta PbapProfile.disconnect(mDevice); 1830654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta } 184afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 185afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 186436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void disconnect(LocalBluetoothProfile profile) { 187436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.disconnect(mDevice)) { 188436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 189d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh Log.d(TAG, "Command sent successfully:DISCONNECT " + describe(profile)); 190f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 191afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 192afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 193afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 194436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void connect(boolean connectAllProfiles) { 195436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 196afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return; 197afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 198afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 199eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mConnectAttempted = SystemClock.elapsedRealtime(); 2004bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connectWithoutResettingTimer(connectAllProfiles); 201eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 202eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan 203436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onBondingDockConnect() { 204582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby // Attempt to connect if UUIDs are available. Otherwise, 205582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby // we will connect when the ACTION_UUID intent arrives. 2064bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connect(false); 207b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh } 208b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh 20939ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby private void connectWithoutResettingTimer(boolean connectAllProfiles) { 210a0d39a39c2f53ebe858685c75c756b51dfac49daJake Hamby // Try to initialize the profiles if they were not. 211436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mProfiles.isEmpty()) { 2126e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // if mProfiles is empty, then do not invoke updateProfiles. This causes a race 2136e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // condition with carkits during pairing, wherein RemoteDevice.UUIDs have been updated 2146e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // from bluetooth stack but ACTION.uuid is not sent yet. 2156e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // Eventually ACTION.uuid will be received which shall trigger the connection of the 2166e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // various profiles 2176e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // If UUIDs are not available yet, connect will be happen 2186e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // upon arrival of the ACTION_UUID intent. 2196e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy Log.d(TAG, "No profiles. Maybe we will connect later"); 2206e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy return; 2212aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 2222aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 223afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 224afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 225afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 226eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan int preferredProfiles = 0; 227436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 22839ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) { 229436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.isPreferred(mDevice)) { 230b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan ++preferredProfiles; 231436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 232b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan } 233afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 234afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 235eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles); 236afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 237eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (preferredProfiles == 0) { 238436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectAutoConnectableProfiles(); 239afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 240afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 241afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 242436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void connectAutoConnectableProfiles() { 243436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 244436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 245436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 246afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 247afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 248afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 249436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 25039ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (profile.isAutoConnectable()) { 251436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profile.setPreferred(mDevice, true); 252436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 253b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan } 254afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 255afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 256afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 257436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 258436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Connect this device to the specified profile. 259436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 260436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param profile the profile to use with the remote device 261436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 262436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void connectProfile(LocalBluetoothProfile profile) { 263eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mConnectAttempted = SystemClock.elapsedRealtime(); 264afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 265afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 266436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 267f457e613d5d91322e0c967fb801899d55e3db9e5Syed Ibrahim M // Refresh the UI based on profile.connect() call 268f457e613d5d91322e0c967fb801899d55e3db9e5Syed Ibrahim M refresh(); 269afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 270afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 2712ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji synchronized void connectInt(LocalBluetoothProfile profile) { 272436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 273436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 274436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 275436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.connect(mDevice)) { 276436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 277d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile)); 278afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 279436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 280afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 281436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName); 282afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 283afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 284afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean ensurePaired() { 28516cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly if (getBondState() == BluetoothDevice.BOND_NONE) { 286436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby startPairing(); 287afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return false; 288afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } else { 289afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 290afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 291afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 292afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 293436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean startPairing() { 294afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Pairing is unreliable while scanning, so cancel discovery 295436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mLocalAdapter.isDiscovering()) { 296436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter.cancelDiscovery(); 297afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 298afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 299d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if (!mDevice.createBond()) { 300436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 301afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 302dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby 303dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = true; // auto-connect after pairing 304436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 305afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 306afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 307ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby /** 308ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby * Return true if user initiated pairing on this device. The message text is 309ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby * slightly different for local vs. remote initiated pairing dialogs. 310ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby */ 311ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby boolean isUserInitiatedPairing() { 312ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby return mConnectAfterPairing; 313ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby } 314ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby 315436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unpair() { 31696b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan int state = getBondState(); 317afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 31896b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan if (state == BluetoothDevice.BOND_BONDING) { 319d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mDevice.cancelBondProcess(); 32096b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan } 32196b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan 32296b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan if (state != BluetoothDevice.BOND_NONE) { 323436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby final BluetoothDevice dev = mDevice; 324f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (dev != null) { 325f907e0bb891eca4d498871a1cc862117a462a076Adam Powell final boolean successful = dev.removeBond(); 326f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (successful) { 327436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 328f907e0bb891eca4d498871a1cc862117a462a076Adam Powell Log.d(TAG, "Command sent successfully:REMOVE_BOND " + describe(null)); 329f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 330436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if (Utils.V) { 331f907e0bb891eca4d498871a1cc862117a462a076Adam Powell Log.v(TAG, "Framework rejected command immediately:REMOVE_BOND " + 332f907e0bb891eca4d498871a1cc862117a462a076Adam Powell describe(null)); 333f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 334f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 335afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 336afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 337afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 33850e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int getProfileConnectionState(LocalBluetoothProfile profile) { 33950e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh if (mProfileConnectionState == null || 34050e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.get(profile) == null) { 34150e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh // If cache is empty make the binder call to get the state 34250e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int state = profile.getConnectionStatus(mDevice); 34350e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.put(profile, state); 34450e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh } 34550e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh return mProfileConnectionState.get(profile); 34650e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh } 34750e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh 3487951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta public void clearProfileConnectionState () 3497951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta { 3507951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta if (Utils.D) { 3517951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta Log.d(TAG," Clearing all connection state for dev:" + mDevice.getName()); 3527951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } 3537951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta for (LocalBluetoothProfile profile :getProfiles()) { 3547951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta mProfileConnectionState.put(profile, BluetoothProfile.STATE_DISCONNECTED); 3557951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } 3567951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } 3577951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta 358436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // TODO: do any of these need to run async on a background thread? 359afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fillData() { 360afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchName(); 361afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchBtClass(); 3622aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan updateProfiles(); 363ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee migratePhonebookPermissionChoice(); 364ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee migrateMessagePermissionChoice(); 365ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee fetchMessageRejectionCount(); 366afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 367afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mVisible = false; 368afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 369afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 370afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 371436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice getDevice() { 372d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice; 373afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 374afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 375436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby String getName() { 376afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return mName; 377afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 378afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 3792f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie /** 3802f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie * Populate name from BluetoothDevice.ACTION_FOUND intent 3812f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie */ 3822f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie void setNewName(String name) { 3832f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie if (mName == null) { 3842f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie mName = name; 3852f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie if (mName == null || TextUtils.isEmpty(mName)) { 386d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mName = mDevice.getAddress(); 387d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 388d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh dispatchAttributesChanged(); 389d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 390d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 391d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh 3922f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie /** 3932f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie * user changes the device name 3942f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie */ 3952f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie void setName(String name) { 3962f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie if (!mName.equals(name)) { 3972f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie mName = name; 3982f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie mDevice.setAlias(name); 3992f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie dispatchAttributesChanged(); 4002f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie } 4012f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie } 4022f837509dd3b9341339d30e64c43e7aa857212abMatthew Xie 403436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refreshName() { 404afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchName(); 405afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 406afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 407afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 408afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fetchName() { 4092036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie mName = mDevice.getAliasName(); 410afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 411afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (TextUtils.isEmpty(mName)) { 412d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mName = mDevice.getAddress(); 413436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) Log.d(TAG, "Device has no name (yet), use address: " + mName); 414afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 415afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 416afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 417436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refresh() { 418afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 419afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 420afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 421436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isVisible() { 422afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return mVisible; 423afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 424afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 425afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project void setVisible(boolean visible) { 426afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (mVisible != visible) { 427afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mVisible = visible; 428afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 429afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 430afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 431afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 432436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int getBondState() { 433d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.getBondState(); 434afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 435afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 436afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project void setRssi(short rssi) { 437afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (mRssi != rssi) { 438afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mRssi = rssi; 439afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 440afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 441afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 442afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 443afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 444afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Checks whether we are connected to this device (any profile counts). 445afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 446afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * @return Whether it is connected. 447afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 448436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isConnected() { 449436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 45050e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 451436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTED) { 452afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 453afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 454afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 455afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 456afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return false; 457afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 458afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 459436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isConnectedProfile(LocalBluetoothProfile profile) { 46050e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 461436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return status == BluetoothProfile.STATE_CONNECTED; 462c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby 463c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby } 464c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby 465436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isBusy() { 466436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 46750e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 468436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTING 469436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby || status == BluetoothProfile.STATE_DISCONNECTING) { 470afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 471afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 472afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 473436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return getBondState() == BluetoothDevice.BOND_BONDING; 474cde015b3d424b0d83030f11432ad0a0589014bd5Jake Hamby } 475cde015b3d424b0d83030f11432ad0a0589014bd5Jake Hamby 476afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 477afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Fetches a new value for the cached BT class. 478afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 479afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fetchBtClass() { 480d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mBtClass = mDevice.getBluetoothClass(); 4812aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 4822aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4832aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private boolean updateProfiles() { 4842aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan ParcelUuid[] uuids = mDevice.getUuids(); 4852aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (uuids == null) return false; 4862aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 487436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ParcelUuid[] localUuids = mLocalAdapter.getUuids(); 488498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh if (localUuids == null) return false; 489498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh 4901b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu mProfileManager.updateProfiles(uuids, localUuids, mProfiles, mRemovedProfiles, 4911b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu mLocalNapRoleConnected, mDevice); 4922aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4932aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (DEBUG) { 4942036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie Log.e(TAG, "updating profiles for " + mDevice.getAliasName()); 4952aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan BluetoothClass bluetoothClass = mDevice.getBluetoothClass(); 4962aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4978c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString()); 4988c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh Log.v(TAG, "UUID:"); 499436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (ParcelUuid uuid : uuids) { 500436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.v(TAG, " " + uuid); 5012aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 502b20dd917e2d29045225985baa980a2a8e22e10fcNick Pelly } 5032aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan return true; 504afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 505afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 506afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 507afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Refreshes the UI for the BT class, including fetching the latest value 508afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * for the class. 509afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 510436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refreshBtClass() { 511afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchBtClass(); 512afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 513afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 514afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 5152aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /** 5162aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * Refreshes the UI when framework alerts us of a UUID change. 5172aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 518436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onUuidChanged() { 5192aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan updateProfiles(); 5202aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 521eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) { 522eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan Log.e(TAG, "onUuidChanged: Time since last connect" 523eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan + (SystemClock.elapsedRealtime() - mConnectAttempted)); 524eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 5252aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 5262aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /* 5272aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * If a connect was attempted earlier without any UUID, we will do the 5282aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * connect now. 5292aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 530436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!mProfiles.isEmpty() 531eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan && (mConnectAttempted + MAX_UUID_DELAY_FOR_AUTO_CONNECT) > SystemClock 5322aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan .elapsedRealtime()) { 53339ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby connectWithoutResettingTimer(false); 5342aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 5352aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan dispatchAttributesChanged(); 5362aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 5372aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 538436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onBondingStateChanged(int bondState) { 539eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (bondState == BluetoothDevice.BOND_NONE) { 540eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mProfiles.clear(); 541dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = false; // cancel auto-connect 54258938ba0d6cddb53a8a76d2e0a2217cf49c92395PauloftheWest setPhonebookPermissionChoice(ACCESS_UNKNOWN); 5435b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie setMessagePermissionChoice(ACCESS_UNKNOWN); 544ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mMessageRejectionCount = 0; 545ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee saveMessageRejectionCount(); 546eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 5471308453b16c2ca85a456bd4bb7f3c71c916bd83eMichael Chan 548eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan refresh(); 549dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby 550dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby if (bondState == BluetoothDevice.BOND_BONDED) { 551dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby if (mDevice.isBluetoothDock()) { 552dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby onBondingDockConnect(); 553dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } else if (mConnectAfterPairing) { 5544bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connect(false); 555dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } 556dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = false; 557dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } 558eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 559eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan 560436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setBtClass(BluetoothClass btClass) { 56116cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly if (btClass != null && mBtClass != btClass) { 562d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh mBtClass = btClass; 563d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh dispatchAttributesChanged(); 564d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 565d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 566d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh 567436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothClass getBtClass() { 568436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mBtClass; 569afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 570afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 571436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> getProfiles() { 572436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return Collections.unmodifiableList(mProfiles); 57348e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani } 574afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 575436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> getConnectableProfiles() { 576436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> connectableProfiles = 577436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<LocalBluetoothProfile>(); 578436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 57939ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (profile.isConnectable()) { 580e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan connectableProfiles.add(profile); 581e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 582e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 583e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan return connectableProfiles; 584e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 585e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan 586c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby List<LocalBluetoothProfile> getRemovedProfiles() { 587c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby return mRemovedProfiles; 588c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 589c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 590436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void registerCallback(Callback callback) { 591afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 592afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mCallbacks.add(callback); 593afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 594afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 595afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 596436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unregisterCallback(Callback callback) { 597afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 598afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mCallbacks.remove(callback); 599afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 600afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 601afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 602afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void dispatchAttributesChanged() { 603afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 604afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project for (Callback callback : mCallbacks) { 605c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby callback.onDeviceAttributesChanged(); 606afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 607afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 608afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 609afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 610afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 611afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public String toString() { 612d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.toString(); 613afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 614afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 615afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 616afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public boolean equals(Object o) { 617d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if ((o == null) || !(o instanceof CachedBluetoothDevice)) { 618436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 619afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 620d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.equals(((CachedBluetoothDevice) o).mDevice); 621afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 622afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 623afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 624afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public int hashCode() { 625d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.getAddress().hashCode(); 626afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 627afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 628436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // This comparison uses non-final fields so the sort order may change 629436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // when device attributes change (such as bonding state). Settings 630436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // will completely refresh the device list when this happens. 631d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly public int compareTo(CachedBluetoothDevice another) { 632afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Connected above not connected 633436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int comparison = (another.isConnected() ? 1 : 0) - (isConnected() ? 1 : 0); 634afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 635afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 636afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Paired above not paired 637afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = (another.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0) - 638afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0); 639afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 640afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 641afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Visible above not visible 642afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0); 643afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 644afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 645afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Stronger signal above weaker signal 646afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = another.mRssi - mRssi; 647afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 648afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 649afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Fallback on name 650436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mName.compareTo(another.mName); 651afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 652afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 653afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public interface Callback { 654c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby void onDeviceAttributesChanged(); 655afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 656b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 657b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie int getPhonebookPermissionChoice() { 658ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee int permission = mDevice.getPhonebookAccessPermission(); 659ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (permission == BluetoothDevice.ACCESS_ALLOWED) { 660ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return ACCESS_ALLOWED; 661ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } else if (permission == BluetoothDevice.ACCESS_REJECTED) { 662ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return ACCESS_REJECTED; 663ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 664ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return ACCESS_UNKNOWN; 665b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 666b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 667b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie void setPhonebookPermissionChoice(int permissionChoice) { 668ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee int permission = BluetoothDevice.ACCESS_UNKNOWN; 669ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (permissionChoice == ACCESS_ALLOWED) { 670ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee permission = BluetoothDevice.ACCESS_ALLOWED; 671ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } else if (permissionChoice == ACCESS_REJECTED) { 672ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee permission = BluetoothDevice.ACCESS_REJECTED; 673b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 674ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mDevice.setPhonebookAccessPermission(permission); 675b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 676b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 677ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee // Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth 678ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee // app's shared preferences). 679ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee private void migratePhonebookPermissionChoice() { 680ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee SharedPreferences preferences = mContext.getSharedPreferences( 681ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee "bluetooth_phonebook_permission", Context.MODE_PRIVATE); 682ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (!preferences.contains(mDevice.getAddress())) { 683ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return; 684ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 685ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee 686ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (mDevice.getPhonebookAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) { 687ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee int oldPermission = preferences.getInt(mDevice.getAddress(), ACCESS_UNKNOWN); 688ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (oldPermission == ACCESS_ALLOWED) { 689ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 690ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } else if (oldPermission == ACCESS_REJECTED) { 691ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); 692ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 693ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 694ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee 695ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee SharedPreferences.Editor editor = preferences.edit(); 696ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee editor.remove(mDevice.getAddress()); 697ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee editor.commit(); 6985b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } 6995b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 7005b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie int getMessagePermissionChoice() { 701ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee int permission = mDevice.getMessageAccessPermission(); 702ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (permission == BluetoothDevice.ACCESS_ALLOWED) { 703ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return ACCESS_ALLOWED; 704ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } else if (permission == BluetoothDevice.ACCESS_REJECTED) { 705ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return ACCESS_REJECTED; 706ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 707ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return ACCESS_UNKNOWN; 7085b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } 7095b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 7105b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie void setMessagePermissionChoice(int permissionChoice) { 711ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee int permission = BluetoothDevice.ACCESS_UNKNOWN; 712ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (permissionChoice == ACCESS_ALLOWED) { 713ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee permission = BluetoothDevice.ACCESS_ALLOWED; 714ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } else if (permissionChoice == ACCESS_REJECTED) { 715ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee permission = BluetoothDevice.ACCESS_REJECTED; 7163fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu } 717ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mDevice.setMessageAccessPermission(permission); 718ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 7199998639a657825babd2514fd9af9726c068544c8Zhihai Xu 720ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee // Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth 721ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee // app's shared preferences). 722ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee private void migrateMessagePermissionChoice() { 723ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee SharedPreferences preferences = mContext.getSharedPreferences( 724ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee "bluetooth_message_permission", Context.MODE_PRIVATE); 725ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (!preferences.contains(mDevice.getAddress())) { 726ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return; 727ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 7289998639a657825babd2514fd9af9726c068544c8Zhihai Xu 729ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (mDevice.getMessageAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) { 730ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee int oldPermission = preferences.getInt(mDevice.getAddress(), ACCESS_UNKNOWN); 731ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (oldPermission == ACCESS_ALLOWED) { 732ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 733ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } else if (oldPermission == ACCESS_REJECTED) { 734ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_REJECTED); 735ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 7365b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } 737ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee 738ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee SharedPreferences.Editor editor = preferences.edit(); 739ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee editor.remove(mDevice.getAddress()); 7405b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie editor.commit(); 7415b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } 7425b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 743ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee /** 744ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee * @return Whether this rejection should persist. 745ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee */ 746ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee boolean checkAndIncreaseMessageRejectionCount() { 747ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (mMessageRejectionCount < MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST) { 748ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mMessageRejectionCount++; 749ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee saveMessageRejectionCount(); 750ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee } 751ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee return mMessageRejectionCount >= MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST; 752b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 753b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 754ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee private void fetchMessageRejectionCount() { 755ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee SharedPreferences preference = mContext.getSharedPreferences( 756ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee MESSAGE_REJECTION_COUNT_PREFS_NAME, Context.MODE_PRIVATE); 757ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee mMessageRejectionCount = preference.getInt(mDevice.getAddress(), 0); 7581083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 7591083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu 760ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee private void saveMessageRejectionCount() { 761ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee SharedPreferences.Editor editor = mContext.getSharedPreferences( 762ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee MESSAGE_REJECTION_COUNT_PREFS_NAME, Context.MODE_PRIVATE).edit(); 763ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee if (mMessageRejectionCount == 0) { 7641083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu editor.remove(mDevice.getAddress()); 7651083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } else { 766ac8b5b7fd6b6774d22d39bb9a4becca1908915c7Edward Jee editor.putInt(mDevice.getAddress(), mMessageRejectionCount); 7671083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 7681083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu editor.commit(); 7691083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 770afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project} 771