CachedBluetoothDevice.java revision 1083b4726ba915261034612ae9b757d67ed19fcb
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 711083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu private int mPhonebookRejectedTimes; 723fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu 731083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu private int mMessageRejectedTimes; 745b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 75436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Collection<Callback> mCallbacks = new ArrayList<Callback>(); 76afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 775b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie // Following constants indicate the user's choices of Phone book/message access settings 78b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User hasn't made any choice or settings app has wiped out the memory 795b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie final static int ACCESS_UNKNOWN = 0; 80b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User has accepted the connection and let Settings app remember the decision 815b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie final static int ACCESS_ALLOWED = 1; 82b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie // User has rejected the connection and let Settings app remember the decision 835b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie final static int ACCESS_REJECTED = 2; 845b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 853fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu // how many times did User reject the connection to make the rejected persist. 863fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu final static int PERSIST_REJECTED_TIMES_LIMIT = 2; 87b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 88b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private final static String PHONEBOOK_PREFS_NAME = "bluetooth_phonebook_permission"; 895b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie private final static String MESSAGE_PREFS_NAME = "bluetooth_message_permission"; 901083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu private final static String PHONEBOOK_REJECT_TIMES = "bluetooth_phonebook_reject"; 911083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu private final static String MESSAGE_REJECT_TIMES = "bluetooth_message_reject"; 92b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 93afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 94afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * When we connect to multiple profiles, we only want to display a single 95afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * error even if they all fail. This tracks that state. 96afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 97afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean mIsConnectingErrorPossible; 98afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 992aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /** 100eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan * Last time a bt profile auto-connect was attempted. 101eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan * If an ACTION_UUID intent comes in within 1022aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * MAX_UUID_DELAY_FOR_AUTO_CONNECT milliseconds, we will try auto-connect 1032aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * again with the new UUIDs 1042aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 105eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan private long mConnectAttempted; 1062aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 107eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan // See mConnectAttempted 1082aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000; 1092aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 110dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby /** Auto-connect after pairing only if locally initiated. */ 111dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby private boolean mConnectAfterPairing; 11284905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh 113e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project /** 114f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * Describes the current device and profile for logging. 11584905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh * 116f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * @param profile Profile to describe 117f907e0bb891eca4d498871a1cc862117a462a076Adam Powell * @return Description of the device and profile 118e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project */ 119436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private String describe(LocalBluetoothProfile profile) { 120f907e0bb891eca4d498871a1cc862117a462a076Adam Powell StringBuilder sb = new StringBuilder(); 121e79f990490de49b39097433707c2bae6d8238330Jake Hamby sb.append("Address:").append(mDevice); 122f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (profile != null) { 123436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby sb.append(" Profile:").append(profile); 124097ed6c671ed733c0967acc32e017020ede4575bMichael Chan } 125e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 126f907e0bb891eca4d498871a1cc862117a462a076Adam Powell return sb.toString(); 127f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 12884905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh 129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) { 130436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "onProfileStateChanged: profile " + profile + 132f907e0bb891eca4d498871a1cc862117a462a076Adam Powell " newProfileState " + newProfileState); 1336c97742c88303c65e68fe08257a7ccf841f03866Michael Chan } 1347951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF) 1357951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta { 1367951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta if (Utils.D) Log.d(TAG, " BT Turninig Off...Profile conn state change ignored..."); 1377951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta return; 1387951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } 13950e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.put(profile, newProfileState); 140436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (newProfileState == BluetoothProfile.STATE_CONNECTED) { 141f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (!mProfiles.contains(profile)) { 142c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mRemovedProfiles.remove(profile); 143f907e0bb891eca4d498871a1cc862117a462a076Adam Powell mProfiles.add(profile); 144c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby if (profile instanceof PanProfile && 145c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby ((PanProfile) profile).isLocalRoleNap(mDevice)) { 146c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // Device doesn't support NAP, so remove PanProfile on disconnect 147c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mLocalNapRoleConnected = true; 148c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 149e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 1505d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz if (profile instanceof MapProfile) { 1515d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz profile.setPreferred(mDevice, true); 1525d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz refresh(); 1535d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz } 1545d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz } else if (profile instanceof MapProfile && 1555d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz newProfileState == BluetoothProfile.STATE_DISCONNECTED) { 1565d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz if (mProfiles.contains(profile)) { 1575d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz mRemovedProfiles.add(profile); 1585d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz mProfiles.remove(profile); 1595d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz } 1605d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz profile.setPreferred(mDevice, false); 1615d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz refresh(); 162c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (mLocalNapRoleConnected && profile instanceof PanProfile && 163c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby ((PanProfile) profile).isLocalRoleNap(mDevice) && 164c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby newProfileState == BluetoothProfile.STATE_DISCONNECTED) { 165c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby Log.d(TAG, "Removing PanProfile from device after NAP disconnect"); 166c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mProfiles.remove(profile); 167c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mRemovedProfiles.add(profile); 168c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mLocalNapRoleConnected = false; 169e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 170e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project } 171e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project 172b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie CachedBluetoothDevice(Context context, 173b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie LocalBluetoothAdapter adapter, 174b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie LocalBluetoothProfileManager profileManager, 175b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie BluetoothDevice device) { 176b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mContext = context; 177436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = adapter; 178436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager = profileManager; 179d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mDevice = device; 18050e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState = new HashMap<LocalBluetoothProfile, Integer>(); 181afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fillData(); 182afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 183afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 184436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void disconnect() { 185436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 186afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project disconnect(profile); 187afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 1880654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta // Disconnect PBAP server in case its connected 1890654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta // This is to ensure all the profiles are disconnected as some CK/Hs do not 1900654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta // disconnect PBAP connection when HF connection is brought down 1910654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta PbapServerProfile PbapProfile = mProfileManager.getPbapProfile(); 1920654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta if (PbapProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED) 1930654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta { 1940654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta PbapProfile.disconnect(mDevice); 1950654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta } 196afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 197afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 198436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void disconnect(LocalBluetoothProfile profile) { 199436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.disconnect(mDevice)) { 200436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 201d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh Log.d(TAG, "Command sent successfully:DISCONNECT " + describe(profile)); 202f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 203afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 204afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 205afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 206436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void connect(boolean connectAllProfiles) { 207436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 208afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return; 209afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 210afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 211eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mConnectAttempted = SystemClock.elapsedRealtime(); 2124bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connectWithoutResettingTimer(connectAllProfiles); 213eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 214eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan 215436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onBondingDockConnect() { 216582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby // Attempt to connect if UUIDs are available. Otherwise, 217582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby // we will connect when the ACTION_UUID intent arrives. 2184bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connect(false); 219b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh } 220b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh 22139ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby private void connectWithoutResettingTimer(boolean connectAllProfiles) { 222a0d39a39c2f53ebe858685c75c756b51dfac49daJake Hamby // Try to initialize the profiles if they were not. 223436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mProfiles.isEmpty()) { 2246e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // if mProfiles is empty, then do not invoke updateProfiles. This causes a race 2256e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // condition with carkits during pairing, wherein RemoteDevice.UUIDs have been updated 2266e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // from bluetooth stack but ACTION.uuid is not sent yet. 2276e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // Eventually ACTION.uuid will be received which shall trigger the connection of the 2286e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // various profiles 2296e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // If UUIDs are not available yet, connect will be happen 2306e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy // upon arrival of the ACTION_UUID intent. 2316e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy Log.d(TAG, "No profiles. Maybe we will connect later"); 2326e4060212e537bdcb69b21c2ba814c23cd393d42Kausik Sinnaswamy return; 2332aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 2342aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 235afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 236afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 237afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 238eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan int preferredProfiles = 0; 239436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 24039ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) { 241436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.isPreferred(mDevice)) { 242b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan ++preferredProfiles; 243436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 244b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan } 245afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 246afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 247eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles); 248afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 249eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (preferredProfiles == 0) { 250436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectAutoConnectableProfiles(); 251afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 252afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 253afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 254436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void connectAutoConnectableProfiles() { 255436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 256436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 257436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 258afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 259afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 260afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 261436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 26239ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (profile.isAutoConnectable()) { 263436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profile.setPreferred(mDevice, true); 264436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 265b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan } 266afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 267afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 268afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 269436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 270436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Connect this device to the specified profile. 271436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 272436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param profile the profile to use with the remote device 273436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 274436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void connectProfile(LocalBluetoothProfile profile) { 275eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mConnectAttempted = SystemClock.elapsedRealtime(); 276afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Reset the only-show-one-error-dialog tracking variable 277afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mIsConnectingErrorPossible = true; 278436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectInt(profile); 279f457e613d5d91322e0c967fb801899d55e3db9e5Syed Ibrahim M // Refresh the UI based on profile.connect() call 280f457e613d5d91322e0c967fb801899d55e3db9e5Syed Ibrahim M refresh(); 281afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 282afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 2832ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji synchronized void connectInt(LocalBluetoothProfile profile) { 284436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!ensurePaired()) { 285436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 286436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 287436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.connect(mDevice)) { 288436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 289d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile)); 290afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 291436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 292afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 293436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName); 294afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 295afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 296afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private boolean ensurePaired() { 29716cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly if (getBondState() == BluetoothDevice.BOND_NONE) { 298436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby startPairing(); 299afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return false; 300afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } else { 301afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 302afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 303afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 304afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 305436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean startPairing() { 306afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Pairing is unreliable while scanning, so cancel discovery 307436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mLocalAdapter.isDiscovering()) { 308436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter.cancelDiscovery(); 309afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 310afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 311d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if (!mDevice.createBond()) { 312436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 313afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 314dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby 315dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = true; // auto-connect after pairing 316436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 317afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 318afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 319ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby /** 320ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby * Return true if user initiated pairing on this device. The message text is 321ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby * slightly different for local vs. remote initiated pairing dialogs. 322ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby */ 323ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby boolean isUserInitiatedPairing() { 324ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby return mConnectAfterPairing; 325ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby } 326ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby 327436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unpair() { 32896b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan int state = getBondState(); 329afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 33096b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan if (state == BluetoothDevice.BOND_BONDING) { 331d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mDevice.cancelBondProcess(); 33296b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan } 33396b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan 33496b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan if (state != BluetoothDevice.BOND_NONE) { 335436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby final BluetoothDevice dev = mDevice; 336f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (dev != null) { 337f907e0bb891eca4d498871a1cc862117a462a076Adam Powell final boolean successful = dev.removeBond(); 338f907e0bb891eca4d498871a1cc862117a462a076Adam Powell if (successful) { 339436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (Utils.D) { 340f907e0bb891eca4d498871a1cc862117a462a076Adam Powell Log.d(TAG, "Command sent successfully:REMOVE_BOND " + describe(null)); 341f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 342436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if (Utils.V) { 343f907e0bb891eca4d498871a1cc862117a462a076Adam Powell Log.v(TAG, "Framework rejected command immediately:REMOVE_BOND " + 344f907e0bb891eca4d498871a1cc862117a462a076Adam Powell describe(null)); 345f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 346f907e0bb891eca4d498871a1cc862117a462a076Adam Powell } 347afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 348afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 349afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 35050e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int getProfileConnectionState(LocalBluetoothProfile profile) { 35150e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh if (mProfileConnectionState == null || 35250e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.get(profile) == null) { 35350e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh // If cache is empty make the binder call to get the state 35450e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int state = profile.getConnectionStatus(mDevice); 35550e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh mProfileConnectionState.put(profile, state); 35650e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh } 35750e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh return mProfileConnectionState.get(profile); 35850e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh } 35950e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh 3607951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta public void clearProfileConnectionState () 3617951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta { 3627951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta if (Utils.D) { 3637951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta Log.d(TAG," Clearing all connection state for dev:" + mDevice.getName()); 3647951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } 3657951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta for (LocalBluetoothProfile profile :getProfiles()) { 3667951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta mProfileConnectionState.put(profile, BluetoothProfile.STATE_DISCONNECTED); 3677951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } 3687951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta } 3697951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta 370436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // TODO: do any of these need to run async on a background thread? 371afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fillData() { 372afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchName(); 373afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchBtClass(); 3742aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan updateProfiles(); 375b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie fetchPhonebookPermissionChoice(); 3765b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie fetchMessagePermissionChoice(); 3771083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu fetchPhonebookRejectTimes(); 3781083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu fetchMessageRejectTimes(); 379afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 380afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mVisible = false; 381afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 382afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 383afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 384436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice getDevice() { 385d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice; 386afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 387afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 388436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby String getName() { 389afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return mName; 390afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 391afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 392436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setName(String name) { 393d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh if (!mName.equals(name)) { 394d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh if (TextUtils.isEmpty(name)) { 395c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby // TODO: use friendly name for unknown device (bug 1181856) 396d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mName = mDevice.getAddress(); 397d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } else { 398d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh mName = name; 3992036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie mDevice.setAlias(name); 400d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 401d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh dispatchAttributesChanged(); 402d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 403d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 404d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh 405436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refreshName() { 406afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchName(); 407afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 408afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 409afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 410afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fetchName() { 4112036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie mName = mDevice.getAliasName(); 412afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 413afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (TextUtils.isEmpty(mName)) { 414d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mName = mDevice.getAddress(); 415436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) Log.d(TAG, "Device has no name (yet), use address: " + mName); 416afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 417afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 418afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 419436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refresh() { 420afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 421afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 422afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 423436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isVisible() { 424afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return mVisible; 425afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 426afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 427afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project void setVisible(boolean visible) { 428afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (mVisible != visible) { 429afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mVisible = visible; 430afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 431afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 432afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 433afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 434436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int getBondState() { 435d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.getBondState(); 436afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 437afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 438afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project void setRssi(short rssi) { 439afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (mRssi != rssi) { 440afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mRssi = rssi; 441afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 442afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 443afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 444afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 445afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 446afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Checks whether we are connected to this device (any profile counts). 447afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 448afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * @return Whether it is connected. 449afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 450436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isConnected() { 451436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 45250e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 453436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTED) { 454afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 455afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 456afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 457afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 458afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return false; 459afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 460afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 461436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isConnectedProfile(LocalBluetoothProfile profile) { 46250e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 463436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return status == BluetoothProfile.STATE_CONNECTED; 464c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby 465c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby } 466c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby 467436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isBusy() { 468436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 46950e0b0cf87f724d25ada10353867f14ebbf644aaJaikumar Ganesh int status = getProfileConnectionState(profile); 470436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTING 471436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby || status == BluetoothProfile.STATE_DISCONNECTING) { 472afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project return true; 473afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 474afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 475436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return getBondState() == BluetoothDevice.BOND_BONDING; 476cde015b3d424b0d83030f11432ad0a0589014bd5Jake Hamby } 477cde015b3d424b0d83030f11432ad0a0589014bd5Jake Hamby 478afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 479afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Fetches a new value for the cached BT class. 480afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 481afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void fetchBtClass() { 482d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly mBtClass = mDevice.getBluetoothClass(); 4832aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 4842aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4852aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private boolean updateProfiles() { 4862aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan ParcelUuid[] uuids = mDevice.getUuids(); 4872aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (uuids == null) return false; 4882aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 489436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ParcelUuid[] localUuids = mLocalAdapter.getUuids(); 490498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh if (localUuids == null) return false; 491498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh 4926bce91bb9b14f82089f6ac90ca06f63a3aa3045cSyed Ibrahim M mProfileManager.updateProfiles(uuids, localUuids, mProfiles, mRemovedProfiles, mLocalNapRoleConnected); 4932aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4942aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan if (DEBUG) { 4952036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie Log.e(TAG, "updating profiles for " + mDevice.getAliasName()); 4962aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan BluetoothClass bluetoothClass = mDevice.getBluetoothClass(); 4972aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 4988c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString()); 4998c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh Log.v(TAG, "UUID:"); 500436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (ParcelUuid uuid : uuids) { 501436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.v(TAG, " " + uuid); 5022aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 503b20dd917e2d29045225985baa980a2a8e22e10fcNick Pelly } 5042aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan return true; 505afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 506afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 507afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 508afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Refreshes the UI for the BT class, including fetching the latest value 509afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * for the class. 510afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 511436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void refreshBtClass() { 512afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project fetchBtClass(); 513afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project dispatchAttributesChanged(); 514afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 515afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 5162aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /** 5172aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * Refreshes the UI when framework alerts us of a UUID change. 5182aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 519436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onUuidChanged() { 5202aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan updateProfiles(); 5212aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 522eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (DEBUG) { 523eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan Log.e(TAG, "onUuidChanged: Time since last connect" 524eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan + (SystemClock.elapsedRealtime() - mConnectAttempted)); 525eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 5262aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 5272aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan /* 5282aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * If a connect was attempted earlier without any UUID, we will do the 5292aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan * connect now. 5302aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan */ 531436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!mProfiles.isEmpty() 532eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan && (mConnectAttempted + MAX_UUID_DELAY_FOR_AUTO_CONNECT) > SystemClock 5332aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan .elapsedRealtime()) { 53439ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby connectWithoutResettingTimer(false); 5352aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 5362aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan dispatchAttributesChanged(); 5372aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan } 5382aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 539436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onBondingStateChanged(int bondState) { 540eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan if (bondState == BluetoothDevice.BOND_NONE) { 541eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan mProfiles.clear(); 542dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = false; // cancel auto-connect 5435b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie setPhonebookPermissionChoice(ACCESS_UNKNOWN); 5445b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie setMessagePermissionChoice(ACCESS_UNKNOWN); 5451083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu mPhonebookRejectedTimes = 0; 5461083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu savePhonebookRejectTimes(); 5471083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu mMessageRejectedTimes = 0; 5481083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu saveMessageRejectTimes(); 549eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 5501308453b16c2ca85a456bd4bb7f3c71c916bd83eMichael Chan 551eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan refresh(); 552dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby 553dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby if (bondState == BluetoothDevice.BOND_BONDED) { 554dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby if (mDevice.isBluetoothDock()) { 555dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby onBondingDockConnect(); 556dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } else if (mConnectAfterPairing) { 5574bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby connect(false); 558dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } 559dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby mConnectAfterPairing = false; 560dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby } 561eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan } 562eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan 563436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setBtClass(BluetoothClass btClass) { 56416cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly if (btClass != null && mBtClass != btClass) { 565d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh mBtClass = btClass; 566d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh dispatchAttributesChanged(); 567d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 568d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh } 569d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh 570436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothClass getBtClass() { 571436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mBtClass; 572afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 573afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 574436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> getProfiles() { 575436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return Collections.unmodifiableList(mProfiles); 57648e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani } 577afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 578436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> getConnectableProfiles() { 579436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> connectableProfiles = 580436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<LocalBluetoothProfile>(); 581436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : mProfiles) { 58239ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby if (profile.isConnectable()) { 583e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan connectableProfiles.add(profile); 584e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 585e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 586e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan return connectableProfiles; 587e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan } 588e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan 589c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby List<LocalBluetoothProfile> getRemovedProfiles() { 590c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby return mRemovedProfiles; 591c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 592c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 593436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void registerCallback(Callback callback) { 594afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 595afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mCallbacks.add(callback); 596afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 597afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 598afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 599436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unregisterCallback(Callback callback) { 600afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 601afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project mCallbacks.remove(callback); 602afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 603afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 604afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 605afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project private void dispatchAttributesChanged() { 606afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project synchronized (mCallbacks) { 607afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project for (Callback callback : mCallbacks) { 608c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby callback.onDeviceAttributesChanged(); 609afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 610afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 611afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 612afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 613afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 614afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public String toString() { 615d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.toString(); 616afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 617afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 618afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 619afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public boolean equals(Object o) { 620d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly if ((o == null) || !(o instanceof CachedBluetoothDevice)) { 621436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 622afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 623d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.equals(((CachedBluetoothDevice) o).mDevice); 624afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 625afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 626afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 627afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public int hashCode() { 628d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly return mDevice.getAddress().hashCode(); 629afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 630afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 631436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // This comparison uses non-final fields so the sort order may change 632436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // when device attributes change (such as bonding state). Settings 633436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // will completely refresh the device list when this happens. 634d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly public int compareTo(CachedBluetoothDevice another) { 635afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Connected above not connected 636436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int comparison = (another.isConnected() ? 1 : 0) - (isConnected() ? 1 : 0); 637afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 638afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 639afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Paired above not paired 640afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = (another.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0) - 641afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0); 642afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 643afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 644afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Visible above not visible 645afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0); 646afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 647afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 648afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Stronger signal above weaker signal 649afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project comparison = another.mRssi - mRssi; 650afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project if (comparison != 0) return comparison; 651afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 652afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project // Fallback on name 653436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mName.compareTo(another.mName); 654afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 655afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 656afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project public interface Callback { 657c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby void onDeviceAttributesChanged(); 658afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 659b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 660b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie int getPhonebookPermissionChoice() { 661b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie return mPhonebookPermissionChoice; 662b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 663b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 664b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie void setPhonebookPermissionChoice(int permissionChoice) { 6653fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu // if user reject it, only save it when reject exceed limit. 6663fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu if (permissionChoice == ACCESS_REJECTED) { 6673fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu mPhonebookRejectedTimes++; 6681083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu savePhonebookRejectTimes(); 6693fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu if (mPhonebookRejectedTimes < PERSIST_REJECTED_TIMES_LIMIT) { 6703fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu return; 6713fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu } 6723fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu } 6739998639a657825babd2514fd9af9726c068544c8Zhihai Xu 6743fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu mPhonebookPermissionChoice = permissionChoice; 6759998639a657825babd2514fd9af9726c068544c8Zhihai Xu 676b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie SharedPreferences.Editor editor = 677b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME, Context.MODE_PRIVATE).edit(); 6785b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie if (permissionChoice == ACCESS_UNKNOWN) { 679b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie editor.remove(mDevice.getAddress()); 680b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } else { 681b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie editor.putInt(mDevice.getAddress(), permissionChoice); 682b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 683b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie editor.commit(); 684b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 685b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 686b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie private void fetchPhonebookPermissionChoice() { 687b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie SharedPreferences preference = mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME, 688b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie Context.MODE_PRIVATE); 689b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie mPhonebookPermissionChoice = preference.getInt(mDevice.getAddress(), 6905b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie ACCESS_UNKNOWN); 6915b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } 6925b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 6931083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu private void fetchPhonebookRejectTimes() { 6941083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu SharedPreferences preference = mContext.getSharedPreferences(PHONEBOOK_REJECT_TIMES, 6951083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu Context.MODE_PRIVATE); 6961083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu mPhonebookRejectedTimes = preference.getInt(mDevice.getAddress(), 0); 6971083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 6981083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu 6991083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu private void savePhonebookRejectTimes() { 7001083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu SharedPreferences.Editor editor = 7011083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu mContext.getSharedPreferences(PHONEBOOK_REJECT_TIMES, 7021083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu Context.MODE_PRIVATE).edit(); 7031083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu if (mPhonebookRejectedTimes == 0) { 7041083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu editor.remove(mDevice.getAddress()); 7051083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } else { 7061083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu editor.putInt(mDevice.getAddress(), mPhonebookRejectedTimes); 7071083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 7081083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu editor.commit(); 7091083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 7105b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 7115b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie int getMessagePermissionChoice() { 7125b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie return mMessagePermissionChoice; 7135b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } 7145b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 7155b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie void setMessagePermissionChoice(int permissionChoice) { 7163fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu // if user reject it, only save it when reject exceed limit. 7173fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu if (permissionChoice == ACCESS_REJECTED) { 7183fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu mMessageRejectedTimes++; 7191083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu saveMessageRejectTimes(); 7203fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu if (mMessageRejectedTimes < PERSIST_REJECTED_TIMES_LIMIT) { 7213fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu return; 7223fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu } 7233fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu } 7249998639a657825babd2514fd9af9726c068544c8Zhihai Xu 7253fd5e2839fba6afc18d99006d61c063c2ed4f121Zhihai Xu mMessagePermissionChoice = permissionChoice; 7269998639a657825babd2514fd9af9726c068544c8Zhihai Xu 7275b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie SharedPreferences.Editor editor = 7285b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie mContext.getSharedPreferences(MESSAGE_PREFS_NAME, Context.MODE_PRIVATE).edit(); 7295b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie if (permissionChoice == ACCESS_UNKNOWN) { 7305b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie editor.remove(mDevice.getAddress()); 7315b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } else { 7325b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie editor.putInt(mDevice.getAddress(), permissionChoice); 7335b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } 7345b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie editor.commit(); 7355b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie } 7365b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie 7375b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie private void fetchMessagePermissionChoice() { 7385b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie SharedPreferences preference = mContext.getSharedPreferences(MESSAGE_PREFS_NAME, 7395b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie Context.MODE_PRIVATE); 7405b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie mMessagePermissionChoice = preference.getInt(mDevice.getAddress(), 7415b5b1e39ddd28af55cf5dd4a9ca9bf29828a66a6Matthew Xie ACCESS_UNKNOWN); 742b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie } 743b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie 7441083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu private void fetchMessageRejectTimes() { 7451083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu SharedPreferences preference = mContext.getSharedPreferences(MESSAGE_REJECT_TIMES, 7461083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu Context.MODE_PRIVATE); 7471083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu mMessageRejectedTimes = preference.getInt(mDevice.getAddress(), 0); 7481083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 7491083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu 7501083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu private void saveMessageRejectTimes() { 7511083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu SharedPreferences.Editor editor = 7521083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu mContext.getSharedPreferences(MESSAGE_REJECT_TIMES, Context.MODE_PRIVATE).edit(); 7531083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu if (mMessageRejectedTimes == 0) { 7541083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu editor.remove(mDevice.getAddress()); 7551083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } else { 7561083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu editor.putInt(mDevice.getAddress(), mMessageRejectedTimes); 7571083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 7581083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu editor.commit(); 7591083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu } 7601083b4726ba915261034612ae9b757d67ed19fcbZhihai Xu 761afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project} 762